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),
73 myTouchToleranceScale (1.0f),
74 myTouchRotationThresholdPx (6.0f),
75 myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)),
76 myTouchPanThresholdPx (4.0f),
77 myTouchZoomThresholdPx (6.0f),
78 myTouchZoomRatio (0.13f),
81 myUpdateStartPointPan (true),
82 myUpdateStartPointRot (true),
83 myUpdateStartPointZRot (true),
85 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
89 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
90 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
91 myAnchorPointPrs1->SetMutable (true);
93 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
94 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
95 myAnchorPointPrs2->SetMutable (true);
97 myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
98 myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD);
99 myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
100 myRubberBand->SetDisplayMode (0);
101 myRubberBand->SetMutable (true);
103 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
104 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom);
105 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan);
106 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle);
108 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
109 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
111 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
112 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
115 // =======================================================================
116 // function : ResetViewInput
118 // =======================================================================
119 void AIS_ViewController::ResetViewInput()
122 myMousePressed = Aspect_VKeyMouse_NONE;
123 myMouseModifiers = Aspect_VKeyFlags_NONE;
124 myMouseSingleButton = -1;
125 myUI.Dragging.ToAbort = true;
126 myMouseActiveGesture = AIS_MouseGesture_NONE;
127 myMouseClickTimer.Stop();
128 myMouseClickCounter = 0;
131 // =======================================================================
132 // function : FlushViewEvents
134 // =======================================================================
135 void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
136 const Handle(V3d_View)& theView,
137 Standard_Boolean theToHandle)
139 flushBuffers (theCtx, theView);
140 flushGestures(theCtx, theView);
143 HandleViewEvents (theCtx, theView);
147 // =======================================================================
148 // function : flushBuffers
150 // =======================================================================
151 void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
152 const Handle(V3d_View)& )
154 myToAskNextFrame = false;
156 myGL.IsNewGesture = myUI.IsNewGesture;
157 myUI.IsNewGesture = false;
159 myGL.ZoomActions.Clear();
160 myGL.ZoomActions.Append (myUI.ZoomActions);
161 myUI.ZoomActions.Clear();
163 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
164 myUI.Orientation.ToFitAll = false;
165 if (myUI.Orientation.ToSetViewOrient)
167 myUI.Orientation.ToSetViewOrient = false;
168 myGL.Orientation.ToSetViewOrient = true;
169 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
172 if (myUI.MoveTo.ToHilight)
174 myUI.MoveTo.ToHilight = false;
175 myGL.MoveTo.ToHilight = true;
176 myGL.MoveTo.Point = myUI.MoveTo.Point;
180 myGL.Selection.Tool = myUI.Selection.Tool;
181 myGL.Selection.IsXOR = myUI.Selection.IsXOR;
182 myGL.Selection.Points = myUI.Selection.Points;
183 myUI.Selection.IsXOR = false;
184 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
186 myUI.Selection.Points.Clear();
190 if (myUI.Selection.ToApplyTool)
192 myGL.Selection.ToApplyTool = true;
193 myUI.Selection.ToApplyTool = false;
194 myUI.Selection.Points.Clear();
197 if (myUI.Panning.ToStart)
199 myUI.Panning.ToStart = false;
200 myGL.Panning.ToStart = true;
201 myGL.Panning.PointStart = myUI.Panning.PointStart;
204 if (myUI.Panning.ToPan)
206 myUI.Panning.ToPan = false;
207 myGL.Panning.ToPan = true;
208 myGL.Panning.Delta = myUI.Panning.Delta;
211 if (myUI.Dragging.ToAbort)
213 myUI.Dragging.ToAbort = false;
214 myGL.Dragging.ToAbort = true;
216 else if (myUI.Dragging.ToStop)
218 myUI.Dragging.ToStop = false;
219 myGL.Dragging.ToStop = true;
221 else if (myUI.Dragging.ToStart)
223 myUI.Dragging.ToStart = false;
224 myGL.Dragging.ToStart = true;
225 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
227 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
229 if (myUI.OrbitRotation.ToStart)
231 myUI.OrbitRotation.ToStart = false;
232 myGL.OrbitRotation.ToStart = true;
233 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
236 if (myUI.OrbitRotation.ToRotate)
238 myUI.OrbitRotation.ToRotate = false;
239 myGL.OrbitRotation.ToRotate = true;
240 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
243 if (myUI.ViewRotation.ToStart)
245 myUI.ViewRotation.ToStart = false;
246 myGL.ViewRotation.ToStart = true;
247 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
250 if (myUI.ViewRotation.ToRotate)
252 myUI.ViewRotation.ToRotate = false;
253 myGL.ViewRotation.ToRotate = true;
254 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
257 if (myUI.ZRotate.ToRotate)
259 myGL.ZRotate = myUI.ZRotate;
260 myUI.ZRotate.ToRotate = false;
264 // =======================================================================
265 // function : flushGestures
267 // =======================================================================
268 void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
269 const Handle(V3d_View)& theView)
271 const Standard_Real aTolScale = myTouchToleranceScale;
272 const Standard_Integer aTouchNb = myTouchPoints.Extent();
273 if (myNbTouchesLast != aTouchNb)
275 myNbTouchesLast = aTouchNb;
276 myGL.IsNewGesture = true;
278 if (aTouchNb == 1) // touch
280 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
281 if (myUpdateStartPointRot)
283 // skip rotation if have active dragged object
284 if (myNavigationMode == AIS_NavigationMode_Orbit)
286 myGL.OrbitRotation.ToStart = true;
287 myGL.OrbitRotation.PointStart = myStartRotCoord;
291 myGL.ViewRotation.ToStart = true;
292 myGL.ViewRotation.PointStart = myStartRotCoord;
295 myUpdateStartPointRot = false;
296 theView->Invalidate();
300 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
301 ? aTolScale * myTouchRotationThresholdPx
303 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
305 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
306 if (myNavigationMode == AIS_NavigationMode_Orbit)
308 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
309 myGL.OrbitRotation.ToRotate = true;
310 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
311 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
315 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
316 myGL.ViewRotation.ToRotate = true;
317 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
318 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
321 aTouch.From = aTouch.To;
324 else if (aTouchNb == 2) // pinch
326 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
327 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
328 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
329 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
331 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
332 (aFrom[0].y() + aFrom[1].y()) / 2.0);
334 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
335 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
337 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
338 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
340 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
341 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
343 Standard_Real aDeltaSize = anEndSize - aStartSize;
345 bool anIsClearDev = false;
347 if (myToAllowTouchZRotation)
349 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
350 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
352 Standard_Real A2 = aTo[0].y() - aTo[1].y();
353 Standard_Real B2 = aTo[1].x() - aTo[0].x();
355 Standard_Real aRotAngle = 0.0;
357 Standard_Real aDenomenator = A1*A2 + B1*B2;
358 if (aDenomenator <= Precision::Confusion())
364 Standard_Real aNumerator = A1*B2 - A2*B1;
365 aRotAngle = ATan (aNumerator / aDenomenator);
368 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
370 myGL.ZRotate.ToRotate = true;
371 myGL.ZRotate.Angle = aRotAngle;
376 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
379 aDeltaSize *= Standard_Real(myTouchZoomRatio);
380 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
381 myGL.ZoomActions.Append (aParams);
385 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
386 ? aTolScale * myTouchPanThresholdPx
388 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
391 if (myUpdateStartPointPan)
393 myGL.Panning.ToStart = true;
394 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
395 myUpdateStartPointPan = false;
396 theView->Invalidate();
399 myGL.Panning.ToPan = true;
400 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
401 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
407 aFirstTouch.From = aFirstTouch.To;
408 aLastTouch .From = aLastTouch.To;
413 // =======================================================================
414 // function : UpdateViewOrientation
416 // =======================================================================
417 void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
420 myUI.Orientation.ToFitAll = theToFitAll;
421 myUI.Orientation.ToSetViewOrient = true;
422 myUI.Orientation.ViewOrient = theOrientation;
425 // =======================================================================
426 // function : SelectInViewer
428 // =======================================================================
429 void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
432 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
434 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
435 myUI.Selection.Points.Clear();
438 myUI.Selection.IsXOR = theIsXOR;
439 myUI.Selection.Points.Append (thePnt);
442 // =======================================================================
443 // function : SelectInViewer
445 // =======================================================================
446 void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
449 myUI.Selection.IsXOR = theIsXOR;
450 myUI.Selection.Points = thePnts;
451 myUI.Selection.ToApplyTool = true;
452 if (thePnts.Length() == 1)
454 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
456 else if (thePnts.Length() == 2)
458 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
462 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
466 // =======================================================================
467 // function : UpdateRubberBand
469 // =======================================================================
470 void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
471 const Graphic3d_Vec2i& thePntTo,
474 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
475 myUI.Selection.IsXOR = theIsXOR;
476 myUI.Selection.Points.Clear();
477 myUI.Selection.Points.Append (thePntFrom);
478 myUI.Selection.Points.Append (thePntTo);
481 // =======================================================================
482 // function : UpdatePolySelection
484 // =======================================================================
485 void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
488 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
490 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
491 myUI.Selection.Points.Clear();
494 if (myUI.Selection.Points.IsEmpty())
496 myUI.Selection.Points.Append (thePnt);
499 && myUI.Selection.Points.Last() != thePnt)
501 myUI.Selection.Points.Append (thePnt);
505 myUI.Selection.Points.ChangeLast() = thePnt;
509 // =======================================================================
510 // function : UpdateZoom
512 // =======================================================================
513 bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
515 if (!myUI.ZoomActions.IsEmpty())
517 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
519 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
524 myUI.ZoomActions.Append (theDelta);
528 // =======================================================================
529 // function : UpdateZRotation
531 // =======================================================================
532 bool AIS_ViewController::UpdateZRotation (double theAngle)
534 if (!ToAllowTouchZRotation())
539 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
540 ? myUI.ZRotate.Angle + theAngle
542 if (myUI.ZRotate.ToRotate)
546 myUI.ZRotate.ToRotate = true;
550 // =======================================================================
551 // function : UpdateMouseScroll
553 // =======================================================================
554 bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
556 Aspect_ScrollDelta aDelta = theDelta;
557 aDelta.Delta *= myScrollZoomRatio;
558 return UpdateZoom (aDelta);
561 // =======================================================================
562 // function : UpdateMouseClick
564 // =======================================================================
565 bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
566 Aspect_VKeyMouse theButton,
567 Aspect_VKeyFlags theModifiers,
568 bool theIsDoubleClick)
570 (void )theIsDoubleClick;
571 if (theButton == Aspect_VKeyMouse_LeftButton)
573 SelectInViewer (thePoint, (theModifiers & Aspect_VKeyFlags_SHIFT) != 0);
579 // =======================================================================
580 // function : UpdateMouseButtons
582 // =======================================================================
583 bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
584 Aspect_VKeyMouse theButtons,
585 Aspect_VKeyFlags theModifiers,
588 bool toUpdateView = false;
589 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
590 if (theButtons == Aspect_VKeyMouse_NONE
591 && myMouseSingleButton > 0)
593 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
594 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
596 ++myMouseClickCounter;
597 const bool isDoubleClick = myMouseClickCounter == 2
598 && myMouseClickTimer.IsStarted()
599 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
601 myMouseClickTimer.Stop();
602 myMouseClickTimer.Reset();
603 myMouseClickTimer.Start();
606 myMouseClickCounter = 0;
608 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
612 myMouseClickTimer.Stop();
613 myMouseClickCounter = 0;
614 myUI.Dragging.ToStop = true;
617 myMouseSingleButton = -1;
619 else if (theButtons == Aspect_VKeyMouse_NONE)
621 myMouseSingleButton = -1;
623 else if (myMouseSingleButton == -1)
625 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
627 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
629 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
631 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
633 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
635 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
639 myMouseSingleButton = 0;
641 if (myMouseSingleButton != 0)
643 if (myMouseClickCounter == 1)
645 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
646 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
648 myMouseClickTimer.Stop();
649 myMouseClickCounter = 0;
652 myMousePressPoint = thePoint;
657 myMouseSingleButton = 0;
659 myUI.Dragging.ToAbort = true;
663 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
664 myMouseModifiers = theModifiers;
665 myMousePressed = theButtons;
667 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
669 myMouseActiveIdleRotation = false;
670 myMouseActiveGesture = AIS_MouseGesture_NONE;
673 myMousePressPoint = thePoint;
674 myMouseProgressPoint = myMousePressPoint;
677 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
679 switch (myMouseActiveGesture)
681 case AIS_MouseGesture_RotateView:
682 case AIS_MouseGesture_RotateOrbit:
684 if (myToAllowRotation)
686 myUpdateStartPointRot = true;
690 myMouseActiveGesture = AIS_MouseGesture_NONE;
694 case AIS_MouseGesture_Pan:
696 if (myToAllowPanning)
698 myUpdateStartPointPan = true;
702 myMouseActiveGesture = AIS_MouseGesture_NONE;
706 case AIS_MouseGesture_Zoom:
708 if (!myToAllowZooming)
710 myMouseActiveGesture = AIS_MouseGesture_NONE;
714 case AIS_MouseGesture_SelectRectangle:
718 case AIS_MouseGesture_SelectLasso:
720 UpdatePolySelection (thePoint, true);
723 case AIS_MouseGesture_NONE:
730 if (theButtons == Aspect_VKeyMouse_LeftButton
731 && theModifiers == Aspect_VKeyFlags_NONE
732 && myToAllowDragging)
734 myUI.Dragging.ToStart = true;
735 myUI.Dragging.PointStart = thePoint;
739 if (aPrevGesture != myMouseActiveGesture)
741 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
742 || aPrevGesture == AIS_MouseGesture_SelectLasso)
744 myUI.Selection.ToApplyTool = true;
747 myUI.IsNewGesture = true;
753 // =======================================================================
754 // function : UpdateMousePosition
756 // =======================================================================
757 bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
758 Aspect_VKeyMouse theButtons,
759 Aspect_VKeyFlags theModifiers,
762 myMousePositionLast = thePoint;
763 if (myMouseSingleButton > 0)
765 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
766 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
767 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
769 myMouseClickTimer.Stop();
770 myMouseClickCounter = 0;
771 myMouseSingleButton = -1;
775 bool toUpdateView = false;
776 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
778 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
780 if (!myMouseActiveIdleRotation
781 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
783 myMouseActiveIdleRotation = true;
784 myMouseActiveGesture = AIS_MouseGesture_RotateView;
785 myMousePressPoint = thePoint;
786 myMouseProgressPoint = thePoint;
787 myUpdateStartPointRot = false;
788 myUI.ViewRotation.ToStart = true;
789 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
790 myUI.ViewRotation.ToRotate = false;
791 aDelta.SetValues (0, 0);
796 if (myMouseActiveIdleRotation
797 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
799 myMouseActiveGesture = AIS_MouseGesture_NONE;
801 myMouseActiveIdleRotation = false;
804 if (myMouseModifiers != theModifiers
805 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
810 switch (myMouseActiveGesture)
812 case AIS_MouseGesture_SelectRectangle:
814 UpdateRubberBand (myMousePressPoint, thePoint);
818 case AIS_MouseGesture_SelectLasso:
820 UpdatePolySelection (thePoint, true);
824 case AIS_MouseGesture_RotateOrbit:
825 case AIS_MouseGesture_RotateView:
827 if (!myToAllowRotation)
831 if (myUpdateStartPointRot)
833 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
835 myUI.OrbitRotation.ToStart = true;
836 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
840 myUI.ViewRotation.ToStart = true;
841 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
843 myUpdateStartPointRot = false;
846 const double aRotTol = theIsEmulated
847 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
849 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
851 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
852 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
853 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
855 myUI.OrbitRotation.ToRotate = true;
856 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
857 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
861 myUI.ViewRotation.ToRotate = true;
862 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
863 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
865 myUI.Dragging.PointTo = thePoint;
867 myMouseProgressPoint = thePoint;
872 case AIS_MouseGesture_Zoom:
874 if (!myToAllowZooming)
878 const double aZoomTol = theIsEmulated
879 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
881 if (double (Abs (aDelta.x())) > aZoomTol)
883 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
887 myMouseProgressPoint = thePoint;
891 case AIS_MouseGesture_Pan:
893 if (!myToAllowPanning)
897 const double aPanTol = theIsEmulated
898 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
900 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
902 if (myUpdateStartPointPan)
904 myUI.Panning.ToStart = true;
905 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
906 myUpdateStartPointPan = false;
909 aDelta.y() = -aDelta.y();
910 myMouseProgressPoint = thePoint;
911 if (myUI.Panning.ToPan)
913 myUI.Panning.Delta += aDelta;
917 myUI.Panning.ToPan = true;
918 myUI.Panning.Delta = aDelta;
930 if (theButtons == Aspect_VKeyMouse_NONE
931 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
934 && myToAllowHighlight)
936 myUI.MoveTo.ToHilight = true;
937 myUI.MoveTo.Point = thePoint;
943 // =======================================================================
944 // function : AddTouchPoint
946 // =======================================================================
947 void AIS_ViewController::AddTouchPoint (Standard_Size theId,
948 const Graphic3d_Vec2d& thePnt,
949 Standard_Boolean theClearBefore)
951 myUI.MoveTo.ToHilight = false;
954 RemoveTouchPoint ((Standard_Size )-1);
957 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
958 if (myTouchPoints.Extent() == 1)
960 myUpdateStartPointRot = true;
961 myStartRotCoord = thePnt;
962 if (myToAllowDragging)
964 myUI.Dragging.ToStart = true;
965 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
968 else if (myTouchPoints.Extent() == 2)
970 myUI.Dragging.ToAbort = true;
972 myUpdateStartPointPan = true;
973 myStartPanCoord = thePnt;
975 myUI.IsNewGesture = true;
978 // =======================================================================
979 // function : RemoveTouchPoint
981 // =======================================================================
982 bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
983 Standard_Boolean theClearSelectPnts)
985 if (theId == (Standard_Size )-1)
987 myTouchPoints.Clear (false);
991 const Standard_Integer anOldExtent = myTouchPoints.Extent();
992 myTouchPoints.RemoveKey (theId);
993 if (myTouchPoints.Extent() == anOldExtent)
999 if (myTouchPoints.Extent() == 1)
1001 // avoid incorrect transition from pinch to one finger
1002 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1003 aFirstTouch.To = aFirstTouch.From;
1005 myStartRotCoord = aFirstTouch.To;
1006 myUpdateStartPointRot = true;
1008 else if (myTouchPoints.Extent() == 2)
1010 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1011 myUpdateStartPointPan = true;
1013 else if (myTouchPoints.IsEmpty())
1015 if (theClearSelectPnts)
1017 myUI.Selection.ToApplyTool = true;
1020 myUI.Dragging.ToStop = true;
1022 myUI.IsNewGesture = true;
1026 // =======================================================================
1027 // function : UpdateTouchPoint
1029 // =======================================================================
1030 void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1031 const Graphic3d_Vec2d& thePnt)
1033 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1035 aTouch->To = thePnt;
1039 AddTouchPoint (theId, thePnt);
1043 // =======================================================================
1044 // function : SetNavigationMode
1046 // =======================================================================
1047 void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1049 myNavigationMode = theMode;
1052 myUI.OrbitRotation.ToStart = false;
1053 myUI.OrbitRotation.ToRotate = false;
1054 myUI.ViewRotation.ToStart = false;
1055 myUI.ViewRotation.ToRotate = false;
1058 // =======================================================================
1059 // function : KeyDown
1061 // =======================================================================
1062 void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1066 myKeys.KeyDown (theKey, theTime, thePressure);
1069 // =======================================================================
1072 // =======================================================================
1073 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1076 myKeys.KeyUp (theKey, theTime);
1079 // =======================================================================
1080 // function : KeyFromAxis
1082 // =======================================================================
1083 void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1084 Aspect_VKey thePositive,
1088 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1091 // =======================================================================
1092 // function : FetchNavigationKeys
1094 // =======================================================================
1095 AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1096 Standard_Real theRunRatio)
1098 AIS_WalkDelta aWalk;
1101 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1102 updateEventsTime (aPrevEventTime, aNewEventTime);
1104 double aDuration = 0.0, aPressure = 1.0;
1105 if (Abs (myThrustSpeed) > gp::Resolution())
1109 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1112 myToAskNextFrame = true;
1116 myHasThrust = false;
1119 aWalk.SetRunning (theRunRatio > 1.0
1120 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1121 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1123 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1124 aWalk.SetJumping (true);
1126 if (!aWalk.IsJumping()
1127 && theCrouchRatio < 1.0
1128 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1130 aWalk.SetRunning (false);
1131 aWalk.SetCrouching (true);
1134 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1135 const double aRunRatio = aWalk.IsRunning()
1137 : aWalk.IsCrouching()
1140 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1142 double aProgress = Abs (Min (aMaxDuration, aDuration));
1143 aProgress *= aRunRatio;
1144 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1145 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1146 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1148 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1150 double aProgress = Abs (Min (aMaxDuration, aDuration));
1151 aProgress *= aRunRatio;
1152 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1153 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1154 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1156 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1158 double aProgress = Abs (Min (aMaxDuration, aDuration));
1159 aProgress *= aRunRatio;
1160 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1161 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1162 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1164 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1166 double aProgress = Abs (Min (aMaxDuration, aDuration));
1167 aProgress *= aRunRatio;
1168 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1169 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1170 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1172 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1174 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1175 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1176 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1177 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1179 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1181 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1182 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1183 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1184 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1186 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1188 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1189 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1190 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1191 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1193 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1195 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1196 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1197 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1198 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1200 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1202 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1203 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1204 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1205 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1207 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1209 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1210 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1211 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1212 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1214 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1216 double aProgress = Abs (Min (aMaxDuration, aDuration));
1217 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1218 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1219 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1221 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1223 double aProgress = Abs (Min (aMaxDuration, aDuration));
1224 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1225 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1226 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1231 // =======================================================================
1232 // function : AbortViewAnimation
1234 // =======================================================================
1235 void AIS_ViewController::AbortViewAnimation()
1237 if (!myViewAnimation.IsNull()
1238 && !myViewAnimation->IsStopped())
1240 myViewAnimation->Stop();
1241 myViewAnimation->SetView (Handle(V3d_View)());
1245 // =======================================================================
1246 // function : handlePanning
1248 // =======================================================================
1249 void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1251 if (!myGL.Panning.ToPan
1252 || !myToAllowPanning)
1257 AbortViewAnimation();
1259 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1260 if (aCam->IsOrthographic()
1261 || !hasPanningAnchorPoint())
1263 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1264 theView->Invalidate();
1268 Graphic3d_Vec2i aWinSize;
1269 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1271 const gp_Dir& aDir = aCam->Direction();
1272 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1273 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1274 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1275 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1276 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1278 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1280 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1281 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1282 aPanTrsf.SetTranslation (aCameraPan);
1283 aCam->Transform (aPanTrsf);
1284 theView->Invalidate();
1287 // =======================================================================
1288 // function : handleZRotate
1290 // =======================================================================
1291 void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1293 if (!myGL.ZRotate.ToRotate
1294 || !myToAllowRotation)
1299 AbortViewAnimation();
1301 Graphic3d_Vec2i aViewPort;
1302 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1303 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1304 0.5 * aViewPort.y());
1305 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1306 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1307 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1308 theView->Invalidate();
1311 // =======================================================================
1312 // function : handleZoom
1314 // =======================================================================
1315 void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1316 const Aspect_ScrollDelta& theParams,
1317 const gp_Pnt* thePnt)
1319 if (!myToAllowZooming)
1324 AbortViewAnimation();
1326 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1329 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1330 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1333 if (!theParams.HasPoint())
1335 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1336 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1337 theView->SetZoom (aCoeff, true);
1338 theView->Invalidate();
1342 // integer delta is too rough for small smooth increments
1343 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1344 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1346 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1347 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1353 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1355 // ensure that zoom will not be too small or too big
1356 double aCoef = aDZoom;
1357 if (aViewDims.x() < aCoef * Precision::Confusion())
1359 aCoef = aViewDims.x() / Precision::Confusion();
1361 else if (aViewDims.x() > aCoef * 1e12)
1363 aCoef = aViewDims.x() / 1e12;
1365 if (aViewDims.y() < aCoef * Precision::Confusion())
1367 aCoef = aViewDims.y() / Precision::Confusion();
1369 else if (aViewDims.y() > aCoef * 1e12)
1371 aCoef = aViewDims.y() / 1e12;
1374 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1375 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1376 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1377 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1378 aCam->SetScale (aCam->Scale() / aCoef);
1380 const gp_Dir& aDir = aCam->Direction();
1381 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1383 // pan back to the point
1384 aDxy = aZoomAtPointXYv - aDxy;
1387 // zoom at 3D point with perspective projection
1388 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1389 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1390 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1392 // view dimensions at 3D point
1393 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1395 Graphic3d_Vec2i aWinSize;
1396 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1397 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
1398 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
1399 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
1400 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
1403 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1405 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1406 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1407 aPanTrsf.SetTranslation (aCameraPan);
1408 aCam->Transform (aPanTrsf);
1409 theView->Invalidate();
1412 // =======================================================================
1413 // function : handleZFocusScroll
1415 // =======================================================================
1416 void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1417 const Aspect_ScrollDelta& theParams)
1419 if (!myToAllowZFocus
1420 || !theView->Camera()->IsStereo())
1425 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1429 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1434 // =======================================================================
1435 // function : handleOrbitRotation
1437 // =======================================================================
1438 void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1439 const gp_Pnt& thePnt,
1442 if (!myToAllowRotation)
1447 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1448 if (myGL.OrbitRotation.ToStart)
1450 // default alternatives
1451 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1452 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1454 myRotatePnt3d = thePnt;
1455 myCamStartOpUp = aCam->Up();
1456 myCamStartOpDir = aCam->Direction();
1457 myCamStartOpEye = aCam->Eye();
1458 myCamStartOpCenter = aCam->Center();
1461 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1462 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1463 const gp_Quaternion aRot = aTrsf.GetRotation();
1464 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1467 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1468 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1470 theView->Invalidate();
1473 if (!myGL.OrbitRotation.ToRotate)
1478 AbortViewAnimation();
1481 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1482 Graphic3d_Vec2i aWinXY;
1483 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1484 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1485 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1486 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1487 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1488 const double aRoll = 0.0;
1491 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1493 aTrsfRot.SetRotation (aRot);
1495 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1496 aCam->SetUp (aNewUp);
1497 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1498 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1500 aCam->OrthogonalizeUp();
1504 // default alternatives
1505 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1506 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1508 // restore previous camera state
1509 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1510 aCam->SetUp (myCamStartOpUp);
1511 aCam->SetDirectionFromEye (myCamStartOpDir);
1513 Graphic3d_Vec2d aWinXY;
1514 theView->Size (aWinXY.x(), aWinXY.y());
1515 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1516 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1518 const double THE_2PI = M_PI * 2.0;
1519 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1520 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1522 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1523 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1524 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1525 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1527 // rotate camera around 3 initial axes
1528 gp_Dir aCamDir (aCam->Direction().Reversed());
1529 gp_Dir aCamUp (aCam->Up());
1530 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1532 gp_Trsf aRot[2], aTrsf;
1533 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1534 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1535 aTrsf.Multiply (aRot[0]);
1536 aTrsf.Multiply (aRot[1]);
1538 aCam->Transform (aTrsf);
1541 theView->Invalidate();
1544 // =======================================================================
1545 // function : handleViewRotation
1547 // =======================================================================
1548 void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1550 double thePitchExtra,
1552 bool theToRestartOnIncrement)
1554 if (!myToAllowRotation)
1559 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1560 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1561 || Abs (thePitchExtra) > gp::Resolution()
1562 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1564 && theToRestartOnIncrement)
1566 myGL.ViewRotation.ToStart = true;
1567 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1569 if (myGL.ViewRotation.ToStart)
1572 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1573 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1574 const gp_Quaternion aRot = aTrsf.GetRotation();
1575 double aRollDummy = 0.0;
1576 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1580 myRotateStartYawPitchRoll[0] += theYawExtra;
1581 myRotateStartYawPitchRoll[1] += thePitchExtra;
1582 myRotateStartYawPitchRoll[2] = theRoll;
1583 myGL.ViewRotation.ToRotate = true;
1586 if (!myGL.ViewRotation.ToRotate)
1591 AbortViewAnimation();
1593 Graphic3d_Vec2i aWinXY;
1594 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1595 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1596 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1597 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1598 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1600 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1602 aTrsfRot.SetRotation (aRot);
1604 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1605 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
1606 aCam->SetUp (aNewUp);
1607 aCam->SetDirectionFromEye (aNewDir);
1608 aCam->OrthogonalizeUp();
1609 theView->Invalidate();
1612 // =======================================================================
1613 // function : PickPoint
1615 // =======================================================================
1616 bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1617 const Handle(AIS_InteractiveContext)& theCtx,
1618 const Handle(V3d_View)& theView,
1619 const Graphic3d_Vec2i& theCursor,
1620 bool theToStickToPickRay)
1622 ResetPreviousMoveTo();
1624 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1625 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1626 if (aSelector->NbPicked() < 1)
1631 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1632 if (theToStickToPickRay
1633 && !Precision::IsInfinite (aPicked.Depth))
1635 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1639 thePnt = aSelector->PickedPoint (1);
1641 return !Precision::IsInfinite (thePnt.X())
1642 && !Precision::IsInfinite (thePnt.Y())
1643 && !Precision::IsInfinite (thePnt.Z());
1646 // =======================================================================
1647 // function : GravityPoint
1649 // =======================================================================
1650 gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1651 const Handle(V3d_View)& theView)
1653 switch (myRotationMode)
1655 case AIS_RotationMode_PickLast:
1656 case AIS_RotationMode_PickCenter:
1658 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1659 if (myRotationMode == AIS_RotationMode_PickCenter)
1661 Graphic3d_Vec2i aViewPort;
1662 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1663 aCursor = aViewPort / 2;
1667 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
1673 case AIS_RotationMode_CameraAt:
1675 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1676 return aCam->Center();
1678 case AIS_RotationMode_BndBoxScene:
1680 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1681 if (!aBndBox.IsVoid())
1683 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1687 case AIS_RotationMode_BndBoxActive:
1691 return theCtx ->GravityPoint (theView);
1694 // =======================================================================
1695 // function : handleCameraActions
1697 // =======================================================================
1698 void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
1699 const Handle(V3d_View)& theView,
1700 const AIS_WalkDelta& theWalk)
1702 // apply view actions
1703 if (myGL.Orientation.ToSetViewOrient)
1705 theView->SetProj (myGL.Orientation.ViewOrient);
1706 myGL.Orientation.ToFitAll = true;
1710 if (myGL.Orientation.ToFitAll)
1712 const double aFitMargin = 0.01;
1713 theView->FitAll (aFitMargin, false);
1714 theView->Invalidate();
1715 myGL.Orientation.ToFitAll = false;
1718 if (myGL.IsNewGesture)
1720 if (myAnchorPointPrs1->HasInteractiveContext())
1722 theCtx->Remove (myAnchorPointPrs1, false);
1723 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
1725 theView->Invalidate();
1729 theView->InvalidateImmediate();
1732 if (myAnchorPointPrs2->HasInteractiveContext())
1734 theCtx->Remove (myAnchorPointPrs2, false);
1735 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
1737 theView->Invalidate();
1741 theView->InvalidateImmediate();
1745 if (myHasHlrOnBeforeRotation)
1747 myHasHlrOnBeforeRotation = false;
1748 theView->SetComputedMode (true);
1749 theView->Invalidate();
1753 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
1755 if (myGL.Panning.ToStart
1756 && myToAllowPanning)
1758 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
1759 if (!theView->Camera()->IsOrthographic())
1761 bool toStickToRay = false;
1762 if (myGL.Panning.PointStart.x() >= 0
1763 && myGL.Panning.PointStart.y() >= 0)
1765 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
1767 if (Precision::IsInfinite (aPanPnt.X()))
1769 Graphic3d_Vec2i aWinSize;
1770 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1771 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
1773 if (!Precision::IsInfinite (aPanPnt.X())
1774 && myToShowPanAnchorPoint)
1777 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
1778 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1781 setPanningAnchorPoint (aPanPnt);
1784 if (myToShowPanAnchorPoint
1785 && hasPanningAnchorPoint()
1786 && myGL.Panning.ToPan
1787 && !myGL.IsNewGesture
1788 && !myAnchorPointPrs2->HasInteractiveContext())
1790 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1793 handlePanning (theView);
1794 handleZRotate (theView);
1797 if ((myNavigationMode == AIS_NavigationMode_Orbit
1798 || myGL.OrbitRotation.ToStart
1799 || myGL.OrbitRotation.ToRotate)
1800 && myToAllowRotation)
1802 if (myGL.OrbitRotation.ToStart
1803 && !myHasHlrOnBeforeRotation)
1805 myHasHlrOnBeforeRotation = theView->ComputedMode();
1806 if (myHasHlrOnBeforeRotation)
1808 theView->SetComputedMode (false);
1813 if (myGL.OrbitRotation.ToStart)
1815 aGravPnt = GravityPoint (theCtx, theView);
1816 if (myToShowRotateCenter)
1819 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
1820 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
1821 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1825 if (myToShowRotateCenter
1826 && myGL.OrbitRotation.ToRotate
1827 && !myGL.IsNewGesture
1828 && !myAnchorPointPrs1->HasInteractiveContext())
1830 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
1831 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1833 handleOrbitRotation (theView, aGravPnt,
1834 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
1837 if ((myNavigationMode != AIS_NavigationMode_Orbit
1838 || myGL.ViewRotation.ToStart
1839 || myGL.ViewRotation.ToRotate)
1840 && myToAllowRotation)
1842 if (myGL.ViewRotation.ToStart
1843 && !myHasHlrOnBeforeRotation)
1845 myHasHlrOnBeforeRotation = theView->ComputedMode();
1846 if (myHasHlrOnBeforeRotation)
1848 theView->SetComputedMode (false);
1853 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
1854 && !myToLockOrbitZUp)
1856 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
1857 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
1858 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
1864 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
1865 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
1868 if (!myGL.ZoomActions.IsEmpty())
1870 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
1872 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
1874 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
1875 && theView->Camera()->IsStereo())
1877 handleZFocusScroll (theView, aZoomParams);
1881 if (!myToAllowZooming)
1886 if (!theView->Camera()->IsOrthographic())
1889 if (aZoomParams.HasPoint()
1890 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
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, myToStickToRayOnZoom))
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;