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),
52 myWalkSpeedAbsolute (1.5f),
53 myWalkSpeedRelative (0.1f),
57 myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
58 myPrevMoveTo (-1, -1),
59 myHasHlrOnBeforeRotation (false),
61 myMouseClickThreshold (3.0),
62 myMouseDoubleClickInt (0.4),
63 myScrollZoomRatio (15.0f),
64 myMouseActiveGesture (AIS_MouseGesture_NONE),
65 myMouseActiveIdleRotation (false),
66 myMouseClickCounter (0),
67 myMousePressed (Aspect_VKeyMouse_NONE),
68 myMouseModifiers (Aspect_VKeyFlags_NONE),
69 myMouseSingleButton (-1),
71 myTouchToleranceScale (1.0f),
72 myTouchRotationThresholdPx (6.0f),
73 myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)),
74 myTouchPanThresholdPx (4.0f),
75 myTouchZoomThresholdPx (6.0f),
76 myTouchZoomRatio (0.13f),
79 myUpdateStartPointPan (true),
80 myUpdateStartPointRot (true),
81 myUpdateStartPointZRot (true),
83 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
87 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
88 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
89 myAnchorPointPrs1->SetMutable (true);
91 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
92 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
93 myAnchorPointPrs2->SetMutable (true);
95 myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
96 myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD);
97 myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
98 myRubberBand->SetDisplayMode (0);
99 myRubberBand->SetMutable (true);
101 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
102 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom);
103 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan);
104 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle);
106 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
107 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
109 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
110 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
113 // =======================================================================
114 // function : ResetViewInput
116 // =======================================================================
117 void AIS_ViewController::ResetViewInput()
120 myMousePressed = Aspect_VKeyMouse_NONE;
121 myMouseModifiers = Aspect_VKeyFlags_NONE;
122 myMouseSingleButton = -1;
123 myUI.Dragging.ToAbort = true;
124 myMouseActiveGesture = AIS_MouseGesture_NONE;
125 myMouseClickTimer.Stop();
126 myMouseClickCounter = 0;
129 // =======================================================================
130 // function : FlushViewEvents
132 // =======================================================================
133 void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
134 const Handle(V3d_View)& theView,
135 Standard_Boolean theToHandle)
137 flushBuffers (theCtx, theView);
138 flushGestures(theCtx, theView);
141 HandleViewEvents (theCtx, theView);
145 // =======================================================================
146 // function : flushBuffers
148 // =======================================================================
149 void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
150 const Handle(V3d_View)& )
152 myToAskNextFrame = false;
154 myGL.IsNewGesture = myUI.IsNewGesture;
155 myUI.IsNewGesture = false;
157 myGL.ZoomActions.Clear();
158 myGL.ZoomActions.Append (myUI.ZoomActions);
159 myUI.ZoomActions.Clear();
161 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
162 myUI.Orientation.ToFitAll = false;
163 if (myUI.Orientation.ToSetViewOrient)
165 myUI.Orientation.ToSetViewOrient = false;
166 myGL.Orientation.ToSetViewOrient = true;
167 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
170 if (myUI.MoveTo.ToHilight)
172 myUI.MoveTo.ToHilight = false;
173 myGL.MoveTo.ToHilight = true;
174 myGL.MoveTo.Point = myUI.MoveTo.Point;
178 myGL.Selection.Tool = myUI.Selection.Tool;
179 myGL.Selection.IsXOR = myUI.Selection.IsXOR;
180 myGL.Selection.Points = myUI.Selection.Points;
181 myUI.Selection.IsXOR = false;
182 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
184 myUI.Selection.Points.Clear();
188 if (myUI.Selection.ToApplyTool)
190 myGL.Selection.ToApplyTool = true;
191 myUI.Selection.ToApplyTool = false;
192 myUI.Selection.Points.Clear();
195 if (myUI.Panning.ToStart)
197 myUI.Panning.ToStart = false;
198 myGL.Panning.ToStart = true;
199 myGL.Panning.PointStart = myUI.Panning.PointStart;
202 if (myUI.Panning.ToPan)
204 myUI.Panning.ToPan = false;
205 myGL.Panning.ToPan = true;
206 myGL.Panning.Delta = myUI.Panning.Delta;
209 if (myUI.Dragging.ToAbort)
211 myUI.Dragging.ToAbort = false;
212 myGL.Dragging.ToAbort = true;
214 else if (myUI.Dragging.ToStop)
216 myUI.Dragging.ToStop = false;
217 myGL.Dragging.ToStop = true;
219 else if (myUI.Dragging.ToStart)
221 myUI.Dragging.ToStart = false;
222 myGL.Dragging.ToStart = true;
223 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
225 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
227 if (myUI.OrbitRotation.ToStart)
229 myUI.OrbitRotation.ToStart = false;
230 myGL.OrbitRotation.ToStart = true;
231 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
234 if (myUI.OrbitRotation.ToRotate)
236 myUI.OrbitRotation.ToRotate = false;
237 myGL.OrbitRotation.ToRotate = true;
238 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
241 if (myUI.ViewRotation.ToStart)
243 myUI.ViewRotation.ToStart = false;
244 myGL.ViewRotation.ToStart = true;
245 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
248 if (myUI.ViewRotation.ToRotate)
250 myUI.ViewRotation.ToRotate = false;
251 myGL.ViewRotation.ToRotate = true;
252 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
255 if (myUI.ZRotate.ToRotate)
257 myGL.ZRotate = myUI.ZRotate;
258 myUI.ZRotate.ToRotate = false;
262 // =======================================================================
263 // function : flushGestures
265 // =======================================================================
266 void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
267 const Handle(V3d_View)& theView)
269 const Standard_Real aTolScale = myTouchToleranceScale;
270 const Standard_Integer aTouchNb = myTouchPoints.Extent();
271 if (myNbTouchesLast != aTouchNb)
273 myNbTouchesLast = aTouchNb;
274 myGL.IsNewGesture = true;
276 if (aTouchNb == 1) // touch
278 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
279 if (myUpdateStartPointRot)
281 // skip rotation if have active dragged object
282 if (myNavigationMode == AIS_NavigationMode_Orbit)
284 myGL.OrbitRotation.ToStart = true;
285 myGL.OrbitRotation.PointStart = myStartRotCoord;
289 myGL.ViewRotation.ToStart = true;
290 myGL.ViewRotation.PointStart = myStartRotCoord;
293 myUpdateStartPointRot = false;
294 theView->Invalidate();
298 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
299 ? aTolScale * myTouchRotationThresholdPx
301 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
303 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
304 if (myNavigationMode == AIS_NavigationMode_Orbit)
306 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
307 myGL.OrbitRotation.ToRotate = true;
308 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
309 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
313 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
314 myGL.ViewRotation.ToRotate = true;
315 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
316 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
319 aTouch.From = aTouch.To;
322 else if (aTouchNb == 2) // pinch
324 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
325 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
326 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
327 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
329 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
330 (aFrom[0].y() + aFrom[1].y()) / 2.0);
332 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
333 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
335 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
336 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
338 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
339 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
341 Standard_Real aDeltaSize = anEndSize - aStartSize;
343 bool anIsClearDev = false;
345 if (myToAllowTouchZRotation)
347 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
348 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
350 Standard_Real A2 = aTo[0].y() - aTo[1].y();
351 Standard_Real B2 = aTo[1].x() - aTo[0].x();
353 Standard_Real aRotAngle = 0.0;
355 Standard_Real aDenomenator = A1*A2 + B1*B2;
356 if (aDenomenator <= Precision::Confusion())
362 Standard_Real aNumerator = A1*B2 - A2*B1;
363 aRotAngle = ATan (aNumerator / aDenomenator);
366 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
368 myGL.ZRotate.ToRotate = true;
369 myGL.ZRotate.Angle = aRotAngle;
374 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
377 aDeltaSize *= Standard_Real(myTouchZoomRatio);
378 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
379 myGL.ZoomActions.Append (aParams);
383 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
384 ? aTolScale * myTouchPanThresholdPx
386 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
389 if (myUpdateStartPointPan)
391 myGL.Panning.ToStart = true;
392 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
393 myUpdateStartPointPan = false;
394 theView->Invalidate();
397 myGL.Panning.ToPan = true;
398 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
399 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
405 aFirstTouch.From = aFirstTouch.To;
406 aLastTouch .From = aLastTouch.To;
411 // =======================================================================
412 // function : UpdateViewOrientation
414 // =======================================================================
415 void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
418 myUI.Orientation.ToFitAll = theToFitAll;
419 myUI.Orientation.ToSetViewOrient = true;
420 myUI.Orientation.ViewOrient = theOrientation;
423 // =======================================================================
424 // function : SelectInViewer
426 // =======================================================================
427 void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
430 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
432 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
433 myUI.Selection.Points.Clear();
436 myUI.Selection.IsXOR = theIsXOR;
437 myUI.Selection.Points.Append (thePnt);
440 // =======================================================================
441 // function : SelectInViewer
443 // =======================================================================
444 void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
447 myUI.Selection.IsXOR = theIsXOR;
448 myUI.Selection.Points = thePnts;
449 myUI.Selection.ToApplyTool = true;
450 if (thePnts.Length() == 1)
452 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
454 else if (thePnts.Length() == 2)
456 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
460 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
464 // =======================================================================
465 // function : UpdateRubberBand
467 // =======================================================================
468 void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
469 const Graphic3d_Vec2i& thePntTo,
472 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
473 myUI.Selection.IsXOR = theIsXOR;
474 myUI.Selection.Points.Clear();
475 myUI.Selection.Points.Append (thePntFrom);
476 myUI.Selection.Points.Append (thePntTo);
479 // =======================================================================
480 // function : UpdatePolySelection
482 // =======================================================================
483 void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
486 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
488 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
489 myUI.Selection.Points.Clear();
492 if (myUI.Selection.Points.IsEmpty())
494 myUI.Selection.Points.Append (thePnt);
497 && myUI.Selection.Points.Last() != thePnt)
499 myUI.Selection.Points.Append (thePnt);
503 myUI.Selection.Points.ChangeLast() = thePnt;
507 // =======================================================================
508 // function : UpdateZoom
510 // =======================================================================
511 bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
513 if (!myUI.ZoomActions.IsEmpty())
515 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
517 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
522 myUI.ZoomActions.Append (theDelta);
526 // =======================================================================
527 // function : UpdateZRotation
529 // =======================================================================
530 bool AIS_ViewController::UpdateZRotation (double theAngle)
532 if (!ToAllowTouchZRotation())
537 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
538 ? myUI.ZRotate.Angle + theAngle
540 if (myUI.ZRotate.ToRotate)
544 myUI.ZRotate.ToRotate = true;
548 // =======================================================================
549 // function : UpdateMouseScroll
551 // =======================================================================
552 bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
554 Aspect_ScrollDelta aDelta = theDelta;
555 aDelta.Delta *= myScrollZoomRatio;
556 return UpdateZoom (aDelta);
559 // =======================================================================
560 // function : UpdateMouseClick
562 // =======================================================================
563 bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
564 Aspect_VKeyMouse theButton,
565 Aspect_VKeyFlags theModifiers,
566 bool theIsDoubleClick)
568 (void )theIsDoubleClick;
569 if (theButton == Aspect_VKeyMouse_LeftButton)
571 SelectInViewer (thePoint, (theModifiers & Aspect_VKeyFlags_SHIFT) != 0);
577 // =======================================================================
578 // function : UpdateMouseButtons
580 // =======================================================================
581 bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
582 Aspect_VKeyMouse theButtons,
583 Aspect_VKeyFlags theModifiers,
586 bool toUpdateView = false;
587 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
588 if (theButtons == Aspect_VKeyMouse_NONE
589 && myMouseSingleButton > 0)
591 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
592 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
594 ++myMouseClickCounter;
595 const bool isDoubleClick = myMouseClickCounter == 2
596 && myMouseClickTimer.IsStarted()
597 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
599 myMouseClickTimer.Stop();
600 myMouseClickTimer.Reset();
601 myMouseClickTimer.Start();
604 myMouseClickCounter = 0;
606 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
610 myMouseClickTimer.Stop();
611 myMouseClickCounter = 0;
612 myUI.Dragging.ToStop = true;
615 myMouseSingleButton = -1;
617 else if (theButtons == Aspect_VKeyMouse_NONE)
619 myMouseSingleButton = -1;
621 else if (myMouseSingleButton == -1)
623 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
625 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
627 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
629 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
631 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
633 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
637 myMouseSingleButton = 0;
639 if (myMouseSingleButton != 0)
641 if (myMouseClickCounter == 1)
643 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
644 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
646 myMouseClickTimer.Stop();
647 myMouseClickCounter = 0;
650 myMousePressPoint = thePoint;
655 myMouseSingleButton = 0;
657 myUI.Dragging.ToAbort = true;
661 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
662 myMouseModifiers = theModifiers;
663 myMousePressed = theButtons;
665 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
667 myMouseActiveIdleRotation = false;
668 myMouseActiveGesture = AIS_MouseGesture_NONE;
671 myMousePressPoint = thePoint;
672 myMouseProgressPoint = myMousePressPoint;
675 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
677 switch (myMouseActiveGesture)
679 case AIS_MouseGesture_RotateView:
680 case AIS_MouseGesture_RotateOrbit:
682 if (myToAllowRotation)
684 myUpdateStartPointRot = true;
688 myMouseActiveGesture = AIS_MouseGesture_NONE;
692 case AIS_MouseGesture_Pan:
694 if (myToAllowPanning)
696 myUpdateStartPointPan = true;
700 myMouseActiveGesture = AIS_MouseGesture_NONE;
704 case AIS_MouseGesture_Zoom:
706 if (!myToAllowZooming)
708 myMouseActiveGesture = AIS_MouseGesture_NONE;
712 case AIS_MouseGesture_SelectRectangle:
716 case AIS_MouseGesture_SelectLasso:
718 UpdatePolySelection (thePoint, true);
721 case AIS_MouseGesture_NONE:
728 if (theButtons == Aspect_VKeyMouse_LeftButton
729 && theModifiers == Aspect_VKeyFlags_NONE
730 && myToAllowDragging)
732 myUI.Dragging.ToStart = true;
733 myUI.Dragging.PointStart = thePoint;
737 if (aPrevGesture != myMouseActiveGesture)
739 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
740 || aPrevGesture == AIS_MouseGesture_SelectLasso)
742 myUI.Selection.ToApplyTool = true;
745 myUI.IsNewGesture = true;
751 // =======================================================================
752 // function : UpdateMousePosition
754 // =======================================================================
755 bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
756 Aspect_VKeyMouse theButtons,
757 Aspect_VKeyFlags theModifiers,
760 myMousePositionLast = thePoint;
761 if (myMouseSingleButton > 0)
763 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
764 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
765 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
767 myMouseClickTimer.Stop();
768 myMouseClickCounter = 0;
769 myMouseSingleButton = -1;
773 bool toUpdateView = false;
774 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
776 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
778 if (!myMouseActiveIdleRotation
779 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
781 myMouseActiveIdleRotation = true;
782 myMouseActiveGesture = AIS_MouseGesture_RotateView;
783 myMousePressPoint = thePoint;
784 myMouseProgressPoint = thePoint;
785 myUpdateStartPointRot = false;
786 myUI.ViewRotation.ToStart = true;
787 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
788 myUI.ViewRotation.ToRotate = false;
789 aDelta.SetValues (0, 0);
794 if (myMouseActiveIdleRotation
795 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
797 myMouseActiveGesture = AIS_MouseGesture_NONE;
799 myMouseActiveIdleRotation = false;
802 if (myMouseModifiers != theModifiers
803 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
808 switch (myMouseActiveGesture)
810 case AIS_MouseGesture_SelectRectangle:
812 UpdateRubberBand (myMousePressPoint, thePoint);
816 case AIS_MouseGesture_SelectLasso:
818 UpdatePolySelection (thePoint, true);
822 case AIS_MouseGesture_RotateOrbit:
823 case AIS_MouseGesture_RotateView:
825 if (!myToAllowRotation)
829 if (myUpdateStartPointRot)
831 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
833 myUI.OrbitRotation.ToStart = true;
834 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
838 myUI.ViewRotation.ToStart = true;
839 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
841 myUpdateStartPointRot = false;
844 const double aRotTol = theIsEmulated
845 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
847 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
849 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
850 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
851 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
853 myUI.OrbitRotation.ToRotate = true;
854 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
855 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
859 myUI.ViewRotation.ToRotate = true;
860 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
861 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
863 myUI.Dragging.PointTo = thePoint;
865 myMouseProgressPoint = thePoint;
870 case AIS_MouseGesture_Zoom:
872 if (!myToAllowZooming)
876 const double aZoomTol = theIsEmulated
877 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
879 if (double (Abs (aDelta.x())) > aZoomTol)
881 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
885 myMouseProgressPoint = thePoint;
889 case AIS_MouseGesture_Pan:
891 if (!myToAllowPanning)
895 const double aPanTol = theIsEmulated
896 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
898 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
900 if (myUpdateStartPointPan)
902 myUI.Panning.ToStart = true;
903 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
904 myUpdateStartPointPan = false;
907 aDelta.y() = -aDelta.y();
908 myMouseProgressPoint = thePoint;
909 if (myUI.Panning.ToPan)
911 myUI.Panning.Delta += aDelta;
915 myUI.Panning.ToPan = true;
916 myUI.Panning.Delta = aDelta;
928 if (theButtons == Aspect_VKeyMouse_NONE
929 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
932 && myToAllowHighlight)
934 myUI.MoveTo.ToHilight = true;
935 myUI.MoveTo.Point = thePoint;
941 // =======================================================================
942 // function : AddTouchPoint
944 // =======================================================================
945 void AIS_ViewController::AddTouchPoint (Standard_Size theId,
946 const Graphic3d_Vec2d& thePnt,
947 Standard_Boolean theClearBefore)
949 myUI.MoveTo.ToHilight = false;
952 RemoveTouchPoint ((Standard_Size )-1);
955 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
956 if (myTouchPoints.Extent() == 1)
958 myUpdateStartPointRot = true;
959 myStartRotCoord = thePnt;
960 if (myToAllowDragging)
962 myUI.Dragging.ToStart = true;
963 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
966 else if (myTouchPoints.Extent() == 2)
968 myUI.Dragging.ToAbort = true;
970 myUpdateStartPointPan = true;
971 myStartPanCoord = thePnt;
973 myUI.IsNewGesture = true;
976 // =======================================================================
977 // function : RemoveTouchPoint
979 // =======================================================================
980 bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
981 Standard_Boolean theClearSelectPnts)
983 if (theId == (Standard_Size )-1)
985 myTouchPoints.Clear (false);
989 const Standard_Integer anOldExtent = myTouchPoints.Extent();
990 myTouchPoints.RemoveKey (theId);
991 if (myTouchPoints.Extent() == anOldExtent)
997 if (myTouchPoints.Extent() == 1)
999 // avoid incorrect transition from pinch to one finger
1000 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1001 aFirstTouch.To = aFirstTouch.From;
1003 myStartRotCoord = aFirstTouch.To;
1004 myUpdateStartPointRot = true;
1006 else if (myTouchPoints.Extent() == 2)
1008 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1009 myUpdateStartPointPan = true;
1011 else if (myTouchPoints.IsEmpty())
1013 if (theClearSelectPnts)
1015 myUI.Selection.ToApplyTool = true;
1018 myUI.Dragging.ToStop = true;
1020 myUI.IsNewGesture = true;
1024 // =======================================================================
1025 // function : UpdateTouchPoint
1027 // =======================================================================
1028 void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1029 const Graphic3d_Vec2d& thePnt)
1031 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1033 aTouch->To = thePnt;
1037 AddTouchPoint (theId, thePnt);
1041 // =======================================================================
1042 // function : SetNavigationMode
1044 // =======================================================================
1045 void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1047 myNavigationMode = theMode;
1050 myUI.OrbitRotation.ToStart = false;
1051 myUI.OrbitRotation.ToRotate = false;
1052 myUI.ViewRotation.ToStart = false;
1053 myUI.ViewRotation.ToRotate = false;
1056 // =======================================================================
1057 // function : KeyDown
1059 // =======================================================================
1060 void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1064 myKeys.KeyDown (theKey, theTime, thePressure);
1067 // =======================================================================
1070 // =======================================================================
1071 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1074 myKeys.KeyUp (theKey, theTime);
1077 // =======================================================================
1078 // function : KeyFromAxis
1080 // =======================================================================
1081 void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1082 Aspect_VKey thePositive,
1086 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1089 // =======================================================================
1090 // function : FetchNavigationKeys
1092 // =======================================================================
1093 AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1094 Standard_Real theRunRatio)
1096 AIS_WalkDelta aWalk;
1099 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1100 updateEventsTime (aPrevEventTime, aNewEventTime);
1102 double aDuration = 0.0, aPressure = 1.0;
1103 if (Abs (myThrustSpeed) > gp::Resolution())
1107 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1110 myToAskNextFrame = true;
1114 myHasThrust = false;
1117 aWalk.SetRunning (theRunRatio > 1.0
1118 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1119 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1121 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1122 aWalk.SetJumping (true);
1124 if (!aWalk.IsJumping()
1125 && theCrouchRatio < 1.0
1126 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1128 aWalk.SetRunning (false);
1129 aWalk.SetCrouching (true);
1132 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1133 const double aRunRatio = aWalk.IsRunning()
1135 : aWalk.IsCrouching()
1138 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1140 double aProgress = Abs (Min (aMaxDuration, aDuration));
1141 aProgress *= aRunRatio;
1142 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1143 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1144 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1146 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1148 double aProgress = Abs (Min (aMaxDuration, aDuration));
1149 aProgress *= aRunRatio;
1150 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1151 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1152 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1154 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1156 double aProgress = Abs (Min (aMaxDuration, aDuration));
1157 aProgress *= aRunRatio;
1158 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1159 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1160 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1162 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1164 double aProgress = Abs (Min (aMaxDuration, aDuration));
1165 aProgress *= aRunRatio;
1166 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1167 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1168 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1170 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1172 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1173 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1174 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1175 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1177 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1179 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1180 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1181 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1182 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1184 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1186 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1187 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1188 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1189 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1191 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1193 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1194 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1195 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1196 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1198 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1200 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1201 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1202 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1203 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1205 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1207 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1208 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1209 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1210 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1212 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1214 double aProgress = Abs (Min (aMaxDuration, aDuration));
1215 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1216 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1217 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1219 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1221 double aProgress = Abs (Min (aMaxDuration, aDuration));
1222 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1223 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1224 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1229 // =======================================================================
1230 // function : AbortViewAnimation
1232 // =======================================================================
1233 void AIS_ViewController::AbortViewAnimation()
1235 if (!myViewAnimation.IsNull()
1236 && !myViewAnimation->IsStopped())
1238 myViewAnimation->Stop();
1239 myViewAnimation->SetView (Handle(V3d_View)());
1243 // =======================================================================
1244 // function : handlePanning
1246 // =======================================================================
1247 void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1249 if (!myGL.Panning.ToPan
1250 || !myToAllowPanning)
1255 AbortViewAnimation();
1257 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1258 if (aCam->IsOrthographic()
1259 || !hasPanningAnchorPoint())
1261 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1262 theView->Invalidate();
1266 Graphic3d_Vec2i aWinSize;
1267 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1269 const gp_Dir& aDir = aCam->Direction();
1270 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1271 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1272 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1273 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1274 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1276 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1278 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1279 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1280 aPanTrsf.SetTranslation (aCameraPan);
1281 aCam->Transform (aPanTrsf);
1282 theView->Invalidate();
1285 // =======================================================================
1286 // function : handleZRotate
1288 // =======================================================================
1289 void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1291 if (!myGL.ZRotate.ToRotate
1292 || !myToAllowRotation)
1297 AbortViewAnimation();
1299 Graphic3d_Vec2i aViewPort;
1300 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1301 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1302 0.5 * aViewPort.y());
1303 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1304 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1305 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1306 theView->Invalidate();
1309 // =======================================================================
1310 // function : handleZoom
1312 // =======================================================================
1313 void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1314 const Aspect_ScrollDelta& theParams,
1315 const gp_Pnt* thePnt)
1317 if (!myToAllowZooming)
1322 AbortViewAnimation();
1324 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1327 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1328 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1331 if (!theParams.HasPoint())
1333 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1334 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1335 theView->SetZoom (aCoeff, true);
1336 theView->Invalidate();
1340 // integer delta is too rough for small smooth increments
1341 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1342 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1344 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1345 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1351 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1353 // ensure that zoom will not be too small or too big
1354 double aCoef = aDZoom;
1355 if (aViewDims.x() < aCoef * Precision::Confusion())
1357 aCoef = aViewDims.x() / Precision::Confusion();
1359 else if (aViewDims.x() > aCoef * 1e12)
1361 aCoef = aViewDims.x() / 1e12;
1363 if (aViewDims.y() < aCoef * Precision::Confusion())
1365 aCoef = aViewDims.y() / Precision::Confusion();
1367 else if (aViewDims.y() > aCoef * 1e12)
1369 aCoef = aViewDims.y() / 1e12;
1372 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1373 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1374 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1375 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1376 aCam->SetScale (aCam->Scale() / aCoef);
1378 const gp_Dir& aDir = aCam->Direction();
1379 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1381 // pan back to the point
1382 aDxy = aZoomAtPointXYv - aDxy;
1385 // zoom at 3D point with perspective projection
1386 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1387 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1388 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1390 // view dimensions at 3D point
1391 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1393 Graphic3d_Vec2i aWinSize;
1394 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1395 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
1396 double(theParams.Point.y()) - 0.5 * double(aWinSize.y()));
1397 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
1398 aDxy.y() += aViewDims1.X() * aPanFromCenterPx.y() / double(aWinSize.x());
1401 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1403 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1404 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1405 aPanTrsf.SetTranslation (aCameraPan);
1406 aCam->Transform (aPanTrsf);
1407 theView->Invalidate();
1410 // =======================================================================
1411 // function : handleZFocusScroll
1413 // =======================================================================
1414 void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1415 const Aspect_ScrollDelta& theParams)
1417 if (!myToAllowZFocus
1418 || !theView->Camera()->IsStereo())
1423 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1427 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1432 // =======================================================================
1433 // function : handleOrbitRotation
1435 // =======================================================================
1436 void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1437 const gp_Pnt& thePnt,
1440 if (!myToAllowRotation)
1445 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1446 if (myGL.OrbitRotation.ToStart)
1448 // default alternatives
1449 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1450 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1452 myRotatePnt3d = thePnt;
1453 myCamStartOpUp = aCam->Up();
1454 myCamStartOpEye = aCam->Eye();
1455 myCamStartOpCenter = aCam->Center();
1458 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1459 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1460 const gp_Quaternion aRot = aTrsf.GetRotation();
1461 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1464 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1465 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1467 theView->Invalidate();
1470 if (!myGL.OrbitRotation.ToRotate)
1475 AbortViewAnimation();
1478 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1479 Graphic3d_Vec2i aWinXY;
1480 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1481 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1482 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1483 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1484 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1485 const double aRoll = 0.0;
1488 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1490 aTrsfRot.SetRotation (aRot);
1492 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1493 aCam->SetUp (aNewUp);
1494 aCam->SetCenter(myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1495 aCam->SetEye (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ());
1496 aCam->OrthogonalizeUp();
1500 // default alternatives
1501 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1502 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1504 // restore previous camera state
1505 aCam->SetUp (myCamStartOpUp);
1506 aCam->SetEye (myCamStartOpEye);
1507 aCam->SetCenter (myCamStartOpCenter);
1509 Graphic3d_Vec2d aWinXY;
1510 theView->Size (aWinXY.x(), aWinXY.y());
1511 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1512 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1514 const double THE_2PI = M_PI * 2.0;
1515 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1516 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1518 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1519 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1520 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1521 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1523 // rotate camera around 3 initial axes
1524 gp_Dir aCamDir (aCam->Direction().Reversed());
1525 gp_Dir aCamUp (aCam->Up());
1526 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1528 gp_Trsf aRot[2], aTrsf;
1529 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1530 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1531 aTrsf.Multiply (aRot[0]);
1532 aTrsf.Multiply (aRot[1]);
1534 aCam->Transform (aTrsf);
1537 theView->Invalidate();
1540 // =======================================================================
1541 // function : handleViewRotation
1543 // =======================================================================
1544 void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1546 double thePitchExtra,
1548 bool theToRestartOnIncrement)
1550 if (!myToAllowRotation)
1555 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1556 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1557 || Abs (thePitchExtra) > gp::Resolution()
1558 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1560 && theToRestartOnIncrement)
1562 myGL.ViewRotation.ToStart = true;
1563 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1565 if (myGL.ViewRotation.ToStart)
1568 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1569 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1570 const gp_Quaternion aRot = aTrsf.GetRotation();
1571 double aRollDummy = 0.0;
1572 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1576 myRotateStartYawPitchRoll[0] += theYawExtra;
1577 myRotateStartYawPitchRoll[1] += thePitchExtra;
1578 myRotateStartYawPitchRoll[2] = theRoll;
1579 myGL.ViewRotation.ToRotate = true;
1582 if (!myGL.ViewRotation.ToRotate)
1587 AbortViewAnimation();
1589 Graphic3d_Vec2i aWinXY;
1590 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1591 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1592 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1593 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1594 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1596 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1598 aTrsfRot.SetRotation (aRot);
1600 const double aDist = aCam->Distance();
1601 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1602 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
1603 aCam->SetUp (aNewUp);
1604 aCam->SetCenter (aCam->Eye().Translated (gp_Vec (aNewDir) * aDist));
1605 aCam->OrthogonalizeUp();
1606 theView->Invalidate();
1609 // =======================================================================
1610 // function : PickPoint
1612 // =======================================================================
1613 bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1614 const Handle(AIS_InteractiveContext)& theCtx,
1615 const Handle(V3d_View)& theView,
1616 const Graphic3d_Vec2i& theCursor,
1617 bool theToStickToPickRay)
1619 ResetPreviousMoveTo();
1621 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1622 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1623 if (aSelector->NbPicked() < 1)
1628 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1629 if (theToStickToPickRay
1630 && !Precision::IsInfinite (aPicked.Depth))
1632 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1636 thePnt = aSelector->PickedPoint (1);
1638 return !Precision::IsInfinite (thePnt.X())
1639 && !Precision::IsInfinite (thePnt.Y())
1640 && !Precision::IsInfinite (thePnt.Z());
1643 // =======================================================================
1644 // function : GravityPoint
1646 // =======================================================================
1647 gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1648 const Handle(V3d_View)& theView)
1650 switch (myRotationMode)
1652 case AIS_RotationMode_PickLast:
1653 case AIS_RotationMode_PickCenter:
1655 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1656 if (myRotationMode == AIS_RotationMode_PickCenter)
1658 Graphic3d_Vec2i aViewPort;
1659 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1660 aCursor = aViewPort / 2;
1664 if (PickPoint (aPnt, theCtx, theView, aCursor, false))
1670 case AIS_RotationMode_CameraAt:
1672 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1673 return aCam->Center();
1675 case AIS_RotationMode_BndBoxScene:
1677 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1678 if (!aBndBox.IsVoid())
1680 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1684 case AIS_RotationMode_BndBoxActive:
1688 return theCtx ->GravityPoint (theView);
1691 // =======================================================================
1692 // function : handleCameraActions
1694 // =======================================================================
1695 void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
1696 const Handle(V3d_View)& theView,
1697 const AIS_WalkDelta& theWalk)
1699 // apply view actions
1700 if (myGL.Orientation.ToSetViewOrient)
1702 theView->SetProj (myGL.Orientation.ViewOrient);
1703 myGL.Orientation.ToFitAll = true;
1707 if (myGL.Orientation.ToFitAll)
1709 const double aFitMargin = 0.01;
1710 theView->FitAll (aFitMargin, false);
1711 theView->Invalidate();
1712 myGL.Orientation.ToFitAll = false;
1715 if (myGL.IsNewGesture)
1717 if (myAnchorPointPrs1->HasInteractiveContext())
1719 theCtx->Remove (myAnchorPointPrs1, false);
1720 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
1722 theView->Invalidate();
1726 theView->InvalidateImmediate();
1729 if (myAnchorPointPrs2->HasInteractiveContext())
1731 theCtx->Remove (myAnchorPointPrs2, false);
1732 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
1734 theView->Invalidate();
1738 theView->InvalidateImmediate();
1742 if (myHasHlrOnBeforeRotation)
1744 myHasHlrOnBeforeRotation = false;
1745 theView->SetComputedMode (true);
1746 theView->Invalidate();
1750 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
1752 if (myGL.Panning.ToStart
1753 && myToAllowPanning)
1755 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
1756 if (!theView->Camera()->IsOrthographic())
1758 bool toStickToRay = false;
1759 if (myGL.Panning.PointStart.x() >= 0
1760 && myGL.Panning.PointStart.y() >= 0)
1762 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
1764 if (Precision::IsInfinite (aPanPnt.X()))
1766 Graphic3d_Vec2i aWinSize;
1767 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1768 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
1770 if (!Precision::IsInfinite (aPanPnt.X())
1771 && myToShowPanAnchorPoint)
1774 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
1775 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1778 setPanningAnchorPoint (aPanPnt);
1781 if (myToShowPanAnchorPoint
1782 && hasPanningAnchorPoint()
1783 && myGL.Panning.ToPan
1784 && !myGL.IsNewGesture
1785 && !myAnchorPointPrs2->HasInteractiveContext())
1787 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1790 handlePanning (theView);
1791 handleZRotate (theView);
1794 if ((myNavigationMode == AIS_NavigationMode_Orbit
1795 || myGL.OrbitRotation.ToStart
1796 || myGL.OrbitRotation.ToRotate)
1797 && myToAllowRotation)
1799 if (myGL.OrbitRotation.ToStart
1800 && !myHasHlrOnBeforeRotation)
1802 myHasHlrOnBeforeRotation = theView->ComputedMode();
1803 if (myHasHlrOnBeforeRotation)
1805 theView->SetComputedMode (false);
1810 if (myGL.OrbitRotation.ToStart)
1812 aGravPnt = GravityPoint (theCtx, theView);
1813 if (myToShowRotateCenter)
1816 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
1817 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
1818 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1822 if (myToShowRotateCenter
1823 && myGL.OrbitRotation.ToRotate
1824 && !myGL.IsNewGesture
1825 && !myAnchorPointPrs1->HasInteractiveContext())
1827 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
1828 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1830 handleOrbitRotation (theView, aGravPnt,
1831 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
1834 if ((myNavigationMode != AIS_NavigationMode_Orbit
1835 || myGL.ViewRotation.ToStart
1836 || myGL.ViewRotation.ToRotate)
1837 && myToAllowRotation)
1839 if (myGL.ViewRotation.ToStart
1840 && !myHasHlrOnBeforeRotation)
1842 myHasHlrOnBeforeRotation = theView->ComputedMode();
1843 if (myHasHlrOnBeforeRotation)
1845 theView->SetComputedMode (false);
1850 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
1851 && !myToLockOrbitZUp)
1853 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
1854 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
1855 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
1861 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
1862 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
1865 if (!myGL.ZoomActions.IsEmpty())
1867 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
1869 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
1871 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
1872 && theView->Camera()->IsStereo())
1874 handleZFocusScroll (theView, aZoomParams);
1878 if (!myToAllowZooming)
1883 if (!theView->Camera()->IsOrthographic())
1885 // what is more natural to user - point on ray or point exactly on geometry in corner cases?
1886 const bool toStickToRay = false; // true;
1889 if (aZoomParams.HasPoint()
1890 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, toStickToRay))
1892 handleZoom (theView, aZoomParams, &aPnt);
1896 Graphic3d_Vec2i aWinSize;
1897 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1898 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, toStickToRay))
1900 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
1901 handleZoom (theView, aZoomParams, &aPnt);
1905 handleZoom (theView, aZoomParams, NULL);
1907 myGL.ZoomActions.Clear();
1911 // =======================================================================
1912 // function : OnSelectionChanged
1914 // =======================================================================
1915 void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
1916 const Handle(V3d_View)& )
1921 // =======================================================================
1922 // function : OnObjectDragged
1924 // =======================================================================
1925 void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
1926 const Handle(V3d_View)& theView,
1927 AIS_DragAction theAction)
1931 case AIS_DragAction_Start:
1933 myDragObject.Nullify();
1934 if (!theCtx->HasDetected())
1939 Handle(AIS_InteractiveObject) aPrs = theCtx->DetectedInteractive();
1940 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (aPrs))
1942 if (aManip->HasActiveMode())
1944 myDragObject = aManip;
1945 aManip->StartTransform (myGL.Dragging.PointStart.x(), myGL.Dragging.PointStart.y(), theView);
1950 case AIS_DragAction_Update:
1952 if (myDragObject.IsNull())
1957 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
1959 theCtx->SetSelectedState (aGlobOwner, true);
1961 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1963 aManip->Transform (myGL.Dragging.PointTo.x(), myGL.Dragging.PointTo.y(), theView);
1965 theView->Invalidate();
1968 case AIS_DragAction_Abort:
1970 if (myDragObject.IsNull())
1975 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
1976 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
1978 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1980 aManip->StopTransform (false);
1982 Standard_FALLTHROUGH
1984 case AIS_DragAction_Stop:
1986 if (myDragObject.IsNull())
1991 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
1993 theCtx->SetSelectedState (aGlobOwner, false);
1996 theView->Invalidate();
1997 myDragObject.Nullify();
2003 // =======================================================================
2004 // function : contextLazyMoveTo
2006 // =======================================================================
2007 void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2008 const Handle(V3d_View)& theView,
2009 const Graphic3d_Vec2i& thePnt)
2011 if (myPrevMoveTo == thePnt)
2016 myPrevMoveTo = thePnt;
2018 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2019 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2020 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2022 if (theView->Viewer()->Grid()->IsActive()
2023 && theView->Viewer()->GridEcho())
2025 if (aNewPicked.IsNull())
2027 Graphic3d_Vec3d aPnt3d;
2028 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2029 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2030 theView->InvalidateImmediate();
2034 theView->Viewer()->HideGridEcho (theView);
2035 theView->InvalidateImmediate();
2039 if (aLastPicked != aNewPicked
2040 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2042 // dynamic highlight affects all Views
2043 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2045 const Handle(V3d_View)& aView = aViewIter.Value();
2046 aView->InvalidateImmediate();
2051 // =======================================================================
2052 // function : handleSelectionPick
2054 // =======================================================================
2055 void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2056 const Handle(V3d_View)& theView)
2058 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2059 && !myGL.Selection.Points.IsEmpty())
2061 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2063 const bool hadPrevMoveTo = HasPreviousMoveTo();
2064 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2067 ResetPreviousMoveTo();
2070 if (myGL.Selection.IsXOR)
2072 theCtx->ShiftSelect (false);
2076 theCtx->Select (false);
2079 // selection affects all Views
2080 theView->Viewer()->Invalidate();
2082 OnSelectionChanged (theCtx, theView);
2085 myGL.Selection.Points.Clear();
2089 // =======================================================================
2090 // function : handleSelectionPoly
2092 // =======================================================================
2093 void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2094 const Handle(V3d_View)& theView)
2096 // rubber-band & window polygon selection
2097 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2098 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon)
2100 if (!myGL.Selection.Points.IsEmpty())
2102 myRubberBand->ClearPoints();
2103 myRubberBand->SetToUpdate();
2105 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand;
2108 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2109 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2113 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2114 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2116 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2117 if (aPntNew != aPrev)
2120 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2125 myRubberBand->SetPolygonClosed (anIsRubber);
2128 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2130 catch (const Standard_Failure& theEx)
2132 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2133 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString(), Message_Warning);
2134 myRubberBand->ClearPoints();
2136 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2138 theView->Invalidate();
2142 theView->InvalidateImmediate();
2145 else if (!myRubberBand.IsNull()
2146 && myRubberBand->HasInteractiveContext())
2148 theCtx->Remove (myRubberBand, false);
2149 myRubberBand->ClearPoints();
2153 if (myGL.Selection.ToApplyTool)
2155 myGL.Selection.ToApplyTool = false;
2156 if (theCtx->IsDisplayed (myRubberBand))
2158 theCtx->Remove (myRubberBand, false);
2160 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2161 if (aPoints.Size() == 4
2162 && aPoints.Value (1).x() == aPoints.Value (2).x()
2163 && aPoints.Value (3).x() == aPoints.Value (4).x()
2164 && aPoints.Value (1).y() == aPoints.Value (4).y()
2165 && aPoints.Value (2).y() == aPoints.Value (3).y())
2167 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2168 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
2169 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2170 if (myGL.Selection.IsXOR)
2172 theCtx->ShiftSelect (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2173 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2178 theCtx->Select (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2179 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2182 theCtx->MainSelector()->AllowOverlapDetection (false);
2184 else if (aPoints.Length() >= 3)
2186 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2187 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2188 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2189 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2191 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2192 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2195 theCtx->MainSelector()->AllowOverlapDetection (false);
2196 if (myGL.Selection.IsXOR)
2198 theCtx->ShiftSelect (aPolyline, theView, false);
2202 theCtx->Select (aPolyline, theView, false);
2207 // selection affects all Views
2208 theView->Viewer()->Invalidate();
2210 myRubberBand->ClearPoints();
2211 OnSelectionChanged (theCtx, theView);
2216 // =======================================================================
2217 // function : handleDynamicHighlight
2219 // =======================================================================
2220 void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2221 const Handle(V3d_View)& theView)
2223 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2224 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2226 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2227 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2228 && !HasPreviousMoveTo())
2230 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2231 ResetPreviousMoveTo();
2232 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2233 theCtx->ClearDetected();
2235 else if (myToAllowHighlight)
2237 if (myPrevMoveTo != aMoveToPnt
2238 || myGL.OrbitRotation.ToRotate
2239 || myGL.ViewRotation.ToRotate
2240 || theView->IsInvalidated())
2242 ResetPreviousMoveTo();
2243 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2245 if (myGL.Dragging.ToStart)
2247 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2251 myGL.MoveTo.ToHilight = false;
2254 if (!myDragObject.IsNull())
2256 if (myGL.Dragging.ToAbort)
2258 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2259 myGL.OrbitRotation.ToRotate = false;
2260 myGL.ViewRotation .ToRotate = false;
2262 else if (myGL.Dragging.ToStop)
2264 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2265 myGL.OrbitRotation.ToRotate = false;
2266 myGL.ViewRotation .ToRotate = false;
2268 else if (myGL.OrbitRotation.ToRotate
2269 || myGL.ViewRotation.ToRotate)
2271 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2272 myGL.OrbitRotation.ToRotate = false;
2273 myGL.ViewRotation .ToRotate = false;
2278 // =======================================================================
2279 // function : handleMoveTo
2281 // =======================================================================
2282 void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2283 const Handle(V3d_View)& theView)
2285 handleSelectionPick (theCtx, theView);
2286 handleDynamicHighlight(theCtx, theView);
2287 handleSelectionPoly (theCtx, theView);
2290 // =======================================================================
2291 // function : handleViewRedraw
2293 // =======================================================================
2294 void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2295 const Handle(V3d_View)& theView)
2297 // manage animation state
2298 if (!myViewAnimation.IsNull()
2299 && !myViewAnimation->IsStopped())
2301 myViewAnimation->UpdateTimer();
2302 ResetPreviousMoveTo();
2306 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2308 const Handle(V3d_View)& aView = aViewIter.Value();
2309 if (aView->IsInvalidated()
2310 || myToAskNextFrame)
2312 if (aView->ComputedMode())
2321 else if (aView->IsInvalidatedImmediate())
2323 aView->RedrawImmediate();
2327 if (myToAskNextFrame)
2330 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
2334 // =======================================================================
2335 // function : HandleViewEvents
2337 // =======================================================================
2338 void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
2339 const Handle(V3d_View)& theView)
2341 handleMoveTo (theCtx, theView);
2343 const AIS_WalkDelta aWalk = FetchNavigationKeys (1.0, 1.0);
2344 handleCameraActions (theCtx, theView, aWalk);
2345 handleViewRedraw (theCtx, theView);
2347 // make sure to not process the same events twice
2349 myToAskNextFrame = false;