1 // Copyright (c) 2016-2019 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include "AIS_ViewController.hxx"
16 #include <AIS_AnimationCamera.hxx>
17 #include <AIS_InteractiveContext.hxx>
18 #include <AIS_Manipulator.hxx>
19 #include <AIS_Point.hxx>
20 #include <AIS_RubberBand.hxx>
21 #include <Aspect_Grid.hxx>
22 #include <Geom_CartesianPoint.hxx>
23 #include <Message.hxx>
24 #include <Message_Messenger.hxx>
25 #include <gp_Quaternion.hxx>
26 #include <V3d_View.hxx>
28 // =======================================================================
29 // function : AIS_ViewController
31 // =======================================================================
32 AIS_ViewController::AIS_ViewController()
33 : myLastEventsTime (0.0),
34 myToAskNextFrame (false),
35 myMinCamDistance (1.0),
36 myRotationMode (AIS_RotationMode_BndBoxActive),
37 myNavigationMode (AIS_NavigationMode_Orbit),
40 myToShowPanAnchorPoint (true),
41 myToShowRotateCenter (true),
42 myToLockOrbitZUp (false),
43 myToInvertPitch (false),
44 myToAllowTouchZRotation(false),
45 myToAllowRotation (true),
46 myToAllowPanning (true),
47 myToAllowZooming (true),
48 myToAllowZFocus (true),
49 myToAllowHighlight (true),
50 myToAllowDragging (true),
51 myToStickToRayOnZoom (true),
52 myToStickToRayOnRotation (true),
54 myWalkSpeedAbsolute (1.5f),
55 myWalkSpeedRelative (0.1f),
59 myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
60 myPrevMoveTo (-1, -1),
61 myHasHlrOnBeforeRotation (false),
63 myMouseClickThreshold (3.0),
64 myMouseDoubleClickInt (0.4),
65 myScrollZoomRatio (15.0f),
66 myMouseActiveGesture (AIS_MouseGesture_NONE),
67 myMouseActiveIdleRotation (false),
68 myMouseClickCounter (0),
69 myMousePressed (Aspect_VKeyMouse_NONE),
70 myMouseModifiers (Aspect_VKeyFlags_NONE),
71 myMouseSingleButton (-1),
72 myMouseStopDragOnUnclick (false),
74 myTouchToleranceScale (1.0f),
75 myTouchRotationThresholdPx (6.0f),
76 myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)),
77 myTouchPanThresholdPx (4.0f),
78 myTouchZoomThresholdPx (6.0f),
79 myTouchZoomRatio (0.13f),
82 myUpdateStartPointPan (true),
83 myUpdateStartPointRot (true),
84 myUpdateStartPointZRot (true),
86 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
90 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
91 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
92 myAnchorPointPrs1->SetMutable (true);
94 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
95 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
96 myAnchorPointPrs2->SetMutable (true);
98 myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
99 myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD);
100 myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
101 myRubberBand->SetDisplayMode (0);
102 myRubberBand->SetMutable (true);
104 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
105 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom);
106 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan);
107 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle);
109 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
110 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
112 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
113 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
116 // =======================================================================
117 // function : ResetViewInput
119 // =======================================================================
120 void AIS_ViewController::ResetViewInput()
123 myMousePressed = Aspect_VKeyMouse_NONE;
124 myMouseModifiers = Aspect_VKeyFlags_NONE;
125 myMouseSingleButton = -1;
126 myUI.Dragging.ToAbort = true;
127 myMouseActiveGesture = AIS_MouseGesture_NONE;
128 myMouseClickTimer.Stop();
129 myMouseClickCounter = 0;
132 // =======================================================================
133 // function : FlushViewEvents
135 // =======================================================================
136 void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
137 const Handle(V3d_View)& theView,
138 Standard_Boolean theToHandle)
140 flushBuffers (theCtx, theView);
141 flushGestures(theCtx, theView);
144 HandleViewEvents (theCtx, theView);
148 // =======================================================================
149 // function : flushBuffers
151 // =======================================================================
152 void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
153 const Handle(V3d_View)& )
155 myToAskNextFrame = false;
157 myGL.IsNewGesture = myUI.IsNewGesture;
158 myUI.IsNewGesture = false;
160 myGL.ZoomActions.Clear();
161 myGL.ZoomActions.Append (myUI.ZoomActions);
162 myUI.ZoomActions.Clear();
164 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
165 myUI.Orientation.ToFitAll = false;
166 if (myUI.Orientation.ToSetViewOrient)
168 myUI.Orientation.ToSetViewOrient = false;
169 myGL.Orientation.ToSetViewOrient = true;
170 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
173 if (myUI.MoveTo.ToHilight)
175 myUI.MoveTo.ToHilight = false;
176 myGL.MoveTo.ToHilight = true;
177 myGL.MoveTo.Point = myUI.MoveTo.Point;
181 myGL.Selection.Tool = myUI.Selection.Tool;
182 myGL.Selection.IsXOR = myUI.Selection.IsXOR;
183 myGL.Selection.Points = myUI.Selection.Points;
184 myUI.Selection.IsXOR = false;
185 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
187 myUI.Selection.Points.Clear();
191 if (myUI.Selection.ToApplyTool)
193 myGL.Selection.ToApplyTool = true;
194 myUI.Selection.ToApplyTool = false;
195 myUI.Selection.Points.Clear();
198 if (myUI.Panning.ToStart)
200 myUI.Panning.ToStart = false;
201 myGL.Panning.ToStart = true;
202 myGL.Panning.PointStart = myUI.Panning.PointStart;
205 if (myUI.Panning.ToPan)
207 myUI.Panning.ToPan = false;
208 myGL.Panning.ToPan = true;
209 myGL.Panning.Delta = myUI.Panning.Delta;
212 if (myUI.Dragging.ToAbort)
214 myUI.Dragging.ToAbort = false;
215 myGL.Dragging.ToAbort = true;
217 else if (myUI.Dragging.ToStop)
219 myUI.Dragging.ToStop = false;
220 myGL.Dragging.ToStop = true;
222 else if (myUI.Dragging.ToStart)
224 myUI.Dragging.ToStart = false;
225 myGL.Dragging.ToStart = true;
226 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
228 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
230 if (myUI.OrbitRotation.ToStart)
232 myUI.OrbitRotation.ToStart = false;
233 myGL.OrbitRotation.ToStart = true;
234 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
237 if (myUI.OrbitRotation.ToRotate)
239 myUI.OrbitRotation.ToRotate = false;
240 myGL.OrbitRotation.ToRotate = true;
241 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
244 if (myUI.ViewRotation.ToStart)
246 myUI.ViewRotation.ToStart = false;
247 myGL.ViewRotation.ToStart = true;
248 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
251 if (myUI.ViewRotation.ToRotate)
253 myUI.ViewRotation.ToRotate = false;
254 myGL.ViewRotation.ToRotate = true;
255 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
258 if (myUI.ZRotate.ToRotate)
260 myGL.ZRotate = myUI.ZRotate;
261 myUI.ZRotate.ToRotate = false;
265 // =======================================================================
266 // function : flushGestures
268 // =======================================================================
269 void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
270 const Handle(V3d_View)& theView)
272 const Standard_Real aTolScale = myTouchToleranceScale;
273 const Standard_Integer aTouchNb = myTouchPoints.Extent();
274 if (myNbTouchesLast != aTouchNb)
276 myNbTouchesLast = aTouchNb;
277 myGL.IsNewGesture = true;
279 if (aTouchNb == 1) // touch
281 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
282 if (myUpdateStartPointRot)
284 // skip rotation if have active dragged object
285 if (myNavigationMode == AIS_NavigationMode_Orbit)
287 myGL.OrbitRotation.ToStart = true;
288 myGL.OrbitRotation.PointStart = myStartRotCoord;
292 myGL.ViewRotation.ToStart = true;
293 myGL.ViewRotation.PointStart = myStartRotCoord;
296 myUpdateStartPointRot = false;
297 theView->Invalidate();
301 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
302 ? aTolScale * myTouchRotationThresholdPx
304 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
306 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
307 if (myNavigationMode == AIS_NavigationMode_Orbit)
309 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
310 myGL.OrbitRotation.ToRotate = true;
311 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
312 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
316 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
317 myGL.ViewRotation.ToRotate = true;
318 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
319 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
322 aTouch.From = aTouch.To;
325 else if (aTouchNb == 2) // pinch
327 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
328 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
329 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
330 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
332 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
333 (aFrom[0].y() + aFrom[1].y()) / 2.0);
335 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
336 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
338 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
339 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
341 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
342 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
344 Standard_Real aDeltaSize = anEndSize - aStartSize;
346 bool anIsClearDev = false;
348 if (myToAllowTouchZRotation)
350 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
351 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
353 Standard_Real A2 = aTo[0].y() - aTo[1].y();
354 Standard_Real B2 = aTo[1].x() - aTo[0].x();
356 Standard_Real aRotAngle = 0.0;
358 Standard_Real aDenomenator = A1*A2 + B1*B2;
359 if (aDenomenator <= Precision::Confusion())
365 Standard_Real aNumerator = A1*B2 - A2*B1;
366 aRotAngle = ATan (aNumerator / aDenomenator);
369 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
371 myGL.ZRotate.ToRotate = true;
372 myGL.ZRotate.Angle = aRotAngle;
377 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
380 aDeltaSize *= Standard_Real(myTouchZoomRatio);
381 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
382 myGL.ZoomActions.Append (aParams);
386 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
387 ? aTolScale * myTouchPanThresholdPx
389 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
392 if (myUpdateStartPointPan)
394 myGL.Panning.ToStart = true;
395 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
396 myUpdateStartPointPan = false;
397 theView->Invalidate();
400 myGL.Panning.ToPan = true;
401 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
402 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
408 aFirstTouch.From = aFirstTouch.To;
409 aLastTouch .From = aLastTouch.To;
414 // =======================================================================
415 // function : UpdateViewOrientation
417 // =======================================================================
418 void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
421 myUI.Orientation.ToFitAll = theToFitAll;
422 myUI.Orientation.ToSetViewOrient = true;
423 myUI.Orientation.ViewOrient = theOrientation;
426 // =======================================================================
427 // function : SelectInViewer
429 // =======================================================================
430 void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
433 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
435 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
436 myUI.Selection.Points.Clear();
439 myUI.Selection.IsXOR = theIsXOR;
440 myUI.Selection.Points.Append (thePnt);
443 // =======================================================================
444 // function : SelectInViewer
446 // =======================================================================
447 void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
450 myUI.Selection.IsXOR = theIsXOR;
451 myUI.Selection.Points = thePnts;
452 myUI.Selection.ToApplyTool = true;
453 if (thePnts.Length() == 1)
455 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
457 else if (thePnts.Length() == 2)
459 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
463 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
467 // =======================================================================
468 // function : UpdateRubberBand
470 // =======================================================================
471 void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
472 const Graphic3d_Vec2i& thePntTo,
475 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
476 myUI.Selection.IsXOR = theIsXOR;
477 myUI.Selection.Points.Clear();
478 myUI.Selection.Points.Append (thePntFrom);
479 myUI.Selection.Points.Append (thePntTo);
482 // =======================================================================
483 // function : UpdatePolySelection
485 // =======================================================================
486 void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
489 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
491 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
492 myUI.Selection.Points.Clear();
495 if (myUI.Selection.Points.IsEmpty())
497 myUI.Selection.Points.Append (thePnt);
500 && myUI.Selection.Points.Last() != thePnt)
502 myUI.Selection.Points.Append (thePnt);
506 myUI.Selection.Points.ChangeLast() = thePnt;
510 // =======================================================================
511 // function : UpdateZoom
513 // =======================================================================
514 bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
516 if (!myUI.ZoomActions.IsEmpty())
518 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
520 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
525 myUI.ZoomActions.Append (theDelta);
529 // =======================================================================
530 // function : UpdateZRotation
532 // =======================================================================
533 bool AIS_ViewController::UpdateZRotation (double theAngle)
535 if (!ToAllowTouchZRotation())
540 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
541 ? myUI.ZRotate.Angle + theAngle
543 if (myUI.ZRotate.ToRotate)
547 myUI.ZRotate.ToRotate = true;
551 // =======================================================================
552 // function : UpdateMouseScroll
554 // =======================================================================
555 bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
557 Aspect_ScrollDelta aDelta = theDelta;
558 aDelta.Delta *= myScrollZoomRatio;
559 return UpdateZoom (aDelta);
562 // =======================================================================
563 // function : UpdateMouseClick
565 // =======================================================================
566 bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
567 Aspect_VKeyMouse theButton,
568 Aspect_VKeyFlags theModifiers,
569 bool theIsDoubleClick)
571 (void )theIsDoubleClick;
572 if (theButton == Aspect_VKeyMouse_LeftButton)
574 SelectInViewer (thePoint, (theModifiers & Aspect_VKeyFlags_SHIFT) != 0);
580 // =======================================================================
581 // function : UpdateMouseButtons
583 // =======================================================================
584 bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
585 Aspect_VKeyMouse theButtons,
586 Aspect_VKeyFlags theModifiers,
589 bool toUpdateView = false;
590 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
591 if (theButtons == Aspect_VKeyMouse_NONE
592 && myMouseSingleButton > 0)
594 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
595 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
597 ++myMouseClickCounter;
598 const bool isDoubleClick = myMouseClickCounter == 2
599 && myMouseClickTimer.IsStarted()
600 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
602 myMouseClickTimer.Stop();
603 myMouseClickTimer.Reset();
604 myMouseClickTimer.Start();
607 myMouseClickCounter = 0;
609 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
613 myMouseClickTimer.Stop();
614 myMouseClickCounter = 0;
615 myMouseStopDragOnUnclick = false;
616 myUI.Dragging.ToStop = true;
619 myMouseSingleButton = -1;
621 else if (theButtons == Aspect_VKeyMouse_NONE)
623 myMouseSingleButton = -1;
624 if (myMouseStopDragOnUnclick)
626 myMouseStopDragOnUnclick = false;
627 myUI.Dragging.ToStop = true;
631 else if (myMouseSingleButton == -1)
633 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
635 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
637 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
639 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
641 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
643 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
647 myMouseSingleButton = 0;
649 if (myMouseSingleButton != 0)
651 if (myMouseClickCounter == 1)
653 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
654 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
656 myMouseClickTimer.Stop();
657 myMouseClickCounter = 0;
660 myMousePressPoint = thePoint;
665 myMouseSingleButton = 0;
667 myUI.Dragging.ToAbort = true;
671 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
672 myMouseModifiers = theModifiers;
673 myMousePressed = theButtons;
675 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
677 myMouseActiveIdleRotation = false;
678 myMouseActiveGesture = AIS_MouseGesture_NONE;
681 myMousePressPoint = thePoint;
682 myMouseProgressPoint = myMousePressPoint;
685 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
687 switch (myMouseActiveGesture)
689 case AIS_MouseGesture_RotateView:
690 case AIS_MouseGesture_RotateOrbit:
692 if (myToAllowRotation)
694 myUpdateStartPointRot = true;
698 myMouseActiveGesture = AIS_MouseGesture_NONE;
702 case AIS_MouseGesture_Pan:
704 if (myToAllowPanning)
706 myUpdateStartPointPan = true;
710 myMouseActiveGesture = AIS_MouseGesture_NONE;
714 case AIS_MouseGesture_Zoom:
716 if (!myToAllowZooming)
718 myMouseActiveGesture = AIS_MouseGesture_NONE;
722 case AIS_MouseGesture_SelectRectangle:
726 case AIS_MouseGesture_SelectLasso:
728 UpdatePolySelection (thePoint, true);
731 case AIS_MouseGesture_NONE:
738 if (theButtons == Aspect_VKeyMouse_LeftButton
739 && theModifiers == Aspect_VKeyFlags_NONE
740 && myToAllowDragging)
742 myUI.Dragging.ToStart = true;
743 myUI.Dragging.PointStart = thePoint;
747 if (aPrevGesture != myMouseActiveGesture)
749 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
750 || aPrevGesture == AIS_MouseGesture_SelectLasso)
752 myUI.Selection.ToApplyTool = true;
755 myUI.IsNewGesture = true;
761 // =======================================================================
762 // function : UpdateMousePosition
764 // =======================================================================
765 bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
766 Aspect_VKeyMouse theButtons,
767 Aspect_VKeyFlags theModifiers,
770 myMousePositionLast = thePoint;
771 if (myMouseSingleButton > 0)
773 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
774 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
775 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
777 myMouseClickTimer.Stop();
778 myMouseClickCounter = 0;
779 myMouseSingleButton = -1;
780 myMouseStopDragOnUnclick = true;
784 bool toUpdateView = false;
785 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
787 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
789 if (!myMouseActiveIdleRotation
790 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
792 myMouseActiveIdleRotation = true;
793 myMouseActiveGesture = AIS_MouseGesture_RotateView;
794 myMousePressPoint = thePoint;
795 myMouseProgressPoint = thePoint;
796 myUpdateStartPointRot = false;
797 myUI.ViewRotation.ToStart = true;
798 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
799 myUI.ViewRotation.ToRotate = false;
800 aDelta.SetValues (0, 0);
805 if (myMouseActiveIdleRotation
806 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
808 myMouseActiveGesture = AIS_MouseGesture_NONE;
810 myMouseActiveIdleRotation = false;
813 if (myMouseModifiers != theModifiers
814 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
819 switch (myMouseActiveGesture)
821 case AIS_MouseGesture_SelectRectangle:
823 UpdateRubberBand (myMousePressPoint, thePoint);
827 case AIS_MouseGesture_SelectLasso:
829 UpdatePolySelection (thePoint, true);
833 case AIS_MouseGesture_RotateOrbit:
834 case AIS_MouseGesture_RotateView:
836 if (!myToAllowRotation)
840 if (myUpdateStartPointRot)
842 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
844 myUI.OrbitRotation.ToStart = true;
845 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
849 myUI.ViewRotation.ToStart = true;
850 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
852 myUpdateStartPointRot = false;
855 const double aRotTol = theIsEmulated
856 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
858 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
860 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
861 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
862 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
864 myUI.OrbitRotation.ToRotate = true;
865 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
866 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
870 myUI.ViewRotation.ToRotate = true;
871 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
872 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
874 myUI.Dragging.PointTo = thePoint;
876 myMouseProgressPoint = thePoint;
881 case AIS_MouseGesture_Zoom:
883 if (!myToAllowZooming)
887 const double aZoomTol = theIsEmulated
888 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
890 if (double (Abs (aDelta.x())) > aZoomTol)
892 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
896 myMouseProgressPoint = thePoint;
900 case AIS_MouseGesture_Pan:
902 if (!myToAllowPanning)
906 const double aPanTol = theIsEmulated
907 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
909 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
911 if (myUpdateStartPointPan)
913 myUI.Panning.ToStart = true;
914 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
915 myUpdateStartPointPan = false;
918 aDelta.y() = -aDelta.y();
919 myMouseProgressPoint = thePoint;
920 if (myUI.Panning.ToPan)
922 myUI.Panning.Delta += aDelta;
926 myUI.Panning.ToPan = true;
927 myUI.Panning.Delta = aDelta;
939 if (theButtons == Aspect_VKeyMouse_NONE
940 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
943 && myToAllowHighlight)
945 myUI.MoveTo.ToHilight = true;
946 myUI.MoveTo.Point = thePoint;
952 // =======================================================================
953 // function : AddTouchPoint
955 // =======================================================================
956 void AIS_ViewController::AddTouchPoint (Standard_Size theId,
957 const Graphic3d_Vec2d& thePnt,
958 Standard_Boolean theClearBefore)
960 myUI.MoveTo.ToHilight = false;
963 RemoveTouchPoint ((Standard_Size )-1);
966 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
967 if (myTouchPoints.Extent() == 1)
969 myUpdateStartPointRot = true;
970 myStartRotCoord = thePnt;
971 if (myToAllowDragging)
973 myUI.Dragging.ToStart = true;
974 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
977 else if (myTouchPoints.Extent() == 2)
979 myUI.Dragging.ToAbort = true;
981 myUpdateStartPointPan = true;
982 myStartPanCoord = thePnt;
984 myUI.IsNewGesture = true;
987 // =======================================================================
988 // function : RemoveTouchPoint
990 // =======================================================================
991 bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
992 Standard_Boolean theClearSelectPnts)
994 if (theId == (Standard_Size )-1)
996 myTouchPoints.Clear (false);
1000 const Standard_Integer anOldExtent = myTouchPoints.Extent();
1001 myTouchPoints.RemoveKey (theId);
1002 if (myTouchPoints.Extent() == anOldExtent)
1008 if (myTouchPoints.Extent() == 1)
1010 // avoid incorrect transition from pinch to one finger
1011 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1012 aFirstTouch.To = aFirstTouch.From;
1014 myStartRotCoord = aFirstTouch.To;
1015 myUpdateStartPointRot = true;
1017 else if (myTouchPoints.Extent() == 2)
1019 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1020 myUpdateStartPointPan = true;
1022 else if (myTouchPoints.IsEmpty())
1024 if (theClearSelectPnts)
1026 myUI.Selection.ToApplyTool = true;
1029 myUI.Dragging.ToStop = true;
1031 myUI.IsNewGesture = true;
1035 // =======================================================================
1036 // function : UpdateTouchPoint
1038 // =======================================================================
1039 void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1040 const Graphic3d_Vec2d& thePnt)
1042 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1044 aTouch->To = thePnt;
1048 AddTouchPoint (theId, thePnt);
1052 // =======================================================================
1053 // function : SetNavigationMode
1055 // =======================================================================
1056 void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1058 myNavigationMode = theMode;
1061 myUI.OrbitRotation.ToStart = false;
1062 myUI.OrbitRotation.ToRotate = false;
1063 myUI.ViewRotation.ToStart = false;
1064 myUI.ViewRotation.ToRotate = false;
1067 // =======================================================================
1068 // function : KeyDown
1070 // =======================================================================
1071 void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1075 myKeys.KeyDown (theKey, theTime, thePressure);
1078 // =======================================================================
1081 // =======================================================================
1082 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1085 myKeys.KeyUp (theKey, theTime);
1088 // =======================================================================
1089 // function : KeyFromAxis
1091 // =======================================================================
1092 void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1093 Aspect_VKey thePositive,
1097 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1100 // =======================================================================
1101 // function : FetchNavigationKeys
1103 // =======================================================================
1104 AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1105 Standard_Real theRunRatio)
1107 AIS_WalkDelta aWalk;
1110 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1111 updateEventsTime (aPrevEventTime, aNewEventTime);
1113 double aDuration = 0.0, aPressure = 1.0;
1114 if (Abs (myThrustSpeed) > gp::Resolution())
1118 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1121 myToAskNextFrame = true;
1125 myHasThrust = false;
1128 aWalk.SetRunning (theRunRatio > 1.0
1129 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1130 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1132 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1133 aWalk.SetJumping (true);
1135 if (!aWalk.IsJumping()
1136 && theCrouchRatio < 1.0
1137 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1139 aWalk.SetRunning (false);
1140 aWalk.SetCrouching (true);
1143 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1144 const double aRunRatio = aWalk.IsRunning()
1146 : aWalk.IsCrouching()
1149 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1151 double aProgress = Abs (Min (aMaxDuration, aDuration));
1152 aProgress *= aRunRatio;
1153 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1154 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1155 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1157 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1159 double aProgress = Abs (Min (aMaxDuration, aDuration));
1160 aProgress *= aRunRatio;
1161 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1162 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1163 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1165 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1167 double aProgress = Abs (Min (aMaxDuration, aDuration));
1168 aProgress *= aRunRatio;
1169 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1170 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1171 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1173 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1175 double aProgress = Abs (Min (aMaxDuration, aDuration));
1176 aProgress *= aRunRatio;
1177 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1178 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1179 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1181 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1183 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1184 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1185 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1186 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1188 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1190 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1191 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1192 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1193 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1195 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1197 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1198 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1199 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1200 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1202 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1204 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1205 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1206 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1207 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1209 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1211 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1212 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1213 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1214 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1216 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1218 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1219 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1220 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1221 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1223 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1225 double aProgress = Abs (Min (aMaxDuration, aDuration));
1226 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1227 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1228 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1230 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1232 double aProgress = Abs (Min (aMaxDuration, aDuration));
1233 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1234 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1235 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1240 // =======================================================================
1241 // function : AbortViewAnimation
1243 // =======================================================================
1244 void AIS_ViewController::AbortViewAnimation()
1246 if (!myViewAnimation.IsNull()
1247 && !myViewAnimation->IsStopped())
1249 myViewAnimation->Stop();
1250 myViewAnimation->SetView (Handle(V3d_View)());
1254 // =======================================================================
1255 // function : handlePanning
1257 // =======================================================================
1258 void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1260 if (!myGL.Panning.ToPan
1261 || !myToAllowPanning)
1266 AbortViewAnimation();
1268 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1269 if (aCam->IsOrthographic()
1270 || !hasPanningAnchorPoint())
1272 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1273 theView->Invalidate();
1277 Graphic3d_Vec2i aWinSize;
1278 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1280 const gp_Dir& aDir = aCam->Direction();
1281 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1282 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1283 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1284 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1285 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1287 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1289 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1290 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1291 aPanTrsf.SetTranslation (aCameraPan);
1292 aCam->Transform (aPanTrsf);
1293 theView->Invalidate();
1296 // =======================================================================
1297 // function : handleZRotate
1299 // =======================================================================
1300 void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1302 if (!myGL.ZRotate.ToRotate
1303 || !myToAllowRotation)
1308 AbortViewAnimation();
1310 Graphic3d_Vec2i aViewPort;
1311 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1312 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1313 0.5 * aViewPort.y());
1314 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1315 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1316 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1317 theView->Invalidate();
1320 // =======================================================================
1321 // function : handleZoom
1323 // =======================================================================
1324 void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1325 const Aspect_ScrollDelta& theParams,
1326 const gp_Pnt* thePnt)
1328 if (!myToAllowZooming)
1333 AbortViewAnimation();
1335 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1338 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1339 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1342 if (!theParams.HasPoint())
1344 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1345 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1346 theView->SetZoom (aCoeff, true);
1347 theView->Invalidate();
1351 // integer delta is too rough for small smooth increments
1352 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1353 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1355 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1356 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1362 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1364 // ensure that zoom will not be too small or too big
1365 double aCoef = aDZoom;
1366 if (aViewDims.x() < aCoef * Precision::Confusion())
1368 aCoef = aViewDims.x() / Precision::Confusion();
1370 else if (aViewDims.x() > aCoef * 1e12)
1372 aCoef = aViewDims.x() / 1e12;
1374 if (aViewDims.y() < aCoef * Precision::Confusion())
1376 aCoef = aViewDims.y() / Precision::Confusion();
1378 else if (aViewDims.y() > aCoef * 1e12)
1380 aCoef = aViewDims.y() / 1e12;
1383 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1384 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1385 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1386 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1387 aCam->SetScale (aCam->Scale() / aCoef);
1389 const gp_Dir& aDir = aCam->Direction();
1390 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1392 // pan back to the point
1393 aDxy = aZoomAtPointXYv - aDxy;
1396 // zoom at 3D point with perspective projection
1397 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1398 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1399 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1401 // view dimensions at 3D point
1402 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1404 Graphic3d_Vec2i aWinSize;
1405 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1406 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
1407 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
1408 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
1409 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
1412 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1414 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1415 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1416 aPanTrsf.SetTranslation (aCameraPan);
1417 aCam->Transform (aPanTrsf);
1418 theView->Invalidate();
1421 // =======================================================================
1422 // function : handleZFocusScroll
1424 // =======================================================================
1425 void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1426 const Aspect_ScrollDelta& theParams)
1428 if (!myToAllowZFocus
1429 || !theView->Camera()->IsStereo())
1434 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1438 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1443 // =======================================================================
1444 // function : handleOrbitRotation
1446 // =======================================================================
1447 void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1448 const gp_Pnt& thePnt,
1451 if (!myToAllowRotation)
1456 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1457 if (myGL.OrbitRotation.ToStart)
1459 // default alternatives
1460 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1461 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1463 myRotatePnt3d = thePnt;
1464 myCamStartOpUp = aCam->Up();
1465 myCamStartOpDir = aCam->Direction();
1466 myCamStartOpEye = aCam->Eye();
1467 myCamStartOpCenter = aCam->Center();
1470 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1471 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1472 const gp_Quaternion aRot = aTrsf.GetRotation();
1473 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1476 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1477 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1479 theView->Invalidate();
1482 if (!myGL.OrbitRotation.ToRotate)
1487 AbortViewAnimation();
1490 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1491 Graphic3d_Vec2i aWinXY;
1492 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1493 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1494 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1495 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1496 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1497 const double aRoll = 0.0;
1500 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1502 aTrsfRot.SetRotation (aRot);
1504 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1505 aCam->SetUp (aNewUp);
1506 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1507 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1509 aCam->OrthogonalizeUp();
1513 // default alternatives
1514 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1515 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1517 // restore previous camera state
1518 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1519 aCam->SetUp (myCamStartOpUp);
1520 aCam->SetDirectionFromEye (myCamStartOpDir);
1522 Graphic3d_Vec2d aWinXY;
1523 theView->Size (aWinXY.x(), aWinXY.y());
1524 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1525 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1527 const double THE_2PI = M_PI * 2.0;
1528 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1529 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1531 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1532 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1533 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1534 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1536 // rotate camera around 3 initial axes
1537 gp_Dir aCamDir (aCam->Direction().Reversed());
1538 gp_Dir aCamUp (aCam->Up());
1539 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1541 gp_Trsf aRot[2], aTrsf;
1542 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1543 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1544 aTrsf.Multiply (aRot[0]);
1545 aTrsf.Multiply (aRot[1]);
1547 aCam->Transform (aTrsf);
1550 theView->Invalidate();
1553 // =======================================================================
1554 // function : handleViewRotation
1556 // =======================================================================
1557 void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1559 double thePitchExtra,
1561 bool theToRestartOnIncrement)
1563 if (!myToAllowRotation)
1568 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1569 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1570 || Abs (thePitchExtra) > gp::Resolution()
1571 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1573 && theToRestartOnIncrement)
1575 myGL.ViewRotation.ToStart = true;
1576 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1578 if (myGL.ViewRotation.ToStart)
1581 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1582 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1583 const gp_Quaternion aRot = aTrsf.GetRotation();
1584 double aRollDummy = 0.0;
1585 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1589 myRotateStartYawPitchRoll[0] += theYawExtra;
1590 myRotateStartYawPitchRoll[1] += thePitchExtra;
1591 myRotateStartYawPitchRoll[2] = theRoll;
1592 myGL.ViewRotation.ToRotate = true;
1595 if (!myGL.ViewRotation.ToRotate)
1600 AbortViewAnimation();
1602 Graphic3d_Vec2i aWinXY;
1603 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1604 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1605 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1606 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1607 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1609 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1611 aTrsfRot.SetRotation (aRot);
1613 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1614 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
1615 aCam->SetUp (aNewUp);
1616 aCam->SetDirectionFromEye (aNewDir);
1617 aCam->OrthogonalizeUp();
1618 theView->Invalidate();
1621 // =======================================================================
1622 // function : PickPoint
1624 // =======================================================================
1625 bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1626 const Handle(AIS_InteractiveContext)& theCtx,
1627 const Handle(V3d_View)& theView,
1628 const Graphic3d_Vec2i& theCursor,
1629 bool theToStickToPickRay)
1631 ResetPreviousMoveTo();
1633 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1634 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1635 if (aSelector->NbPicked() < 1)
1640 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1641 if (theToStickToPickRay
1642 && !Precision::IsInfinite (aPicked.Depth))
1644 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1648 thePnt = aSelector->PickedPoint (1);
1650 return !Precision::IsInfinite (thePnt.X())
1651 && !Precision::IsInfinite (thePnt.Y())
1652 && !Precision::IsInfinite (thePnt.Z());
1655 // =======================================================================
1656 // function : GravityPoint
1658 // =======================================================================
1659 gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1660 const Handle(V3d_View)& theView)
1662 switch (myRotationMode)
1664 case AIS_RotationMode_PickLast:
1665 case AIS_RotationMode_PickCenter:
1667 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1668 if (myRotationMode == AIS_RotationMode_PickCenter)
1670 Graphic3d_Vec2i aViewPort;
1671 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1672 aCursor = aViewPort / 2;
1676 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
1682 case AIS_RotationMode_CameraAt:
1684 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1685 return aCam->Center();
1687 case AIS_RotationMode_BndBoxScene:
1689 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1690 if (!aBndBox.IsVoid())
1692 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1696 case AIS_RotationMode_BndBoxActive:
1700 return theCtx ->GravityPoint (theView);
1703 // =======================================================================
1704 // function : handleCameraActions
1706 // =======================================================================
1707 void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
1708 const Handle(V3d_View)& theView,
1709 const AIS_WalkDelta& theWalk)
1711 // apply view actions
1712 if (myGL.Orientation.ToSetViewOrient)
1714 theView->SetProj (myGL.Orientation.ViewOrient);
1715 myGL.Orientation.ToFitAll = true;
1719 if (myGL.Orientation.ToFitAll)
1721 const double aFitMargin = 0.01;
1722 theView->FitAll (aFitMargin, false);
1723 theView->Invalidate();
1724 myGL.Orientation.ToFitAll = false;
1727 if (myGL.IsNewGesture)
1729 if (myAnchorPointPrs1->HasInteractiveContext())
1731 theCtx->Remove (myAnchorPointPrs1, false);
1732 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
1734 theView->Invalidate();
1738 theView->InvalidateImmediate();
1741 if (myAnchorPointPrs2->HasInteractiveContext())
1743 theCtx->Remove (myAnchorPointPrs2, false);
1744 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
1746 theView->Invalidate();
1750 theView->InvalidateImmediate();
1754 if (myHasHlrOnBeforeRotation)
1756 myHasHlrOnBeforeRotation = false;
1757 theView->SetComputedMode (true);
1758 theView->Invalidate();
1762 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
1764 if (myGL.Panning.ToStart
1765 && myToAllowPanning)
1767 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
1768 if (!theView->Camera()->IsOrthographic())
1770 bool toStickToRay = false;
1771 if (myGL.Panning.PointStart.x() >= 0
1772 && myGL.Panning.PointStart.y() >= 0)
1774 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
1776 if (Precision::IsInfinite (aPanPnt.X()))
1778 Graphic3d_Vec2i aWinSize;
1779 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1780 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
1782 if (!Precision::IsInfinite (aPanPnt.X())
1783 && myToShowPanAnchorPoint)
1786 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
1787 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1790 setPanningAnchorPoint (aPanPnt);
1793 if (myToShowPanAnchorPoint
1794 && hasPanningAnchorPoint()
1795 && myGL.Panning.ToPan
1796 && !myGL.IsNewGesture
1797 && !myAnchorPointPrs2->HasInteractiveContext())
1799 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1802 handlePanning (theView);
1803 handleZRotate (theView);
1806 if ((myNavigationMode == AIS_NavigationMode_Orbit
1807 || myGL.OrbitRotation.ToStart
1808 || myGL.OrbitRotation.ToRotate)
1809 && myToAllowRotation)
1811 if (myGL.OrbitRotation.ToStart
1812 && !myHasHlrOnBeforeRotation)
1814 myHasHlrOnBeforeRotation = theView->ComputedMode();
1815 if (myHasHlrOnBeforeRotation)
1817 theView->SetComputedMode (false);
1822 if (myGL.OrbitRotation.ToStart)
1824 aGravPnt = GravityPoint (theCtx, theView);
1825 if (myToShowRotateCenter)
1828 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
1829 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
1830 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1834 if (myToShowRotateCenter
1835 && myGL.OrbitRotation.ToRotate
1836 && !myGL.IsNewGesture
1837 && !myAnchorPointPrs1->HasInteractiveContext())
1839 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
1840 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1842 handleOrbitRotation (theView, aGravPnt,
1843 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
1846 if ((myNavigationMode != AIS_NavigationMode_Orbit
1847 || myGL.ViewRotation.ToStart
1848 || myGL.ViewRotation.ToRotate)
1849 && myToAllowRotation)
1851 if (myGL.ViewRotation.ToStart
1852 && !myHasHlrOnBeforeRotation)
1854 myHasHlrOnBeforeRotation = theView->ComputedMode();
1855 if (myHasHlrOnBeforeRotation)
1857 theView->SetComputedMode (false);
1862 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
1863 && !myToLockOrbitZUp)
1865 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
1866 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
1867 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
1873 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
1874 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
1877 if (!myGL.ZoomActions.IsEmpty())
1879 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
1881 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
1883 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
1884 && theView->Camera()->IsStereo())
1886 handleZFocusScroll (theView, aZoomParams);
1890 if (!myToAllowZooming)
1895 if (!theView->Camera()->IsOrthographic())
1898 if (aZoomParams.HasPoint()
1899 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
1901 handleZoom (theView, aZoomParams, &aPnt);
1905 Graphic3d_Vec2i aWinSize;
1906 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1907 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom))
1909 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
1910 handleZoom (theView, aZoomParams, &aPnt);
1914 handleZoom (theView, aZoomParams, NULL);
1916 myGL.ZoomActions.Clear();
1920 // =======================================================================
1921 // function : OnSelectionChanged
1923 // =======================================================================
1924 void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
1925 const Handle(V3d_View)& )
1930 // =======================================================================
1931 // function : OnObjectDragged
1933 // =======================================================================
1934 void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
1935 const Handle(V3d_View)& theView,
1936 AIS_DragAction theAction)
1940 case AIS_DragAction_Start:
1942 myDragObject.Nullify();
1943 if (!theCtx->HasDetected())
1948 Handle(AIS_InteractiveObject) aPrs = theCtx->DetectedInteractive();
1949 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (aPrs))
1951 if (aManip->HasActiveMode())
1953 myDragObject = aManip;
1954 aManip->StartTransform (myGL.Dragging.PointStart.x(), myGL.Dragging.PointStart.y(), theView);
1959 case AIS_DragAction_Update:
1961 if (myDragObject.IsNull())
1966 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
1968 theCtx->SetSelectedState (aGlobOwner, true);
1970 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1972 aManip->Transform (myGL.Dragging.PointTo.x(), myGL.Dragging.PointTo.y(), theView);
1974 theView->Invalidate();
1977 case AIS_DragAction_Abort:
1979 if (myDragObject.IsNull())
1984 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
1985 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
1987 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1989 aManip->StopTransform (false);
1991 Standard_FALLTHROUGH
1993 case AIS_DragAction_Stop:
1995 if (myDragObject.IsNull())
2000 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2002 theCtx->SetSelectedState (aGlobOwner, false);
2005 theView->Invalidate();
2006 myDragObject.Nullify();
2012 // =======================================================================
2013 // function : contextLazyMoveTo
2015 // =======================================================================
2016 void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2017 const Handle(V3d_View)& theView,
2018 const Graphic3d_Vec2i& thePnt)
2020 if (myPrevMoveTo == thePnt)
2025 myPrevMoveTo = thePnt;
2027 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2028 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2029 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2031 if (theView->Viewer()->Grid()->IsActive()
2032 && theView->Viewer()->GridEcho())
2034 if (aNewPicked.IsNull())
2036 Graphic3d_Vec3d aPnt3d;
2037 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2038 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2039 theView->InvalidateImmediate();
2043 theView->Viewer()->HideGridEcho (theView);
2044 theView->InvalidateImmediate();
2048 if (aLastPicked != aNewPicked
2049 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2051 // dynamic highlight affects all Views
2052 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2054 const Handle(V3d_View)& aView = aViewIter.Value();
2055 aView->InvalidateImmediate();
2060 // =======================================================================
2061 // function : handleSelectionPick
2063 // =======================================================================
2064 void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2065 const Handle(V3d_View)& theView)
2067 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2068 && !myGL.Selection.Points.IsEmpty())
2070 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2072 const bool hadPrevMoveTo = HasPreviousMoveTo();
2073 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2076 ResetPreviousMoveTo();
2079 if (myGL.Selection.IsXOR)
2081 theCtx->ShiftSelect (false);
2085 theCtx->Select (false);
2088 // selection affects all Views
2089 theView->Viewer()->Invalidate();
2091 OnSelectionChanged (theCtx, theView);
2094 myGL.Selection.Points.Clear();
2098 // =======================================================================
2099 // function : handleSelectionPoly
2101 // =======================================================================
2102 void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2103 const Handle(V3d_View)& theView)
2105 // rubber-band & window polygon selection
2106 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2107 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon)
2109 if (!myGL.Selection.Points.IsEmpty())
2111 myRubberBand->ClearPoints();
2112 myRubberBand->SetToUpdate();
2114 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand;
2117 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2118 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2122 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2123 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2125 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2126 if (aPntNew != aPrev)
2129 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2134 myRubberBand->SetPolygonClosed (anIsRubber);
2137 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2139 catch (const Standard_Failure& theEx)
2141 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2142 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString(), Message_Warning);
2143 myRubberBand->ClearPoints();
2145 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2147 theView->Invalidate();
2151 theView->InvalidateImmediate();
2154 else if (!myRubberBand.IsNull()
2155 && myRubberBand->HasInteractiveContext())
2157 theCtx->Remove (myRubberBand, false);
2158 myRubberBand->ClearPoints();
2162 if (myGL.Selection.ToApplyTool)
2164 myGL.Selection.ToApplyTool = false;
2165 if (theCtx->IsDisplayed (myRubberBand))
2167 theCtx->Remove (myRubberBand, false);
2169 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2170 if (aPoints.Size() == 4
2171 && aPoints.Value (1).x() == aPoints.Value (2).x()
2172 && aPoints.Value (3).x() == aPoints.Value (4).x()
2173 && aPoints.Value (1).y() == aPoints.Value (4).y()
2174 && aPoints.Value (2).y() == aPoints.Value (3).y())
2176 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2177 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
2178 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2179 if (myGL.Selection.IsXOR)
2181 theCtx->ShiftSelect (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2182 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2187 theCtx->Select (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2188 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2191 theCtx->MainSelector()->AllowOverlapDetection (false);
2193 else if (aPoints.Length() >= 3)
2195 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2196 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2197 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2198 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2200 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2201 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2204 theCtx->MainSelector()->AllowOverlapDetection (false);
2205 if (myGL.Selection.IsXOR)
2207 theCtx->ShiftSelect (aPolyline, theView, false);
2211 theCtx->Select (aPolyline, theView, false);
2216 // selection affects all Views
2217 theView->Viewer()->Invalidate();
2219 myRubberBand->ClearPoints();
2220 OnSelectionChanged (theCtx, theView);
2225 // =======================================================================
2226 // function : handleDynamicHighlight
2228 // =======================================================================
2229 void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2230 const Handle(V3d_View)& theView)
2232 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2233 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2235 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2236 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2237 && !HasPreviousMoveTo())
2239 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2240 ResetPreviousMoveTo();
2241 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2242 theCtx->ClearDetected();
2244 else if (myToAllowHighlight)
2246 if (myPrevMoveTo != aMoveToPnt
2247 || myGL.OrbitRotation.ToRotate
2248 || myGL.ViewRotation.ToRotate
2249 || theView->IsInvalidated())
2251 ResetPreviousMoveTo();
2252 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2254 if (myGL.Dragging.ToStart)
2256 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2260 myGL.MoveTo.ToHilight = false;
2263 if (!myDragObject.IsNull())
2265 if (myGL.Dragging.ToAbort)
2267 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2268 myGL.OrbitRotation.ToRotate = false;
2269 myGL.ViewRotation .ToRotate = false;
2271 else if (myGL.Dragging.ToStop)
2273 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2274 myGL.OrbitRotation.ToRotate = false;
2275 myGL.ViewRotation .ToRotate = false;
2277 else if (myGL.OrbitRotation.ToRotate
2278 || myGL.ViewRotation.ToRotate)
2280 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2281 myGL.OrbitRotation.ToRotate = false;
2282 myGL.ViewRotation .ToRotate = false;
2287 // =======================================================================
2288 // function : handleMoveTo
2290 // =======================================================================
2291 void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2292 const Handle(V3d_View)& theView)
2294 handleSelectionPick (theCtx, theView);
2295 handleDynamicHighlight(theCtx, theView);
2296 handleSelectionPoly (theCtx, theView);
2299 // =======================================================================
2300 // function : handleViewRedraw
2302 // =======================================================================
2303 void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2304 const Handle(V3d_View)& theView)
2306 // manage animation state
2307 if (!myViewAnimation.IsNull()
2308 && !myViewAnimation->IsStopped())
2310 myViewAnimation->UpdateTimer();
2311 ResetPreviousMoveTo();
2315 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2317 const Handle(V3d_View)& aView = aViewIter.Value();
2318 if (aView->IsInvalidated()
2319 || myToAskNextFrame)
2321 if (aView->ComputedMode())
2330 else if (aView->IsInvalidatedImmediate())
2332 aView->RedrawImmediate();
2336 if (myToAskNextFrame)
2339 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
2343 // =======================================================================
2344 // function : HandleViewEvents
2346 // =======================================================================
2347 void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
2348 const Handle(V3d_View)& theView)
2350 handleMoveTo (theCtx, theView);
2352 const AIS_WalkDelta aWalk = FetchNavigationKeys (1.0, 1.0);
2353 handleCameraActions (theCtx, theView, aWalk);
2354 handleViewRedraw (theCtx, theView);
2356 // make sure to not process the same events twice
2358 myToAskNextFrame = false;