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_Manipulator.hxx>
19 #include <AIS_Point.hxx>
20 #include <AIS_RubberBand.hxx>
21 #include <Aspect_Grid.hxx>
22 #include <Geom_CartesianPoint.hxx>
23 #include <Message.hxx>
24 #include <Message_Messenger.hxx>
25 #include <gp_Quaternion.hxx>
26 #include <V3d_View.hxx>
28 // =======================================================================
29 // function : AIS_ViewController
31 // =======================================================================
32 AIS_ViewController::AIS_ViewController()
33 : myLastEventsTime (0.0),
34 myToAskNextFrame (false),
35 myMinCamDistance (1.0),
36 myRotationMode (AIS_RotationMode_BndBoxActive),
37 myNavigationMode (AIS_NavigationMode_Orbit),
40 myToShowPanAnchorPoint (true),
41 myToShowRotateCenter (true),
42 myToLockOrbitZUp (false),
43 myToInvertPitch (false),
44 myToAllowTouchZRotation(false),
45 myToAllowRotation (true),
46 myToAllowPanning (true),
47 myToAllowZooming (true),
48 myToAllowZFocus (true),
49 myToAllowHighlight (true),
50 myToAllowDragging (true),
51 myToStickToRayOnZoom (true),
52 myToStickToRayOnRotation (true),
54 myWalkSpeedAbsolute (1.5f),
55 myWalkSpeedRelative (0.1f),
59 myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
60 myPrevMoveTo (-1, -1),
61 myHasHlrOnBeforeRotation (false),
63 myMouseClickThreshold (3.0),
64 myMouseDoubleClickInt (0.4),
65 myScrollZoomRatio (15.0f),
66 myMouseActiveGesture (AIS_MouseGesture_NONE),
67 myMouseActiveIdleRotation (false),
68 myMouseClickCounter (0),
69 myMousePressed (Aspect_VKeyMouse_NONE),
70 myMouseModifiers (Aspect_VKeyFlags_NONE),
71 myMouseSingleButton (-1),
72 myMouseStopDragOnUnclick (false),
74 myTouchToleranceScale (1.0f),
75 myTouchRotationThresholdPx (6.0f),
76 myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)),
77 myTouchPanThresholdPx (4.0f),
78 myTouchZoomThresholdPx (6.0f),
79 myTouchZoomRatio (0.13f),
82 myUpdateStartPointPan (true),
83 myUpdateStartPointRot (true),
84 myUpdateStartPointZRot (true),
86 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
90 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
91 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
92 myAnchorPointPrs1->SetMutable (true);
94 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
95 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
96 myAnchorPointPrs2->SetMutable (true);
98 myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
99 myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD);
100 myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
101 myRubberBand->SetDisplayMode (0);
102 myRubberBand->SetMutable (true);
104 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
105 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom);
106 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan);
107 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle);
109 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
110 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
112 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
113 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
116 // =======================================================================
117 // function : ~AIS_ViewController
119 // =======================================================================
120 AIS_ViewController::~AIS_ViewController()
125 // =======================================================================
126 // function : ResetViewInput
128 // =======================================================================
129 void AIS_ViewController::ResetViewInput()
132 myMousePressed = Aspect_VKeyMouse_NONE;
133 myMouseModifiers = Aspect_VKeyFlags_NONE;
134 myMouseSingleButton = -1;
135 myUI.Dragging.ToAbort = true;
136 myMouseActiveGesture = AIS_MouseGesture_NONE;
137 myMouseClickTimer.Stop();
138 myMouseClickCounter = 0;
141 // =======================================================================
142 // function : FlushViewEvents
144 // =======================================================================
145 void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
146 const Handle(V3d_View)& theView,
147 Standard_Boolean theToHandle)
149 flushBuffers (theCtx, theView);
150 flushGestures(theCtx, theView);
153 HandleViewEvents (theCtx, theView);
157 // =======================================================================
158 // function : flushBuffers
160 // =======================================================================
161 void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
162 const Handle(V3d_View)& )
164 myToAskNextFrame = false;
166 myGL.IsNewGesture = myUI.IsNewGesture;
167 myUI.IsNewGesture = false;
169 myGL.ZoomActions.Clear();
170 myGL.ZoomActions.Append (myUI.ZoomActions);
171 myUI.ZoomActions.Clear();
173 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
174 myUI.Orientation.ToFitAll = false;
175 if (myUI.Orientation.ToSetViewOrient)
177 myUI.Orientation.ToSetViewOrient = false;
178 myGL.Orientation.ToSetViewOrient = true;
179 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
182 if (myUI.MoveTo.ToHilight)
184 myUI.MoveTo.ToHilight = false;
185 myGL.MoveTo.ToHilight = true;
186 myGL.MoveTo.Point = myUI.MoveTo.Point;
190 myGL.Selection.Tool = myUI.Selection.Tool;
191 myGL.Selection.IsXOR = myUI.Selection.IsXOR;
192 myGL.Selection.Points = myUI.Selection.Points;
193 myUI.Selection.IsXOR = false;
194 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
196 myUI.Selection.Points.Clear();
200 if (myUI.Selection.ToApplyTool)
202 myGL.Selection.ToApplyTool = true;
203 myUI.Selection.ToApplyTool = false;
204 myUI.Selection.Points.Clear();
207 if (myUI.Panning.ToStart)
209 myUI.Panning.ToStart = false;
210 myGL.Panning.ToStart = true;
211 myGL.Panning.PointStart = myUI.Panning.PointStart;
214 if (myUI.Panning.ToPan)
216 myUI.Panning.ToPan = false;
217 myGL.Panning.ToPan = true;
218 myGL.Panning.Delta = myUI.Panning.Delta;
221 if (myUI.Dragging.ToAbort)
223 myUI.Dragging.ToAbort = false;
224 myGL.Dragging.ToAbort = true;
226 else if (myUI.Dragging.ToStop)
228 myUI.Dragging.ToStop = false;
229 myGL.Dragging.ToStop = true;
231 else if (myUI.Dragging.ToStart)
233 myUI.Dragging.ToStart = false;
234 myGL.Dragging.ToStart = true;
235 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
237 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
239 if (myUI.OrbitRotation.ToStart)
241 myUI.OrbitRotation.ToStart = false;
242 myGL.OrbitRotation.ToStart = true;
243 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
246 if (myUI.OrbitRotation.ToRotate)
248 myUI.OrbitRotation.ToRotate = false;
249 myGL.OrbitRotation.ToRotate = true;
250 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
253 if (myUI.ViewRotation.ToStart)
255 myUI.ViewRotation.ToStart = false;
256 myGL.ViewRotation.ToStart = true;
257 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
260 if (myUI.ViewRotation.ToRotate)
262 myUI.ViewRotation.ToRotate = false;
263 myGL.ViewRotation.ToRotate = true;
264 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
267 if (myUI.ZRotate.ToRotate)
269 myGL.ZRotate = myUI.ZRotate;
270 myUI.ZRotate.ToRotate = false;
274 // =======================================================================
275 // function : flushGestures
277 // =======================================================================
278 void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
279 const Handle(V3d_View)& theView)
281 const Standard_Real aTolScale = myTouchToleranceScale;
282 const Standard_Integer aTouchNb = myTouchPoints.Extent();
283 if (myNbTouchesLast != aTouchNb)
285 myNbTouchesLast = aTouchNb;
286 myGL.IsNewGesture = true;
288 if (aTouchNb == 1) // touch
290 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
291 if (myUpdateStartPointRot)
293 // skip rotation if have active dragged object
294 if (myNavigationMode == AIS_NavigationMode_Orbit)
296 myGL.OrbitRotation.ToStart = true;
297 myGL.OrbitRotation.PointStart = myStartRotCoord;
301 myGL.ViewRotation.ToStart = true;
302 myGL.ViewRotation.PointStart = myStartRotCoord;
305 myUpdateStartPointRot = false;
306 theView->Invalidate();
310 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
311 ? aTolScale * myTouchRotationThresholdPx
313 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
315 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
316 if (myNavigationMode == AIS_NavigationMode_Orbit)
318 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
319 myGL.OrbitRotation.ToRotate = true;
320 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
321 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
325 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
326 myGL.ViewRotation.ToRotate = true;
327 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
328 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
331 aTouch.From = aTouch.To;
334 else if (aTouchNb == 2) // pinch
336 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
337 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
338 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
339 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
341 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
342 (aFrom[0].y() + aFrom[1].y()) / 2.0);
344 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
345 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
347 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
348 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
350 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
351 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
353 Standard_Real aDeltaSize = anEndSize - aStartSize;
355 bool anIsClearDev = false;
357 if (myToAllowTouchZRotation)
359 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
360 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
362 Standard_Real A2 = aTo[0].y() - aTo[1].y();
363 Standard_Real B2 = aTo[1].x() - aTo[0].x();
365 Standard_Real aRotAngle = 0.0;
367 Standard_Real aDenomenator = A1*A2 + B1*B2;
368 if (aDenomenator <= Precision::Confusion())
374 Standard_Real aNumerator = A1*B2 - A2*B1;
375 aRotAngle = ATan (aNumerator / aDenomenator);
378 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
380 myGL.ZRotate.ToRotate = true;
381 myGL.ZRotate.Angle = aRotAngle;
386 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
389 aDeltaSize *= Standard_Real(myTouchZoomRatio);
390 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
391 myGL.ZoomActions.Append (aParams);
395 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
396 ? aTolScale * myTouchPanThresholdPx
398 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
401 if (myUpdateStartPointPan)
403 myGL.Panning.ToStart = true;
404 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
405 myUpdateStartPointPan = false;
406 theView->Invalidate();
409 myGL.Panning.ToPan = true;
410 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
411 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
417 aFirstTouch.From = aFirstTouch.To;
418 aLastTouch .From = aLastTouch.To;
423 // =======================================================================
424 // function : UpdateViewOrientation
426 // =======================================================================
427 void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
430 myUI.Orientation.ToFitAll = theToFitAll;
431 myUI.Orientation.ToSetViewOrient = true;
432 myUI.Orientation.ViewOrient = theOrientation;
435 // =======================================================================
436 // function : SelectInViewer
438 // =======================================================================
439 void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
442 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
444 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
445 myUI.Selection.Points.Clear();
448 myUI.Selection.IsXOR = theIsXOR;
449 myUI.Selection.Points.Append (thePnt);
452 // =======================================================================
453 // function : SelectInViewer
455 // =======================================================================
456 void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
459 myUI.Selection.IsXOR = theIsXOR;
460 myUI.Selection.Points = thePnts;
461 myUI.Selection.ToApplyTool = true;
462 if (thePnts.Length() == 1)
464 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
466 else if (thePnts.Length() == 2)
468 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
472 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
476 // =======================================================================
477 // function : UpdateRubberBand
479 // =======================================================================
480 void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
481 const Graphic3d_Vec2i& thePntTo,
484 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
485 myUI.Selection.IsXOR = theIsXOR;
486 myUI.Selection.Points.Clear();
487 myUI.Selection.Points.Append (thePntFrom);
488 myUI.Selection.Points.Append (thePntTo);
491 // =======================================================================
492 // function : UpdatePolySelection
494 // =======================================================================
495 void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
498 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
500 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
501 myUI.Selection.Points.Clear();
504 if (myUI.Selection.Points.IsEmpty())
506 myUI.Selection.Points.Append (thePnt);
509 && myUI.Selection.Points.Last() != thePnt)
511 myUI.Selection.Points.Append (thePnt);
515 myUI.Selection.Points.ChangeLast() = thePnt;
519 // =======================================================================
520 // function : UpdateZoom
522 // =======================================================================
523 bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
525 if (!myUI.ZoomActions.IsEmpty())
527 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
529 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
534 myUI.ZoomActions.Append (theDelta);
538 // =======================================================================
539 // function : UpdateZRotation
541 // =======================================================================
542 bool AIS_ViewController::UpdateZRotation (double theAngle)
544 if (!ToAllowTouchZRotation())
549 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
550 ? myUI.ZRotate.Angle + theAngle
552 if (myUI.ZRotate.ToRotate)
556 myUI.ZRotate.ToRotate = true;
560 // =======================================================================
561 // function : UpdateMouseScroll
563 // =======================================================================
564 bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
566 Aspect_ScrollDelta aDelta = theDelta;
567 aDelta.Delta *= myScrollZoomRatio;
568 return UpdateZoom (aDelta);
571 // =======================================================================
572 // function : UpdateMouseClick
574 // =======================================================================
575 bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
576 Aspect_VKeyMouse theButton,
577 Aspect_VKeyFlags theModifiers,
578 bool theIsDoubleClick)
580 (void )theIsDoubleClick;
581 if (theButton == Aspect_VKeyMouse_LeftButton)
583 SelectInViewer (thePoint, (theModifiers & Aspect_VKeyFlags_SHIFT) != 0);
589 // =======================================================================
590 // function : UpdateMouseButtons
592 // =======================================================================
593 bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
594 Aspect_VKeyMouse theButtons,
595 Aspect_VKeyFlags theModifiers,
598 bool toUpdateView = false;
599 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
600 if (theButtons == Aspect_VKeyMouse_NONE
601 && myMouseSingleButton > 0)
603 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
604 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
606 ++myMouseClickCounter;
607 const bool isDoubleClick = myMouseClickCounter == 2
608 && myMouseClickTimer.IsStarted()
609 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
611 myMouseClickTimer.Stop();
612 myMouseClickTimer.Reset();
613 myMouseClickTimer.Start();
616 myMouseClickCounter = 0;
618 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
622 myMouseClickTimer.Stop();
623 myMouseClickCounter = 0;
624 myMouseStopDragOnUnclick = false;
625 myUI.Dragging.ToStop = true;
628 myMouseSingleButton = -1;
630 else if (theButtons == Aspect_VKeyMouse_NONE)
632 myMouseSingleButton = -1;
633 if (myMouseStopDragOnUnclick)
635 myMouseStopDragOnUnclick = false;
636 myUI.Dragging.ToStop = true;
640 else if (myMouseSingleButton == -1)
642 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
644 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
646 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
648 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
650 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
652 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
656 myMouseSingleButton = 0;
658 if (myMouseSingleButton != 0)
660 if (myMouseClickCounter == 1)
662 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
663 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
665 myMouseClickTimer.Stop();
666 myMouseClickCounter = 0;
669 myMousePressPoint = thePoint;
674 myMouseSingleButton = 0;
676 myUI.Dragging.ToAbort = true;
680 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
681 myMouseModifiers = theModifiers;
682 myMousePressed = theButtons;
684 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
686 myMouseActiveIdleRotation = false;
687 myMouseActiveGesture = AIS_MouseGesture_NONE;
690 myMousePressPoint = thePoint;
691 myMouseProgressPoint = myMousePressPoint;
694 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
696 switch (myMouseActiveGesture)
698 case AIS_MouseGesture_RotateView:
699 case AIS_MouseGesture_RotateOrbit:
701 if (myToAllowRotation)
703 myUpdateStartPointRot = true;
707 myMouseActiveGesture = AIS_MouseGesture_NONE;
711 case AIS_MouseGesture_Pan:
713 if (myToAllowPanning)
715 myUpdateStartPointPan = true;
719 myMouseActiveGesture = AIS_MouseGesture_NONE;
723 case AIS_MouseGesture_Zoom:
725 if (!myToAllowZooming)
727 myMouseActiveGesture = AIS_MouseGesture_NONE;
731 case AIS_MouseGesture_SelectRectangle:
735 case AIS_MouseGesture_SelectLasso:
737 UpdatePolySelection (thePoint, true);
740 case AIS_MouseGesture_NONE:
747 if (theButtons == Aspect_VKeyMouse_LeftButton
748 && theModifiers == Aspect_VKeyFlags_NONE
749 && myToAllowDragging)
751 myUI.Dragging.ToStart = true;
752 myUI.Dragging.PointStart = thePoint;
756 if (aPrevGesture != myMouseActiveGesture)
758 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
759 || aPrevGesture == AIS_MouseGesture_SelectLasso)
761 myUI.Selection.ToApplyTool = true;
764 myUI.IsNewGesture = true;
770 // =======================================================================
771 // function : UpdateMousePosition
773 // =======================================================================
774 bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
775 Aspect_VKeyMouse theButtons,
776 Aspect_VKeyFlags theModifiers,
779 myMousePositionLast = thePoint;
780 if (myMouseSingleButton > 0)
782 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
783 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
784 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
786 myMouseClickTimer.Stop();
787 myMouseClickCounter = 0;
788 myMouseSingleButton = -1;
789 myMouseStopDragOnUnclick = true;
793 bool toUpdateView = false;
794 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
796 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
798 if (!myMouseActiveIdleRotation
799 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
801 myMouseActiveIdleRotation = true;
802 myMouseActiveGesture = AIS_MouseGesture_RotateView;
803 myMousePressPoint = thePoint;
804 myMouseProgressPoint = thePoint;
805 myUpdateStartPointRot = false;
806 myUI.ViewRotation.ToStart = true;
807 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
808 myUI.ViewRotation.ToRotate = false;
809 aDelta.SetValues (0, 0);
814 if (myMouseActiveIdleRotation
815 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
817 myMouseActiveGesture = AIS_MouseGesture_NONE;
819 myMouseActiveIdleRotation = false;
822 if (myMouseModifiers != theModifiers
823 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
828 switch (myMouseActiveGesture)
830 case AIS_MouseGesture_SelectRectangle:
832 UpdateRubberBand (myMousePressPoint, thePoint);
836 case AIS_MouseGesture_SelectLasso:
838 UpdatePolySelection (thePoint, true);
842 case AIS_MouseGesture_RotateOrbit:
843 case AIS_MouseGesture_RotateView:
845 if (!myToAllowRotation)
849 if (myUpdateStartPointRot)
851 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
853 myUI.OrbitRotation.ToStart = true;
854 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
858 myUI.ViewRotation.ToStart = true;
859 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
861 myUpdateStartPointRot = false;
864 const double aRotTol = theIsEmulated
865 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
867 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
869 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
870 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
871 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
873 myUI.OrbitRotation.ToRotate = true;
874 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
875 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
879 myUI.ViewRotation.ToRotate = true;
880 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
881 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
883 myUI.Dragging.PointTo = thePoint;
885 myMouseProgressPoint = thePoint;
890 case AIS_MouseGesture_Zoom:
892 if (!myToAllowZooming)
896 const double aZoomTol = theIsEmulated
897 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
899 if (double (Abs (aDelta.x())) > aZoomTol)
901 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
905 myMouseProgressPoint = thePoint;
909 case AIS_MouseGesture_Pan:
911 if (!myToAllowPanning)
915 const double aPanTol = theIsEmulated
916 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
918 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
920 if (myUpdateStartPointPan)
922 myUI.Panning.ToStart = true;
923 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
924 myUpdateStartPointPan = false;
927 aDelta.y() = -aDelta.y();
928 myMouseProgressPoint = thePoint;
929 if (myUI.Panning.ToPan)
931 myUI.Panning.Delta += aDelta;
935 myUI.Panning.ToPan = true;
936 myUI.Panning.Delta = aDelta;
948 if (theButtons == Aspect_VKeyMouse_NONE
949 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
952 && myToAllowHighlight)
954 myUI.MoveTo.ToHilight = true;
955 myUI.MoveTo.Point = thePoint;
961 // =======================================================================
962 // function : AddTouchPoint
964 // =======================================================================
965 void AIS_ViewController::AddTouchPoint (Standard_Size theId,
966 const Graphic3d_Vec2d& thePnt,
967 Standard_Boolean theClearBefore)
969 myUI.MoveTo.ToHilight = false;
972 RemoveTouchPoint ((Standard_Size )-1);
975 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
976 if (myTouchPoints.Extent() == 1)
978 myUpdateStartPointRot = true;
979 myStartRotCoord = thePnt;
980 if (myToAllowDragging)
982 myUI.Dragging.ToStart = true;
983 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
986 else if (myTouchPoints.Extent() == 2)
988 myUI.Dragging.ToAbort = true;
990 myUpdateStartPointPan = true;
991 myStartPanCoord = thePnt;
993 myUI.IsNewGesture = true;
996 // =======================================================================
997 // function : RemoveTouchPoint
999 // =======================================================================
1000 bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
1001 Standard_Boolean theClearSelectPnts)
1003 if (theId == (Standard_Size )-1)
1005 myTouchPoints.Clear (false);
1009 const Standard_Integer anOldExtent = myTouchPoints.Extent();
1010 myTouchPoints.RemoveKey (theId);
1011 if (myTouchPoints.Extent() == anOldExtent)
1017 if (myTouchPoints.Extent() == 1)
1019 // avoid incorrect transition from pinch to one finger
1020 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1021 aFirstTouch.To = aFirstTouch.From;
1023 myStartRotCoord = aFirstTouch.To;
1024 myUpdateStartPointRot = true;
1026 else if (myTouchPoints.Extent() == 2)
1028 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1029 myUpdateStartPointPan = true;
1031 else if (myTouchPoints.IsEmpty())
1033 if (theClearSelectPnts)
1035 myUI.Selection.ToApplyTool = true;
1038 myUI.Dragging.ToStop = true;
1040 myUI.IsNewGesture = true;
1044 // =======================================================================
1045 // function : UpdateTouchPoint
1047 // =======================================================================
1048 void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1049 const Graphic3d_Vec2d& thePnt)
1051 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1053 aTouch->To = thePnt;
1057 AddTouchPoint (theId, thePnt);
1061 // =======================================================================
1062 // function : SetNavigationMode
1064 // =======================================================================
1065 void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1067 myNavigationMode = theMode;
1070 myUI.OrbitRotation.ToStart = false;
1071 myUI.OrbitRotation.ToRotate = false;
1072 myUI.ViewRotation.ToStart = false;
1073 myUI.ViewRotation.ToRotate = false;
1076 // =======================================================================
1077 // function : KeyDown
1079 // =======================================================================
1080 void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1084 myKeys.KeyDown (theKey, theTime, thePressure);
1087 // =======================================================================
1090 // =======================================================================
1091 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1094 myKeys.KeyUp (theKey, theTime);
1097 // =======================================================================
1098 // function : KeyFromAxis
1100 // =======================================================================
1101 void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1102 Aspect_VKey thePositive,
1106 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1109 // =======================================================================
1110 // function : FetchNavigationKeys
1112 // =======================================================================
1113 AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1114 Standard_Real theRunRatio)
1116 AIS_WalkDelta aWalk;
1119 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1120 updateEventsTime (aPrevEventTime, aNewEventTime);
1122 double aDuration = 0.0, aPressure = 1.0;
1123 if (Abs (myThrustSpeed) > gp::Resolution())
1127 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1130 myToAskNextFrame = true;
1134 myHasThrust = false;
1137 aWalk.SetRunning (theRunRatio > 1.0
1138 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1139 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1141 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1142 aWalk.SetJumping (true);
1144 if (!aWalk.IsJumping()
1145 && theCrouchRatio < 1.0
1146 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1148 aWalk.SetRunning (false);
1149 aWalk.SetCrouching (true);
1152 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1153 const double aRunRatio = aWalk.IsRunning()
1155 : aWalk.IsCrouching()
1158 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1160 double aProgress = Abs (Min (aMaxDuration, aDuration));
1161 aProgress *= aRunRatio;
1162 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1163 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1164 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1166 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1168 double aProgress = Abs (Min (aMaxDuration, aDuration));
1169 aProgress *= aRunRatio;
1170 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1171 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1172 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1174 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1176 double aProgress = Abs (Min (aMaxDuration, aDuration));
1177 aProgress *= aRunRatio;
1178 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1179 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1180 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1182 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1184 double aProgress = Abs (Min (aMaxDuration, aDuration));
1185 aProgress *= aRunRatio;
1186 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1187 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1188 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1190 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1192 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1193 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1194 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1195 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1197 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1199 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1200 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1201 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1202 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1204 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1206 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1207 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1208 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1209 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1211 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1213 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1214 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1215 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1216 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1218 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1220 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1221 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1222 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1223 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1225 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1227 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1228 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1229 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1230 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1232 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1234 double aProgress = Abs (Min (aMaxDuration, aDuration));
1235 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1236 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1237 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1239 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1241 double aProgress = Abs (Min (aMaxDuration, aDuration));
1242 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1243 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1244 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1249 // =======================================================================
1250 // function : AbortViewAnimation
1252 // =======================================================================
1253 void AIS_ViewController::AbortViewAnimation()
1255 if (!myViewAnimation.IsNull()
1256 && !myViewAnimation->IsStopped())
1258 myViewAnimation->Stop();
1259 myViewAnimation->SetView (Handle(V3d_View)());
1263 // =======================================================================
1264 // function : handlePanning
1266 // =======================================================================
1267 void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1269 if (!myGL.Panning.ToPan
1270 || !myToAllowPanning)
1275 AbortViewAnimation();
1277 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1278 if (aCam->IsOrthographic()
1279 || !hasPanningAnchorPoint())
1281 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1282 theView->Invalidate();
1286 Graphic3d_Vec2i aWinSize;
1287 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1289 const gp_Dir& aDir = aCam->Direction();
1290 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1291 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1292 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1293 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1294 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1296 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1298 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1299 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1300 aPanTrsf.SetTranslation (aCameraPan);
1301 aCam->Transform (aPanTrsf);
1302 theView->Invalidate();
1305 // =======================================================================
1306 // function : handleZRotate
1308 // =======================================================================
1309 void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1311 if (!myGL.ZRotate.ToRotate
1312 || !myToAllowRotation)
1317 AbortViewAnimation();
1319 Graphic3d_Vec2i aViewPort;
1320 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1321 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1322 0.5 * aViewPort.y());
1323 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1324 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1325 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1326 theView->Invalidate();
1329 // =======================================================================
1330 // function : handleZoom
1332 // =======================================================================
1333 void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1334 const Aspect_ScrollDelta& theParams,
1335 const gp_Pnt* thePnt)
1337 if (!myToAllowZooming)
1342 AbortViewAnimation();
1344 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1347 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1348 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1351 if (!theParams.HasPoint())
1353 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1354 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1355 theView->SetZoom (aCoeff, true);
1356 theView->Invalidate();
1360 // integer delta is too rough for small smooth increments
1361 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1362 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1364 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1365 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1371 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1373 // ensure that zoom will not be too small or too big
1374 double aCoef = aDZoom;
1375 if (aViewDims.x() < aCoef * Precision::Confusion())
1377 aCoef = aViewDims.x() / Precision::Confusion();
1379 else if (aViewDims.x() > aCoef * 1e12)
1381 aCoef = aViewDims.x() / 1e12;
1383 if (aViewDims.y() < aCoef * Precision::Confusion())
1385 aCoef = aViewDims.y() / Precision::Confusion();
1387 else if (aViewDims.y() > aCoef * 1e12)
1389 aCoef = aViewDims.y() / 1e12;
1392 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1393 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1394 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1395 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1396 aCam->SetScale (aCam->Scale() / aCoef);
1398 const gp_Dir& aDir = aCam->Direction();
1399 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1401 // pan back to the point
1402 aDxy = aZoomAtPointXYv - aDxy;
1405 // zoom at 3D point with perspective projection
1406 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1407 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1408 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1410 // view dimensions at 3D point
1411 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1413 Graphic3d_Vec2i aWinSize;
1414 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1415 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
1416 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
1417 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
1418 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
1421 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1423 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1424 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1425 aPanTrsf.SetTranslation (aCameraPan);
1426 aCam->Transform (aPanTrsf);
1427 theView->Invalidate();
1430 // =======================================================================
1431 // function : handleZFocusScroll
1433 // =======================================================================
1434 void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1435 const Aspect_ScrollDelta& theParams)
1437 if (!myToAllowZFocus
1438 || !theView->Camera()->IsStereo())
1443 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1447 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1452 // =======================================================================
1453 // function : handleOrbitRotation
1455 // =======================================================================
1456 void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1457 const gp_Pnt& thePnt,
1460 if (!myToAllowRotation)
1465 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1466 if (myGL.OrbitRotation.ToStart)
1468 // default alternatives
1469 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1470 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1472 myRotatePnt3d = thePnt;
1473 myCamStartOpUp = aCam->Up();
1474 myCamStartOpDir = aCam->Direction();
1475 myCamStartOpEye = aCam->Eye();
1476 myCamStartOpCenter = aCam->Center();
1479 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1480 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1481 const gp_Quaternion aRot = aTrsf.GetRotation();
1482 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1485 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1486 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1488 theView->Invalidate();
1491 if (!myGL.OrbitRotation.ToRotate)
1496 AbortViewAnimation();
1499 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1500 Graphic3d_Vec2i aWinXY;
1501 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1502 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1503 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1504 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1505 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1506 const double aRoll = 0.0;
1509 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1511 aTrsfRot.SetRotation (aRot);
1513 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1514 aCam->SetUp (aNewUp);
1515 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1516 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1518 aCam->OrthogonalizeUp();
1522 // default alternatives
1523 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1524 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1526 // restore previous camera state
1527 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1528 aCam->SetUp (myCamStartOpUp);
1529 aCam->SetDirectionFromEye (myCamStartOpDir);
1531 Graphic3d_Vec2d aWinXY;
1532 theView->Size (aWinXY.x(), aWinXY.y());
1533 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1534 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1536 const double THE_2PI = M_PI * 2.0;
1537 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1538 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1540 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1541 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1542 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1543 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1545 // rotate camera around 3 initial axes
1546 gp_Dir aCamDir (aCam->Direction().Reversed());
1547 gp_Dir aCamUp (aCam->Up());
1548 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1550 gp_Trsf aRot[2], aTrsf;
1551 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1552 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1553 aTrsf.Multiply (aRot[0]);
1554 aTrsf.Multiply (aRot[1]);
1556 aCam->Transform (aTrsf);
1559 theView->Invalidate();
1562 // =======================================================================
1563 // function : handleViewRotation
1565 // =======================================================================
1566 void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1568 double thePitchExtra,
1570 bool theToRestartOnIncrement)
1572 if (!myToAllowRotation)
1577 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1578 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1579 || Abs (thePitchExtra) > gp::Resolution()
1580 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1582 && theToRestartOnIncrement)
1584 myGL.ViewRotation.ToStart = true;
1585 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1587 if (myGL.ViewRotation.ToStart)
1590 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1591 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1592 const gp_Quaternion aRot = aTrsf.GetRotation();
1593 double aRollDummy = 0.0;
1594 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1598 myRotateStartYawPitchRoll[0] += theYawExtra;
1599 myRotateStartYawPitchRoll[1] += thePitchExtra;
1600 myRotateStartYawPitchRoll[2] = theRoll;
1601 myGL.ViewRotation.ToRotate = true;
1604 if (!myGL.ViewRotation.ToRotate)
1609 AbortViewAnimation();
1611 Graphic3d_Vec2i aWinXY;
1612 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1613 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1614 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1615 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1616 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1618 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1620 aTrsfRot.SetRotation (aRot);
1622 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1623 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
1624 aCam->SetUp (aNewUp);
1625 aCam->SetDirectionFromEye (aNewDir);
1626 aCam->OrthogonalizeUp();
1627 theView->Invalidate();
1630 // =======================================================================
1631 // function : PickPoint
1633 // =======================================================================
1634 bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1635 const Handle(AIS_InteractiveContext)& theCtx,
1636 const Handle(V3d_View)& theView,
1637 const Graphic3d_Vec2i& theCursor,
1638 bool theToStickToPickRay)
1640 ResetPreviousMoveTo();
1642 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1643 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1644 if (aSelector->NbPicked() < 1)
1649 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1650 if (theToStickToPickRay
1651 && !Precision::IsInfinite (aPicked.Depth))
1653 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1657 thePnt = aSelector->PickedPoint (1);
1659 return !Precision::IsInfinite (thePnt.X())
1660 && !Precision::IsInfinite (thePnt.Y())
1661 && !Precision::IsInfinite (thePnt.Z());
1664 // =======================================================================
1665 // function : GravityPoint
1667 // =======================================================================
1668 gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1669 const Handle(V3d_View)& theView)
1671 switch (myRotationMode)
1673 case AIS_RotationMode_PickLast:
1674 case AIS_RotationMode_PickCenter:
1676 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1677 if (myRotationMode == AIS_RotationMode_PickCenter)
1679 Graphic3d_Vec2i aViewPort;
1680 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1681 aCursor = aViewPort / 2;
1685 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
1691 case AIS_RotationMode_CameraAt:
1693 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1694 return aCam->Center();
1696 case AIS_RotationMode_BndBoxScene:
1698 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1699 if (!aBndBox.IsVoid())
1701 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1705 case AIS_RotationMode_BndBoxActive:
1709 return theCtx ->GravityPoint (theView);
1712 // =======================================================================
1713 // function : handleCameraActions
1715 // =======================================================================
1716 void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
1717 const Handle(V3d_View)& theView,
1718 const AIS_WalkDelta& theWalk)
1720 // apply view actions
1721 if (myGL.Orientation.ToSetViewOrient)
1723 theView->SetProj (myGL.Orientation.ViewOrient);
1724 myGL.Orientation.ToFitAll = true;
1728 if (myGL.Orientation.ToFitAll)
1730 const double aFitMargin = 0.01;
1731 theView->FitAll (aFitMargin, false);
1732 theView->Invalidate();
1733 myGL.Orientation.ToFitAll = false;
1736 if (myGL.IsNewGesture)
1738 if (myAnchorPointPrs1->HasInteractiveContext())
1740 theCtx->Remove (myAnchorPointPrs1, false);
1741 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
1743 theView->Invalidate();
1747 theView->InvalidateImmediate();
1750 if (myAnchorPointPrs2->HasInteractiveContext())
1752 theCtx->Remove (myAnchorPointPrs2, false);
1753 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
1755 theView->Invalidate();
1759 theView->InvalidateImmediate();
1763 if (myHasHlrOnBeforeRotation)
1765 myHasHlrOnBeforeRotation = false;
1766 theView->SetComputedMode (true);
1767 theView->Invalidate();
1771 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
1773 if (myGL.Panning.ToStart
1774 && myToAllowPanning)
1776 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
1777 if (!theView->Camera()->IsOrthographic())
1779 bool toStickToRay = false;
1780 if (myGL.Panning.PointStart.x() >= 0
1781 && myGL.Panning.PointStart.y() >= 0)
1783 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
1785 if (Precision::IsInfinite (aPanPnt.X()))
1787 Graphic3d_Vec2i aWinSize;
1788 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1789 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
1791 if (!Precision::IsInfinite (aPanPnt.X())
1792 && myToShowPanAnchorPoint)
1795 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
1796 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1799 setPanningAnchorPoint (aPanPnt);
1802 if (myToShowPanAnchorPoint
1803 && hasPanningAnchorPoint()
1804 && myGL.Panning.ToPan
1805 && !myGL.IsNewGesture
1806 && !myAnchorPointPrs2->HasInteractiveContext())
1808 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1811 handlePanning (theView);
1812 handleZRotate (theView);
1815 if ((myNavigationMode == AIS_NavigationMode_Orbit
1816 || myGL.OrbitRotation.ToStart
1817 || myGL.OrbitRotation.ToRotate)
1818 && myToAllowRotation)
1820 if (myGL.OrbitRotation.ToStart
1821 && !myHasHlrOnBeforeRotation)
1823 myHasHlrOnBeforeRotation = theView->ComputedMode();
1824 if (myHasHlrOnBeforeRotation)
1826 theView->SetComputedMode (false);
1831 if (myGL.OrbitRotation.ToStart)
1833 aGravPnt = GravityPoint (theCtx, theView);
1834 if (myToShowRotateCenter)
1837 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
1838 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
1839 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1843 if (myToShowRotateCenter
1844 && myGL.OrbitRotation.ToRotate
1845 && !myGL.IsNewGesture
1846 && !myAnchorPointPrs1->HasInteractiveContext())
1848 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
1849 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1851 handleOrbitRotation (theView, aGravPnt,
1852 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
1855 if ((myNavigationMode != AIS_NavigationMode_Orbit
1856 || myGL.ViewRotation.ToStart
1857 || myGL.ViewRotation.ToRotate)
1858 && myToAllowRotation)
1860 if (myGL.ViewRotation.ToStart
1861 && !myHasHlrOnBeforeRotation)
1863 myHasHlrOnBeforeRotation = theView->ComputedMode();
1864 if (myHasHlrOnBeforeRotation)
1866 theView->SetComputedMode (false);
1871 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
1872 && !myToLockOrbitZUp)
1874 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
1875 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
1876 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
1882 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
1883 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
1886 if (!myGL.ZoomActions.IsEmpty())
1888 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
1890 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
1892 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
1893 && theView->Camera()->IsStereo())
1895 handleZFocusScroll (theView, aZoomParams);
1899 if (!myToAllowZooming)
1904 if (!theView->Camera()->IsOrthographic())
1907 if (aZoomParams.HasPoint()
1908 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
1910 handleZoom (theView, aZoomParams, &aPnt);
1914 Graphic3d_Vec2i aWinSize;
1915 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1916 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom))
1918 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
1919 handleZoom (theView, aZoomParams, &aPnt);
1923 handleZoom (theView, aZoomParams, NULL);
1925 myGL.ZoomActions.Clear();
1929 // =======================================================================
1930 // function : OnSelectionChanged
1932 // =======================================================================
1933 void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
1934 const Handle(V3d_View)& )
1939 // =======================================================================
1940 // function : OnObjectDragged
1942 // =======================================================================
1943 void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
1944 const Handle(V3d_View)& theView,
1945 AIS_DragAction theAction)
1949 case AIS_DragAction_Start:
1951 myDragObject.Nullify();
1952 if (!theCtx->HasDetected())
1957 Handle(AIS_InteractiveObject) aPrs = theCtx->DetectedInteractive();
1958 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (aPrs))
1960 if (aManip->HasActiveMode())
1962 myDragObject = aManip;
1963 aManip->StartTransform (myGL.Dragging.PointStart.x(), myGL.Dragging.PointStart.y(), theView);
1968 case AIS_DragAction_Update:
1970 if (myDragObject.IsNull())
1975 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
1977 theCtx->SetSelectedState (aGlobOwner, true);
1979 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1981 aManip->Transform (myGL.Dragging.PointTo.x(), myGL.Dragging.PointTo.y(), theView);
1983 theView->Invalidate();
1986 case AIS_DragAction_Abort:
1988 if (myDragObject.IsNull())
1993 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
1994 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
1996 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1998 aManip->StopTransform (false);
2000 Standard_FALLTHROUGH
2002 case AIS_DragAction_Stop:
2004 if (myDragObject.IsNull())
2009 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2011 theCtx->SetSelectedState (aGlobOwner, false);
2014 theView->Invalidate();
2015 myDragObject.Nullify();
2021 // =======================================================================
2022 // function : contextLazyMoveTo
2024 // =======================================================================
2025 void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2026 const Handle(V3d_View)& theView,
2027 const Graphic3d_Vec2i& thePnt)
2029 if (myPrevMoveTo == thePnt)
2034 myPrevMoveTo = thePnt;
2036 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2037 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2038 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2040 if (theView->Viewer()->Grid()->IsActive()
2041 && theView->Viewer()->GridEcho())
2043 if (aNewPicked.IsNull())
2045 Graphic3d_Vec3d aPnt3d;
2046 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2047 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2048 theView->InvalidateImmediate();
2052 theView->Viewer()->HideGridEcho (theView);
2053 theView->InvalidateImmediate();
2057 if (aLastPicked != aNewPicked
2058 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2060 // dynamic highlight affects all Views
2061 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2063 const Handle(V3d_View)& aView = aViewIter.Value();
2064 aView->InvalidateImmediate();
2069 // =======================================================================
2070 // function : handleSelectionPick
2072 // =======================================================================
2073 void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2074 const Handle(V3d_View)& theView)
2076 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2077 && !myGL.Selection.Points.IsEmpty())
2079 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2081 const bool hadPrevMoveTo = HasPreviousMoveTo();
2082 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2085 ResetPreviousMoveTo();
2088 if (myGL.Selection.IsXOR)
2090 theCtx->ShiftSelect (false);
2094 theCtx->Select (false);
2097 // selection affects all Views
2098 theView->Viewer()->Invalidate();
2100 OnSelectionChanged (theCtx, theView);
2103 myGL.Selection.Points.Clear();
2107 // =======================================================================
2108 // function : handleSelectionPoly
2110 // =======================================================================
2111 void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2112 const Handle(V3d_View)& theView)
2114 // rubber-band & window polygon selection
2115 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2116 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon)
2118 if (!myGL.Selection.Points.IsEmpty())
2120 myRubberBand->ClearPoints();
2121 myRubberBand->SetToUpdate();
2123 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand;
2126 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2127 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2131 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2132 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2134 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2135 if (aPntNew != aPrev)
2138 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2143 myRubberBand->SetPolygonClosed (anIsRubber);
2146 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2148 catch (const Standard_Failure& theEx)
2150 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2151 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString(), Message_Warning);
2152 myRubberBand->ClearPoints();
2154 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2156 theView->Invalidate();
2160 theView->InvalidateImmediate();
2163 else if (!myRubberBand.IsNull()
2164 && myRubberBand->HasInteractiveContext())
2166 theCtx->Remove (myRubberBand, false);
2167 myRubberBand->ClearPoints();
2171 if (myGL.Selection.ToApplyTool)
2173 myGL.Selection.ToApplyTool = false;
2174 if (theCtx->IsDisplayed (myRubberBand))
2176 theCtx->Remove (myRubberBand, false);
2178 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2179 if (aPoints.Size() == 4
2180 && aPoints.Value (1).x() == aPoints.Value (2).x()
2181 && aPoints.Value (3).x() == aPoints.Value (4).x()
2182 && aPoints.Value (1).y() == aPoints.Value (4).y()
2183 && aPoints.Value (2).y() == aPoints.Value (3).y())
2185 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2186 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
2187 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2188 if (myGL.Selection.IsXOR)
2190 theCtx->ShiftSelect (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2191 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2196 theCtx->Select (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2197 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2200 theCtx->MainSelector()->AllowOverlapDetection (false);
2202 else if (aPoints.Length() >= 3)
2204 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2205 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2206 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2207 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2209 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2210 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2213 if (myGL.Selection.IsXOR)
2215 theCtx->ShiftSelect (aPolyline, theView, false);
2219 theCtx->Select (aPolyline, theView, false);
2221 theCtx->MainSelector()->AllowOverlapDetection (false);
2225 // selection affects all Views
2226 theView->Viewer()->Invalidate();
2228 myRubberBand->ClearPoints();
2229 OnSelectionChanged (theCtx, theView);
2234 // =======================================================================
2235 // function : handleDynamicHighlight
2237 // =======================================================================
2238 void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2239 const Handle(V3d_View)& theView)
2241 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2242 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2244 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2245 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2246 && !HasPreviousMoveTo())
2248 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2249 ResetPreviousMoveTo();
2250 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2251 theCtx->ClearDetected();
2253 else if (myToAllowHighlight)
2255 if (myPrevMoveTo != aMoveToPnt
2256 || myGL.OrbitRotation.ToRotate
2257 || myGL.ViewRotation.ToRotate
2258 || theView->IsInvalidated())
2260 ResetPreviousMoveTo();
2261 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2263 if (myGL.Dragging.ToStart)
2265 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2269 myGL.MoveTo.ToHilight = false;
2272 if (!myDragObject.IsNull())
2274 if (myGL.Dragging.ToAbort)
2276 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2277 myGL.OrbitRotation.ToRotate = false;
2278 myGL.ViewRotation .ToRotate = false;
2280 else if (myGL.Dragging.ToStop)
2282 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2283 myGL.OrbitRotation.ToRotate = false;
2284 myGL.ViewRotation .ToRotate = false;
2286 else if (myGL.OrbitRotation.ToRotate
2287 || myGL.ViewRotation.ToRotate)
2289 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2290 myGL.OrbitRotation.ToRotate = false;
2291 myGL.ViewRotation .ToRotate = false;
2296 // =======================================================================
2297 // function : handleMoveTo
2299 // =======================================================================
2300 void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2301 const Handle(V3d_View)& theView)
2303 handleSelectionPick (theCtx, theView);
2304 handleDynamicHighlight(theCtx, theView);
2305 handleSelectionPoly (theCtx, theView);
2308 // =======================================================================
2309 // function : handleViewRedraw
2311 // =======================================================================
2312 void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2313 const Handle(V3d_View)& theView)
2315 // manage animation state
2316 if (!myViewAnimation.IsNull()
2317 && !myViewAnimation->IsStopped())
2319 myViewAnimation->UpdateTimer();
2320 ResetPreviousMoveTo();
2324 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2326 const Handle(V3d_View)& aView = aViewIter.Value();
2327 if (aView->IsInvalidated()
2328 || myToAskNextFrame)
2330 if (aView->ComputedMode())
2339 else if (aView->IsInvalidatedImmediate())
2341 aView->RedrawImmediate();
2345 if (myToAskNextFrame)
2348 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
2352 // =======================================================================
2353 // function : HandleViewEvents
2355 // =======================================================================
2356 void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
2357 const Handle(V3d_View)& theView)
2359 handleMoveTo (theCtx, theView);
2361 const AIS_WalkDelta aWalk = FetchNavigationKeys (1.0, 1.0);
2362 handleCameraActions (theCtx, theView, aWalk);
2363 handleViewRedraw (theCtx, theView);
2365 // make sure to not process the same events twice
2367 myToAskNextFrame = false;