0031321: C# wrapper - wrap AIS_ViewController
[occt.git] / src / AIS / AIS_ViewController.cxx
CommitLineData
49582f9d 1// Copyright (c) 2016-2019 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
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.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
14#include "AIS_ViewController.hxx"
15
2108d9a2 16#include <AIS_AnimationCamera.hxx>
49582f9d 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>
27
28// =======================================================================
29// function : AIS_ViewController
30// purpose :
31// =======================================================================
32AIS_ViewController::AIS_ViewController()
33: myLastEventsTime (0.0),
34 myToAskNextFrame (false),
35 myMinCamDistance (1.0),
36 myRotationMode (AIS_RotationMode_BndBoxActive),
37 myNavigationMode (AIS_NavigationMode_Orbit),
38 myMouseAccel (1.0f),
39 myOrbitAccel (1.0f),
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),
9460f8c0 51 myToStickToRayOnZoom (true),
52 myToStickToRayOnRotation (true),
49582f9d 53 //
54 myWalkSpeedAbsolute (1.5f),
55 myWalkSpeedRelative (0.1f),
56 myThrustSpeed (0.0f),
57 myHasThrust (false),
58 //
2108d9a2 59 myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
49582f9d 60 myPrevMoveTo (-1, -1),
61 myHasHlrOnBeforeRotation (false),
62 //
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),
215dd331 72 myMouseStopDragOnUnclick (false),
49582f9d 73 //
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),
80 //
81 myNbTouchesLast (0),
82 myUpdateStartPointPan (true),
83 myUpdateStartPointRot (true),
84 myUpdateStartPointZRot (true),
85 //
86 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
87{
88 myEventTimer.Start();
89
90 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
91 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
92 myAnchorPointPrs1->SetMutable (true);
93
94 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
95 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
96 myAnchorPointPrs2->SetMutable (true);
97
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);
103
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);
108
109 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
110 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
111
112 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
113 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
114}
115
00ea7f26 116// =======================================================================
117// function : ~AIS_ViewController
118// purpose :
119// =======================================================================
120AIS_ViewController::~AIS_ViewController()
121{
122 //
123}
124
49582f9d 125// =======================================================================
126// function : ResetViewInput
127// purpose :
128// =======================================================================
129void AIS_ViewController::ResetViewInput()
130{
131 myKeys.Reset();
132 myMousePressed = Aspect_VKeyMouse_NONE;
133 myMouseModifiers = Aspect_VKeyFlags_NONE;
134 myMouseSingleButton = -1;
135 myUI.Dragging.ToAbort = true;
136 myMouseActiveGesture = AIS_MouseGesture_NONE;
137 myMouseClickTimer.Stop();
138 myMouseClickCounter = 0;
139}
140
141// =======================================================================
142// function : FlushViewEvents
143// purpose :
144// =======================================================================
145void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
146 const Handle(V3d_View)& theView,
147 Standard_Boolean theToHandle)
148{
149 flushBuffers (theCtx, theView);
150 flushGestures(theCtx, theView);
151 if (theToHandle)
152 {
153 HandleViewEvents (theCtx, theView);
154 }
155}
156
157// =======================================================================
158// function : flushBuffers
159// purpose :
160// =======================================================================
161void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
162 const Handle(V3d_View)& )
163{
164 myToAskNextFrame = false;
165
166 myGL.IsNewGesture = myUI.IsNewGesture;
167 myUI.IsNewGesture = false;
168
169 myGL.ZoomActions.Clear();
170 myGL.ZoomActions.Append (myUI.ZoomActions);
171 myUI.ZoomActions.Clear();
172
173 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
174 myUI.Orientation.ToFitAll = false;
175 if (myUI.Orientation.ToSetViewOrient)
176 {
177 myUI.Orientation.ToSetViewOrient = false;
178 myGL.Orientation.ToSetViewOrient = true;
179 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
180 }
181
182 if (myUI.MoveTo.ToHilight)
183 {
184 myUI.MoveTo.ToHilight = false;
185 myGL.MoveTo.ToHilight = true;
186 myGL.MoveTo.Point = myUI.MoveTo.Point;
187 }
188
189 {
190 myGL.Selection.Tool = myUI.Selection.Tool;
191 myGL.Selection.IsXOR = myUI.Selection.IsXOR;
192 myGL.Selection.Points = myUI.Selection.Points;
193 myUI.Selection.IsXOR = false;
194 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
195 {
196 myUI.Selection.Points.Clear();
197 }
198 }
199
200 if (myUI.Selection.ToApplyTool)
201 {
202 myGL.Selection.ToApplyTool = true;
203 myUI.Selection.ToApplyTool = false;
204 myUI.Selection.Points.Clear();
205 }
206
207 if (myUI.Panning.ToStart)
208 {
209 myUI.Panning.ToStart = false;
210 myGL.Panning.ToStart = true;
211 myGL.Panning.PointStart = myUI.Panning.PointStart;
212 }
213
214 if (myUI.Panning.ToPan)
215 {
216 myUI.Panning.ToPan = false;
217 myGL.Panning.ToPan = true;
218 myGL.Panning.Delta = myUI.Panning.Delta;
219 }
220
221 if (myUI.Dragging.ToAbort)
222 {
223 myUI.Dragging.ToAbort = false;
224 myGL.Dragging.ToAbort = true;
225 }
226 else if (myUI.Dragging.ToStop)
227 {
228 myUI.Dragging.ToStop = false;
229 myGL.Dragging.ToStop = true;
230 }
231 else if (myUI.Dragging.ToStart)
232 {
233 myUI.Dragging.ToStart = false;
234 myGL.Dragging.ToStart = true;
235 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
236 }
237 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
238
239 if (myUI.OrbitRotation.ToStart)
240 {
241 myUI.OrbitRotation.ToStart = false;
242 myGL.OrbitRotation.ToStart = true;
243 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
244 }
245
246 if (myUI.OrbitRotation.ToRotate)
247 {
248 myUI.OrbitRotation.ToRotate = false;
249 myGL.OrbitRotation.ToRotate = true;
250 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
251 }
252
253 if (myUI.ViewRotation.ToStart)
254 {
255 myUI.ViewRotation.ToStart = false;
256 myGL.ViewRotation.ToStart = true;
257 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
258 }
259
260 if (myUI.ViewRotation.ToRotate)
261 {
262 myUI.ViewRotation.ToRotate = false;
263 myGL.ViewRotation.ToRotate = true;
264 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
265 }
266
267 if (myUI.ZRotate.ToRotate)
268 {
269 myGL.ZRotate = myUI.ZRotate;
270 myUI.ZRotate.ToRotate = false;
271 }
272}
273
274// =======================================================================
275// function : flushGestures
276// purpose :
277// =======================================================================
278void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
279 const Handle(V3d_View)& theView)
280{
281 const Standard_Real aTolScale = myTouchToleranceScale;
282 const Standard_Integer aTouchNb = myTouchPoints.Extent();
283 if (myNbTouchesLast != aTouchNb)
284 {
285 myNbTouchesLast = aTouchNb;
286 myGL.IsNewGesture = true;
287 }
288 if (aTouchNb == 1) // touch
289 {
290 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
291 if (myUpdateStartPointRot)
292 {
293 // skip rotation if have active dragged object
294 if (myNavigationMode == AIS_NavigationMode_Orbit)
295 {
296 myGL.OrbitRotation.ToStart = true;
297 myGL.OrbitRotation.PointStart = myStartRotCoord;
298 }
299 else
300 {
301 myGL.ViewRotation.ToStart = true;
302 myGL.ViewRotation.PointStart = myStartRotCoord;
303 }
304
305 myUpdateStartPointRot = false;
306 theView->Invalidate();
307 }
308
309 // rotation
310 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
311 ? aTolScale * myTouchRotationThresholdPx
312 : gp::Resolution();
313 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
314 {
315 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
316 if (myNavigationMode == AIS_NavigationMode_Orbit)
317 {
318 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
319 myGL.OrbitRotation.ToRotate = true;
320 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
321 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
322 }
323 else
324 {
325 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
326 myGL.ViewRotation.ToRotate = true;
327 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
328 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
329 }
330
331 aTouch.From = aTouch.To;
332 }
333 }
334 else if (aTouchNb == 2) // pinch
335 {
336 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
337 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
338 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
339 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
340
341 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
342 (aFrom[0].y() + aFrom[1].y()) / 2.0);
343
344 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
345 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
346
347 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
348 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
349
350 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
351 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
352
353 Standard_Real aDeltaSize = anEndSize - aStartSize;
354
355 bool anIsClearDev = false;
356
357 if (myToAllowTouchZRotation)
358 {
359 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
360 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
361
362 Standard_Real A2 = aTo[0].y() - aTo[1].y();
363 Standard_Real B2 = aTo[1].x() - aTo[0].x();
364
365 Standard_Real aRotAngle = 0.0;
366
367 Standard_Real aDenomenator = A1*A2 + B1*B2;
368 if (aDenomenator <= Precision::Confusion())
369 {
370 aRotAngle = 0.0;
371 }
372 else
373 {
374 Standard_Real aNumerator = A1*B2 - A2*B1;
375 aRotAngle = ATan (aNumerator / aDenomenator);
376 }
377
378 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
379 {
380 myGL.ZRotate.ToRotate = true;
381 myGL.ZRotate.Angle = aRotAngle;
382 anIsClearDev = true;
383 }
384 }
385
386 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
387 {
388 // zoom
389 aDeltaSize *= Standard_Real(myTouchZoomRatio);
390 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
391 myGL.ZoomActions.Append (aParams);
392 anIsClearDev = true;
393 }
394
395 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
396 ? aTolScale * myTouchPanThresholdPx
397 : gp::Resolution();
398 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
399 {
400 // pan
401 if (myUpdateStartPointPan)
402 {
403 myGL.Panning.ToStart = true;
404 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
405 myUpdateStartPointPan = false;
406 theView->Invalidate();
407 }
408
409 myGL.Panning.ToPan = true;
410 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
411 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
412 anIsClearDev = true;
413 }
414
415 if (anIsClearDev)
416 {
417 aFirstTouch.From = aFirstTouch.To;
418 aLastTouch .From = aLastTouch.To;
419 }
420 }
421}
422
423// =======================================================================
424// function : UpdateViewOrientation
425// purpose :
426// =======================================================================
427void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
428 bool theToFitAll)
429{
430 myUI.Orientation.ToFitAll = theToFitAll;
431 myUI.Orientation.ToSetViewOrient = true;
432 myUI.Orientation.ViewOrient = theOrientation;
433}
434
435// =======================================================================
436// function : SelectInViewer
437// purpose :
438// =======================================================================
439void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
440 const bool theIsXOR)
441{
442 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
443 {
444 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
445 myUI.Selection.Points.Clear();
446 }
447
448 myUI.Selection.IsXOR = theIsXOR;
449 myUI.Selection.Points.Append (thePnt);
450}
451
452// =======================================================================
453// function : SelectInViewer
454// purpose :
455// =======================================================================
456void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
457 const bool theIsXOR)
458{
459 myUI.Selection.IsXOR = theIsXOR;
460 myUI.Selection.Points = thePnts;
461 myUI.Selection.ToApplyTool = true;
462 if (thePnts.Length() == 1)
463 {
464 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
465 }
466 else if (thePnts.Length() == 2)
467 {
468 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
469 }
470 else
471 {
472 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
473 }
474}
475
476// =======================================================================
477// function : UpdateRubberBand
478// purpose :
479// =======================================================================
480void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
481 const Graphic3d_Vec2i& thePntTo,
482 const bool theIsXOR)
483{
484 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
485 myUI.Selection.IsXOR = theIsXOR;
486 myUI.Selection.Points.Clear();
487 myUI.Selection.Points.Append (thePntFrom);
488 myUI.Selection.Points.Append (thePntTo);
489}
490
491// =======================================================================
492// function : UpdatePolySelection
493// purpose :
494// =======================================================================
495void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
496 bool theToAppend)
497{
498 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
499 {
500 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
501 myUI.Selection.Points.Clear();
502 }
503
504 if (myUI.Selection.Points.IsEmpty())
505 {
506 myUI.Selection.Points.Append (thePnt);
507 }
508 else if (theToAppend
509 && myUI.Selection.Points.Last() != thePnt)
510 {
511 myUI.Selection.Points.Append (thePnt);
512 }
513 else
514 {
515 myUI.Selection.Points.ChangeLast() = thePnt;
516 }
517}
518
519// =======================================================================
520// function : UpdateZoom
521// purpose :
522// =======================================================================
523bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
524{
525 if (!myUI.ZoomActions.IsEmpty())
526 {
527 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
528 {
529 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
530 return false;
531 }
532 }
533
534 myUI.ZoomActions.Append (theDelta);
535 return true;
536}
537
538// =======================================================================
539// function : UpdateZRotation
540// purpose :
541// =======================================================================
542bool AIS_ViewController::UpdateZRotation (double theAngle)
543{
544 if (!ToAllowTouchZRotation())
545 {
546 return false;
547 }
548
549 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
550 ? myUI.ZRotate.Angle + theAngle
551 : theAngle;
552 if (myUI.ZRotate.ToRotate)
553 {
554 return false;
555 }
556 myUI.ZRotate.ToRotate = true;
557 return true;
558}
559
560// =======================================================================
561// function : UpdateMouseScroll
562// purpose :
563// =======================================================================
564bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
565{
566 Aspect_ScrollDelta aDelta = theDelta;
567 aDelta.Delta *= myScrollZoomRatio;
568 return UpdateZoom (aDelta);
569}
570
571// =======================================================================
572// function : UpdateMouseClick
573// purpose :
574// =======================================================================
575bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
576 Aspect_VKeyMouse theButton,
577 Aspect_VKeyFlags theModifiers,
578 bool theIsDoubleClick)
579{
580 (void )theIsDoubleClick;
581 if (theButton == Aspect_VKeyMouse_LeftButton)
582 {
583 SelectInViewer (thePoint, (theModifiers & Aspect_VKeyFlags_SHIFT) != 0);
584 return true;
585 }
586 return false;
587}
588
589// =======================================================================
590// function : UpdateMouseButtons
591// purpose :
592// =======================================================================
593bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
594 Aspect_VKeyMouse theButtons,
595 Aspect_VKeyFlags theModifiers,
596 bool theIsEmulated)
597{
598 bool toUpdateView = false;
599 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
600 if (theButtons == Aspect_VKeyMouse_NONE
601 && myMouseSingleButton > 0)
602 {
603 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
604 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
605 {
606 ++myMouseClickCounter;
607 const bool isDoubleClick = myMouseClickCounter == 2
608 && myMouseClickTimer.IsStarted()
609 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
610
611 myMouseClickTimer.Stop();
612 myMouseClickTimer.Reset();
613 myMouseClickTimer.Start();
614 if (isDoubleClick)
615 {
616 myMouseClickCounter = 0;
617 }
618 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
619 }
620 else
621 {
622 myMouseClickTimer.Stop();
623 myMouseClickCounter = 0;
215dd331 624 myMouseStopDragOnUnclick = false;
49582f9d 625 myUI.Dragging.ToStop = true;
626 toUpdateView = true;
627 }
628 myMouseSingleButton = -1;
629 }
630 else if (theButtons == Aspect_VKeyMouse_NONE)
631 {
632 myMouseSingleButton = -1;
215dd331 633 if (myMouseStopDragOnUnclick)
634 {
635 myMouseStopDragOnUnclick = false;
636 myUI.Dragging.ToStop = true;
637 toUpdateView = true;
638 }
49582f9d 639 }
640 else if (myMouseSingleButton == -1)
641 {
642 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
643 {
644 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
645 }
646 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
647 {
648 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
649 }
650 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
651 {
652 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
653 }
654 else
655 {
656 myMouseSingleButton = 0;
657 }
658 if (myMouseSingleButton != 0)
659 {
660 if (myMouseClickCounter == 1)
661 {
662 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
663 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
664 {
665 myMouseClickTimer.Stop();
666 myMouseClickCounter = 0;
667 }
668 }
669 myMousePressPoint = thePoint;
670 }
671 }
672 else
673 {
674 myMouseSingleButton = 0;
675
676 myUI.Dragging.ToAbort = true;
677 toUpdateView = true;
678 }
679
680 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
681 myMouseModifiers = theModifiers;
682 myMousePressed = theButtons;
683 if (theIsEmulated
684 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
685 {
686 myMouseActiveIdleRotation = false;
687 myMouseActiveGesture = AIS_MouseGesture_NONE;
688 if (theButtons != 0)
689 {
690 myMousePressPoint = thePoint;
691 myMouseProgressPoint = myMousePressPoint;
692 }
693
694 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
695 {
696 switch (myMouseActiveGesture)
697 {
698 case AIS_MouseGesture_RotateView:
699 case AIS_MouseGesture_RotateOrbit:
700 {
701 if (myToAllowRotation)
702 {
703 myUpdateStartPointRot = true;
704 }
705 else
706 {
707 myMouseActiveGesture = AIS_MouseGesture_NONE;
708 }
709 break;
710 }
711 case AIS_MouseGesture_Pan:
712 {
713 if (myToAllowPanning)
714 {
715 myUpdateStartPointPan = true;
716 }
717 else
718 {
719 myMouseActiveGesture = AIS_MouseGesture_NONE;
720 }
721 break;
722 }
723 case AIS_MouseGesture_Zoom:
724 {
725 if (!myToAllowZooming)
726 {
727 myMouseActiveGesture = AIS_MouseGesture_NONE;
728 }
729 break;
730 }
731 case AIS_MouseGesture_SelectRectangle:
732 {
733 break;
734 }
735 case AIS_MouseGesture_SelectLasso:
736 {
737 UpdatePolySelection (thePoint, true);
738 break;
739 }
740 case AIS_MouseGesture_NONE:
741 {
742 break;
743 }
744 }
745 }
746
747 if (theButtons == Aspect_VKeyMouse_LeftButton
748 && theModifiers == Aspect_VKeyFlags_NONE
749 && myToAllowDragging)
750 {
751 myUI.Dragging.ToStart = true;
752 myUI.Dragging.PointStart = thePoint;
753 }
754 }
755
756 if (aPrevGesture != myMouseActiveGesture)
757 {
758 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
759 || aPrevGesture == AIS_MouseGesture_SelectLasso)
760 {
761 myUI.Selection.ToApplyTool = true;
762 }
763
764 myUI.IsNewGesture = true;
765 toUpdateView = true;
766 }
767 return toUpdateView;
768}
769
770// =======================================================================
771// function : UpdateMousePosition
772// purpose :
773// =======================================================================
774bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
775 Aspect_VKeyMouse theButtons,
776 Aspect_VKeyFlags theModifiers,
777 bool theIsEmulated)
778{
779 myMousePositionLast = thePoint;
780 if (myMouseSingleButton > 0)
781 {
782 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
783 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
784 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
785 {
786 myMouseClickTimer.Stop();
787 myMouseClickCounter = 0;
788 myMouseSingleButton = -1;
215dd331 789 myMouseStopDragOnUnclick = true;
49582f9d 790 }
791 }
792
793 bool toUpdateView = false;
794 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
795 if (!theIsEmulated
796 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
797 {
798 if (!myMouseActiveIdleRotation
799 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
800 {
801 myMouseActiveIdleRotation = true;
802 myMouseActiveGesture = AIS_MouseGesture_RotateView;
803 myMousePressPoint = thePoint;
804 myMouseProgressPoint = thePoint;
805 myUpdateStartPointRot = false;
806 myUI.ViewRotation.ToStart = true;
807 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
808 myUI.ViewRotation.ToRotate = false;
809 aDelta.SetValues (0, 0);
810 }
811 }
812 else
813 {
814 if (myMouseActiveIdleRotation
815 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
816 {
817 myMouseActiveGesture = AIS_MouseGesture_NONE;
818 }
819 myMouseActiveIdleRotation = false;
820 }
821
822 if (myMouseModifiers != theModifiers
823 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
824 {
825 toUpdateView = true;
826 }
827
828 switch (myMouseActiveGesture)
829 {
830 case AIS_MouseGesture_SelectRectangle:
831 {
832 UpdateRubberBand (myMousePressPoint, thePoint);
833 toUpdateView = true;
834 break;
835 }
836 case AIS_MouseGesture_SelectLasso:
837 {
838 UpdatePolySelection (thePoint, true);
839 toUpdateView = true;
840 break;
841 }
842 case AIS_MouseGesture_RotateOrbit:
843 case AIS_MouseGesture_RotateView:
844 {
845 if (!myToAllowRotation)
846 {
847 break;
848 }
849 if (myUpdateStartPointRot)
850 {
851 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
852 {
853 myUI.OrbitRotation.ToStart = true;
854 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
855 }
856 else
857 {
858 myUI.ViewRotation.ToStart = true;
859 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
860 }
861 myUpdateStartPointRot = false;
862 }
863
864 const double aRotTol = theIsEmulated
865 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
866 : 0.0;
867 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
868 {
869 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
870 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
871 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
872 {
873 myUI.OrbitRotation.ToRotate = true;
874 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
875 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
876 }
877 else
878 {
879 myUI.ViewRotation.ToRotate = true;
880 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
881 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
882 }
883 myUI.Dragging.PointTo = thePoint;
884
885 myMouseProgressPoint = thePoint;
886 toUpdateView = true;
887 }
888 break;
889 }
890 case AIS_MouseGesture_Zoom:
891 {
892 if (!myToAllowZooming)
893 {
894 break;
895 }
896 const double aZoomTol = theIsEmulated
897 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
898 : 0.0;
899 if (double (Abs (aDelta.x())) > aZoomTol)
900 {
901 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
902 {
903 toUpdateView = true;
904 }
905 myMouseProgressPoint = thePoint;
906 }
907 break;
908 }
909 case AIS_MouseGesture_Pan:
910 {
911 if (!myToAllowPanning)
912 {
913 break;
914 }
915 const double aPanTol = theIsEmulated
916 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
917 : 0.0;
918 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
919 {
920 if (myUpdateStartPointPan)
921 {
922 myUI.Panning.ToStart = true;
923 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
924 myUpdateStartPointPan = false;
925 }
926
927 aDelta.y() = -aDelta.y();
928 myMouseProgressPoint = thePoint;
929 if (myUI.Panning.ToPan)
930 {
931 myUI.Panning.Delta += aDelta;
932 }
933 else
934 {
935 myUI.Panning.ToPan = true;
936 myUI.Panning.Delta = aDelta;
937 }
938 toUpdateView = true;
939 }
940 break;
941 }
942 default:
943 {
944 break;
945 }
946 }
947
948 if (theButtons == Aspect_VKeyMouse_NONE
949 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
950 && !theIsEmulated
951 && !HasTouchPoints()
952 && myToAllowHighlight)
953 {
954 myUI.MoveTo.ToHilight = true;
955 myUI.MoveTo.Point = thePoint;
956 toUpdateView = true;
957 }
958 return toUpdateView;
959}
960
961// =======================================================================
962// function : AddTouchPoint
963// purpose :
964// =======================================================================
965void AIS_ViewController::AddTouchPoint (Standard_Size theId,
966 const Graphic3d_Vec2d& thePnt,
967 Standard_Boolean theClearBefore)
968{
969 myUI.MoveTo.ToHilight = false;
970 if (theClearBefore)
971 {
972 RemoveTouchPoint ((Standard_Size )-1);
973 }
974
975 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
976 if (myTouchPoints.Extent() == 1)
977 {
978 myUpdateStartPointRot = true;
979 myStartRotCoord = thePnt;
980 if (myToAllowDragging)
981 {
982 myUI.Dragging.ToStart = true;
983 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
984 }
985 }
986 else if (myTouchPoints.Extent() == 2)
987 {
988 myUI.Dragging.ToAbort = true;
989
990 myUpdateStartPointPan = true;
991 myStartPanCoord = thePnt;
992 }
993 myUI.IsNewGesture = true;
994}
995
996// =======================================================================
997// function : RemoveTouchPoint
998// purpose :
999// =======================================================================
1000bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
1001 Standard_Boolean theClearSelectPnts)
1002{
1003 if (theId == (Standard_Size )-1)
1004 {
1005 myTouchPoints.Clear (false);
1006 }
1007 else
1008 {
1009 const Standard_Integer anOldExtent = myTouchPoints.Extent();
1010 myTouchPoints.RemoveKey (theId);
1011 if (myTouchPoints.Extent() == anOldExtent)
1012 {
1013 return false;
1014 }
1015 }
1016
1017 if (myTouchPoints.Extent() == 1)
1018 {
1019 // avoid incorrect transition from pinch to one finger
1020 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1021 aFirstTouch.To = aFirstTouch.From;
1022
1023 myStartRotCoord = aFirstTouch.To;
1024 myUpdateStartPointRot = true;
1025 }
1026 else if (myTouchPoints.Extent() == 2)
1027 {
1028 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1029 myUpdateStartPointPan = true;
1030 }
1031 else if (myTouchPoints.IsEmpty())
1032 {
1033 if (theClearSelectPnts)
1034 {
1035 myUI.Selection.ToApplyTool = true;
1036 }
1037
1038 myUI.Dragging.ToStop = true;
1039 }
1040 myUI.IsNewGesture = true;
1041 return true;
1042}
1043
1044// =======================================================================
1045// function : UpdateTouchPoint
1046// purpose :
1047// =======================================================================
1048void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1049 const Graphic3d_Vec2d& thePnt)
1050{
1051 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1052 {
1053 aTouch->To = thePnt;
1054 }
1055 else
1056 {
1057 AddTouchPoint (theId, thePnt);
1058 }
1059}
1060
1061// =======================================================================
1062// function : SetNavigationMode
1063// purpose :
1064// =======================================================================
1065void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1066{
1067 myNavigationMode = theMode;
1068
1069 // abort rotation
1070 myUI.OrbitRotation.ToStart = false;
1071 myUI.OrbitRotation.ToRotate = false;
1072 myUI.ViewRotation.ToStart = false;
1073 myUI.ViewRotation.ToRotate = false;
1074}
1075
1076// =======================================================================
1077// function : KeyDown
1078// purpose :
1079// =======================================================================
1080void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1081 double theTime,
1082 double thePressure)
1083{
1084 myKeys.KeyDown (theKey, theTime, thePressure);
1085}
1086
1087// =======================================================================
1088// function : KeyUp
1089// purpose :
1090// =======================================================================
1091void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1092 double theTime)
1093{
1094 myKeys.KeyUp (theKey, theTime);
1095}
1096
1097// =======================================================================
1098// function : KeyFromAxis
1099// purpose :
1100// =======================================================================
1101void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1102 Aspect_VKey thePositive,
1103 double theTime,
1104 double thePressure)
1105{
1106 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1107}
1108
1109// =======================================================================
1110// function : FetchNavigationKeys
1111// purpose :
1112// =======================================================================
1113AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1114 Standard_Real theRunRatio)
1115{
1116 AIS_WalkDelta aWalk;
1117
1118 // navigation keys
1119 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1120 updateEventsTime (aPrevEventTime, aNewEventTime);
1121
1122 double aDuration = 0.0, aPressure = 1.0;
1123 if (Abs (myThrustSpeed) > gp::Resolution())
1124 {
1125 if (myHasThrust)
1126 {
1127 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1128 }
1129 myHasThrust = true;
1130 myToAskNextFrame = true;
1131 }
1132 else
1133 {
1134 myHasThrust = false;
1135 }
1136
1137 aWalk.SetRunning (theRunRatio > 1.0
1138 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1139 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1140 {
1141 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1142 aWalk.SetJumping (true);
1143 }
1144 if (!aWalk.IsJumping()
1145 && theCrouchRatio < 1.0
1146 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1147 {
1148 aWalk.SetRunning (false);
1149 aWalk.SetCrouching (true);
1150 }
1151
1152 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1153 const double aRunRatio = aWalk.IsRunning()
1154 ? theRunRatio
1155 : aWalk.IsCrouching()
1156 ? theCrouchRatio
1157 : 1.0;
1158 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1159 {
1160 double aProgress = Abs (Min (aMaxDuration, aDuration));
1161 aProgress *= aRunRatio;
1162 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1163 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1164 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1165 }
1166 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1167 {
1168 double aProgress = Abs (Min (aMaxDuration, aDuration));
1169 aProgress *= aRunRatio;
1170 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1171 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1172 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1173 }
1174 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1175 {
1176 double aProgress = Abs (Min (aMaxDuration, aDuration));
1177 aProgress *= aRunRatio;
1178 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1179 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1180 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1181 }
1182 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1183 {
1184 double aProgress = Abs (Min (aMaxDuration, aDuration));
1185 aProgress *= aRunRatio;
1186 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1187 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1188 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1189 }
1190 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1191 {
1192 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1193 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1194 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1195 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1196 }
1197 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1198 {
1199 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1200 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1201 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1202 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1203 }
1204 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1205 {
1206 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1207 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1208 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1209 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1210 }
1211 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1212 {
1213 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1214 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1215 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1216 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1217 }
1218 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1219 {
1220 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1221 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1222 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1223 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1224 }
1225 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1226 {
1227 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1228 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1229 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1230 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1231 }
1232 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1233 {
1234 double aProgress = Abs (Min (aMaxDuration, aDuration));
1235 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1236 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1237 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1238 }
1239 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1240 {
1241 double aProgress = Abs (Min (aMaxDuration, aDuration));
1242 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1243 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1244 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1245 }
1246 return aWalk;
1247}
1248
2108d9a2 1249// =======================================================================
1250// function : AbortViewAnimation
1251// purpose :
1252// =======================================================================
1253void AIS_ViewController::AbortViewAnimation()
1254{
1255 if (!myViewAnimation.IsNull()
1256 && !myViewAnimation->IsStopped())
1257 {
1258 myViewAnimation->Stop();
1259 myViewAnimation->SetView (Handle(V3d_View)());
1260 }
1261}
1262
49582f9d 1263// =======================================================================
1264// function : handlePanning
1265// purpose :
1266// =======================================================================
1267void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1268{
1269 if (!myGL.Panning.ToPan
1270 || !myToAllowPanning)
1271 {
1272 return;
1273 }
1274
2108d9a2 1275 AbortViewAnimation();
1276
49582f9d 1277 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1278 if (aCam->IsOrthographic()
1279 || !hasPanningAnchorPoint())
1280 {
1281 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1282 theView->Invalidate();
1283 return;
1284 }
1285
1286 Graphic3d_Vec2i aWinSize;
1287 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1288
1289 const gp_Dir& aDir = aCam->Direction();
1290 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1291 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1292 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1293 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1294 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1295
1296 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1297 gp_Trsf aPanTrsf;
1298 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1299 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1300 aPanTrsf.SetTranslation (aCameraPan);
1301 aCam->Transform (aPanTrsf);
1302 theView->Invalidate();
1303}
1304
1305// =======================================================================
1306// function : handleZRotate
1307// purpose :
1308// =======================================================================
1309void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1310{
1311 if (!myGL.ZRotate.ToRotate
1312 || !myToAllowRotation)
1313 {
1314 return;
1315 }
1316
2108d9a2 1317 AbortViewAnimation();
1318
49582f9d 1319 Graphic3d_Vec2i aViewPort;
1320 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1321 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1322 0.5 * aViewPort.y());
1323 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1324 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1325 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1326 theView->Invalidate();
1327}
1328
1329// =======================================================================
1330// function : handleZoom
1331// purpose :
1332// =======================================================================
1333void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1334 const Aspect_ScrollDelta& theParams,
1335 const gp_Pnt* thePnt)
1336{
1337 if (!myToAllowZooming)
1338 {
1339 return;
1340 }
1341
2108d9a2 1342 AbortViewAnimation();
1343
49582f9d 1344 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1345 if (thePnt != NULL)
1346 {
1347 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1348 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1349 }
1350
1351 if (!theParams.HasPoint())
1352 {
1353 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1354 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1355 theView->SetZoom (aCoeff, true);
1356 theView->Invalidate();
1357 return;
1358 }
1359
1360 // integer delta is too rough for small smooth increments
1361 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1362 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1363
1364 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1365 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1366 if (aDZoom <= 0.0)
1367 {
1368 return;
1369 }
1370
1371 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1372
1373 // ensure that zoom will not be too small or too big
1374 double aCoef = aDZoom;
1375 if (aViewDims.x() < aCoef * Precision::Confusion())
1376 {
1377 aCoef = aViewDims.x() / Precision::Confusion();
1378 }
1379 else if (aViewDims.x() > aCoef * 1e12)
1380 {
1381 aCoef = aViewDims.x() / 1e12;
1382 }
1383 if (aViewDims.y() < aCoef * Precision::Confusion())
1384 {
1385 aCoef = aViewDims.y() / Precision::Confusion();
1386 }
1387 else if (aViewDims.y() > aCoef * 1e12)
1388 {
1389 aCoef = aViewDims.y() / 1e12;
1390 }
1391
1392 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1393 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1394 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1395 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1396 aCam->SetScale (aCam->Scale() / aCoef);
1397
1398 const gp_Dir& aDir = aCam->Direction();
1399 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1400
1401 // pan back to the point
1402 aDxy = aZoomAtPointXYv - aDxy;
1403 if (thePnt != NULL)
1404 {
1405 // zoom at 3D point with perspective projection
1406 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1407 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1408 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1409
1410 // view dimensions at 3D point
1411 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1412
1413 Graphic3d_Vec2i aWinSize;
1414 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1415 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
9460f8c0 1416 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
49582f9d 1417 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
9460f8c0 1418 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
49582f9d 1419 }
1420
1421 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1422 gp_Trsf aPanTrsf;
1423 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1424 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1425 aPanTrsf.SetTranslation (aCameraPan);
1426 aCam->Transform (aPanTrsf);
1427 theView->Invalidate();
1428}
1429
1430// =======================================================================
1431// function : handleZFocusScroll
1432// purpose :
1433// =======================================================================
1434void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1435 const Aspect_ScrollDelta& theParams)
1436{
1437 if (!myToAllowZFocus
1438 || !theView->Camera()->IsStereo())
1439 {
1440 return;
1441 }
1442
1443 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1444 if (aFocus > 0.2
1445 && aFocus < 2.0)
1446 {
1447 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1448 theView->Redraw();
1449 }
1450}
1451
1452// =======================================================================
1453// function : handleOrbitRotation
1454// purpose :
1455// =======================================================================
1456void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1457 const gp_Pnt& thePnt,
1458 bool theToLockZUp)
1459{
1460 if (!myToAllowRotation)
1461 {
1462 return;
1463 }
1464
1465 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1466 if (myGL.OrbitRotation.ToStart)
1467 {
1468 // default alternatives
1469 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1470 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1471
1472 myRotatePnt3d = thePnt;
1473 myCamStartOpUp = aCam->Up();
607e5e62 1474 myCamStartOpDir = aCam->Direction();
49582f9d 1475 myCamStartOpEye = aCam->Eye();
1476 myCamStartOpCenter = aCam->Center();
1477
1478 gp_Trsf aTrsf;
1479 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1480 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1481 const gp_Quaternion aRot = aTrsf.GetRotation();
1482 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1483
1484 aTrsf.Invert();
1485 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1486 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1487
1488 theView->Invalidate();
1489 }
1490
1491 if (!myGL.OrbitRotation.ToRotate)
1492 {
1493 return;
1494 }
1495
2108d9a2 1496 AbortViewAnimation();
49582f9d 1497 if (theToLockZUp)
1498 {
1499 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1500 Graphic3d_Vec2i aWinXY;
1501 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1502 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1503 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1504 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1505 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1506 const double aRoll = 0.0;
1507
1508 gp_Quaternion aRot;
1509 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1510 gp_Trsf aTrsfRot;
1511 aTrsfRot.SetRotation (aRot);
1512
1513 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1514 aCam->SetUp (aNewUp);
607e5e62 1515 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1516 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1517
49582f9d 1518 aCam->OrthogonalizeUp();
1519 }
1520 else
1521 {
1522 // default alternatives
1523 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1524 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1525
1526 // restore previous camera state
607e5e62 1527 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1528 aCam->SetUp (myCamStartOpUp);
1529 aCam->SetDirectionFromEye (myCamStartOpDir);
49582f9d 1530
1531 Graphic3d_Vec2d aWinXY;
1532 theView->Size (aWinXY.x(), aWinXY.y());
1533 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1534 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1535
1536 const double THE_2PI = M_PI * 2.0;
1537 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1538 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1539
1540 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1541 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1542 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1543 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1544
1545 // rotate camera around 3 initial axes
1546 gp_Dir aCamDir (aCam->Direction().Reversed());
1547 gp_Dir aCamUp (aCam->Up());
1548 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1549
1550 gp_Trsf aRot[2], aTrsf;
1551 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1552 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1553 aTrsf.Multiply (aRot[0]);
1554 aTrsf.Multiply (aRot[1]);
1555
1556 aCam->Transform (aTrsf);
1557 }
1558
1559 theView->Invalidate();
1560}
1561
1562// =======================================================================
1563// function : handleViewRotation
1564// purpose :
1565// =======================================================================
1566void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1567 double theYawExtra,
1568 double thePitchExtra,
1569 double theRoll,
1570 bool theToRestartOnIncrement)
1571{
1572 if (!myToAllowRotation)
1573 {
1574 return;
1575 }
1576
1577 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1578 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1579 || Abs (thePitchExtra) > gp::Resolution()
1580 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1581 if (toRotateAnyway
1582 && theToRestartOnIncrement)
1583 {
1584 myGL.ViewRotation.ToStart = true;
1585 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1586 }
1587 if (myGL.ViewRotation.ToStart)
1588 {
1589 gp_Trsf aTrsf;
1590 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1591 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1592 const gp_Quaternion aRot = aTrsf.GetRotation();
1593 double aRollDummy = 0.0;
1594 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1595 }
1596 if (toRotateAnyway)
1597 {
1598 myRotateStartYawPitchRoll[0] += theYawExtra;
1599 myRotateStartYawPitchRoll[1] += thePitchExtra;
1600 myRotateStartYawPitchRoll[2] = theRoll;
1601 myGL.ViewRotation.ToRotate = true;
1602 }
1603
1604 if (!myGL.ViewRotation.ToRotate)
1605 {
1606 return;
1607 }
1608
2108d9a2 1609 AbortViewAnimation();
1610
49582f9d 1611 Graphic3d_Vec2i aWinXY;
1612 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1613 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1614 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1615 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1616 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1617 gp_Quaternion aRot;
1618 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1619 gp_Trsf aTrsfRot;
1620 aTrsfRot.SetRotation (aRot);
1621
49582f9d 1622 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1623 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
607e5e62 1624 aCam->SetUp (aNewUp);
1625 aCam->SetDirectionFromEye (aNewDir);
49582f9d 1626 aCam->OrthogonalizeUp();
1627 theView->Invalidate();
1628}
1629
1630// =======================================================================
1631// function : PickPoint
1632// purpose :
1633// =======================================================================
1634bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1635 const Handle(AIS_InteractiveContext)& theCtx,
1636 const Handle(V3d_View)& theView,
1637 const Graphic3d_Vec2i& theCursor,
1638 bool theToStickToPickRay)
1639{
1640 ResetPreviousMoveTo();
1641
1642 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1643 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1644 if (aSelector->NbPicked() < 1)
1645 {
1646 return false;
1647 }
1648
1649 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1650 if (theToStickToPickRay
1651 && !Precision::IsInfinite (aPicked.Depth))
1652 {
1653 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1654 }
1655 else
1656 {
1657 thePnt = aSelector->PickedPoint (1);
1658 }
1659 return !Precision::IsInfinite (thePnt.X())
1660 && !Precision::IsInfinite (thePnt.Y())
1661 && !Precision::IsInfinite (thePnt.Z());
1662}
1663
1664// =======================================================================
1665// function : GravityPoint
1666// purpose :
1667// =======================================================================
1668gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1669 const Handle(V3d_View)& theView)
1670{
1671 switch (myRotationMode)
1672 {
1673 case AIS_RotationMode_PickLast:
1674 case AIS_RotationMode_PickCenter:
1675 {
1676 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1677 if (myRotationMode == AIS_RotationMode_PickCenter)
1678 {
1679 Graphic3d_Vec2i aViewPort;
1680 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1681 aCursor = aViewPort / 2;
1682 }
1683
1684 gp_Pnt aPnt;
9460f8c0 1685 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
49582f9d 1686 {
1687 return aPnt;
1688 }
1689 break;
1690 }
1691 case AIS_RotationMode_CameraAt:
1692 {
1693 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1694 return aCam->Center();
1695 }
1696 case AIS_RotationMode_BndBoxScene:
1697 {
1698 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1699 if (!aBndBox.IsVoid())
1700 {
1701 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1702 }
1703 break;
1704 }
1705 case AIS_RotationMode_BndBoxActive:
1706 break;
1707 }
1708
1709 return theCtx ->GravityPoint (theView);
1710}
1711
1712// =======================================================================
1713// function : handleCameraActions
1714// purpose :
1715// =======================================================================
1716void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
1717 const Handle(V3d_View)& theView,
1718 const AIS_WalkDelta& theWalk)
1719{
1720 // apply view actions
1721 if (myGL.Orientation.ToSetViewOrient)
1722 {
1723 theView->SetProj (myGL.Orientation.ViewOrient);
1724 myGL.Orientation.ToFitAll = true;
1725 }
1726
1727 // apply fit all
1728 if (myGL.Orientation.ToFitAll)
1729 {
1730 const double aFitMargin = 0.01;
1731 theView->FitAll (aFitMargin, false);
1732 theView->Invalidate();
1733 myGL.Orientation.ToFitAll = false;
1734 }
1735
1736 if (myGL.IsNewGesture)
1737 {
1738 if (myAnchorPointPrs1->HasInteractiveContext())
1739 {
1740 theCtx->Remove (myAnchorPointPrs1, false);
1741 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
1742 {
1743 theView->Invalidate();
1744 }
1745 else
1746 {
1747 theView->InvalidateImmediate();
1748 }
1749 }
1750 if (myAnchorPointPrs2->HasInteractiveContext())
1751 {
1752 theCtx->Remove (myAnchorPointPrs2, false);
1753 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
1754 {
1755 theView->Invalidate();
1756 }
1757 else
1758 {
1759 theView->InvalidateImmediate();
1760 }
1761 }
1762
1763 if (myHasHlrOnBeforeRotation)
1764 {
1765 myHasHlrOnBeforeRotation = false;
1766 theView->SetComputedMode (true);
1767 theView->Invalidate();
1768 }
1769 }
1770
1771 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
1772 {
1773 if (myGL.Panning.ToStart
1774 && myToAllowPanning)
1775 {
1776 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
1777 if (!theView->Camera()->IsOrthographic())
1778 {
1779 bool toStickToRay = false;
1780 if (myGL.Panning.PointStart.x() >= 0
1781 && myGL.Panning.PointStart.y() >= 0)
1782 {
1783 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
1784 }
1785 if (Precision::IsInfinite (aPanPnt.X()))
1786 {
1787 Graphic3d_Vec2i aWinSize;
1788 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1789 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
1790 }
1791 if (!Precision::IsInfinite (aPanPnt.X())
1792 && myToShowPanAnchorPoint)
1793 {
1794 gp_Trsf aPntTrsf;
1795 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
1796 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1797 }
1798 }
1799 setPanningAnchorPoint (aPanPnt);
1800 }
1801
1802 if (myToShowPanAnchorPoint
1803 && hasPanningAnchorPoint()
1804 && myGL.Panning.ToPan
1805 && !myGL.IsNewGesture
1806 && !myAnchorPointPrs2->HasInteractiveContext())
1807 {
1808 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1809 }
1810
1811 handlePanning (theView);
1812 handleZRotate (theView);
1813 }
1814
1815 if ((myNavigationMode == AIS_NavigationMode_Orbit
1816 || myGL.OrbitRotation.ToStart
1817 || myGL.OrbitRotation.ToRotate)
1818 && myToAllowRotation)
1819 {
1820 if (myGL.OrbitRotation.ToStart
1821 && !myHasHlrOnBeforeRotation)
1822 {
1823 myHasHlrOnBeforeRotation = theView->ComputedMode();
1824 if (myHasHlrOnBeforeRotation)
1825 {
1826 theView->SetComputedMode (false);
1827 }
1828 }
1829
1830 gp_Pnt aGravPnt;
1831 if (myGL.OrbitRotation.ToStart)
1832 {
1833 aGravPnt = GravityPoint (theCtx, theView);
1834 if (myToShowRotateCenter)
1835 {
1836 gp_Trsf aPntTrsf;
1837 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
1838 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
1839 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1840 }
1841 }
1842
1843 if (myToShowRotateCenter
1844 && myGL.OrbitRotation.ToRotate
1845 && !myGL.IsNewGesture
1846 && !myAnchorPointPrs1->HasInteractiveContext())
1847 {
1848 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
1849 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1850 }
1851 handleOrbitRotation (theView, aGravPnt,
1852 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
1853 }
1854
1855 if ((myNavigationMode != AIS_NavigationMode_Orbit
1856 || myGL.ViewRotation.ToStart
1857 || myGL.ViewRotation.ToRotate)
1858 && myToAllowRotation)
1859 {
1860 if (myGL.ViewRotation.ToStart
1861 && !myHasHlrOnBeforeRotation)
1862 {
1863 myHasHlrOnBeforeRotation = theView->ComputedMode();
1864 if (myHasHlrOnBeforeRotation)
1865 {
1866 theView->SetComputedMode (false);
1867 }
1868 }
1869
1870 double aRoll = 0.0;
1871 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
1872 && !myToLockOrbitZUp)
1873 {
1874 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
1875 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
1876 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
1877 {
1878 aRoll = -aRoll;
1879 }
1880 }
1881
1882 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
1883 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
1884 }
1885
1886 if (!myGL.ZoomActions.IsEmpty())
1887 {
1888 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
1889 {
1890 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
1891 if (myToAllowZFocus
1892 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
1893 && theView->Camera()->IsStereo())
1894 {
1895 handleZFocusScroll (theView, aZoomParams);
1896 continue;
1897 }
1898
1899 if (!myToAllowZooming)
1900 {
1901 continue;
1902 }
1903
1904 if (!theView->Camera()->IsOrthographic())
1905 {
49582f9d 1906 gp_Pnt aPnt;
1907 if (aZoomParams.HasPoint()
9460f8c0 1908 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
49582f9d 1909 {
1910 handleZoom (theView, aZoomParams, &aPnt);
1911 continue;
1912 }
1913
1914 Graphic3d_Vec2i aWinSize;
1915 theView->Window()->Size (aWinSize.x(), aWinSize.y());
9460f8c0 1916 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom))
49582f9d 1917 {
1918 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
1919 handleZoom (theView, aZoomParams, &aPnt);
1920 continue;
1921 }
1922 }
1923 handleZoom (theView, aZoomParams, NULL);
1924 }
1925 myGL.ZoomActions.Clear();
1926 }
1927}
1928
1929// =======================================================================
1930// function : OnSelectionChanged
1931// purpose :
1932// =======================================================================
1933void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
1934 const Handle(V3d_View)& )
1935{
1936 //
1937}
1938
1939// =======================================================================
1940// function : OnObjectDragged
1941// purpose :
1942// =======================================================================
1943void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
1944 const Handle(V3d_View)& theView,
1945 AIS_DragAction theAction)
1946{
1947 switch (theAction)
1948 {
1949 case AIS_DragAction_Start:
1950 {
1951 myDragObject.Nullify();
1952 if (!theCtx->HasDetected())
1953 {
1954 return;
1955 }
1956
1957 Handle(AIS_InteractiveObject) aPrs = theCtx->DetectedInteractive();
1958 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (aPrs))
1959 {
1960 if (aManip->HasActiveMode())
1961 {
1962 myDragObject = aManip;
1963 aManip->StartTransform (myGL.Dragging.PointStart.x(), myGL.Dragging.PointStart.y(), theView);
1964 }
1965 }
1966 return;
1967 }
1968 case AIS_DragAction_Update:
1969 {
1970 if (myDragObject.IsNull())
1971 {
1972 return;
1973 }
1974
1975 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
1976 {
1977 theCtx->SetSelectedState (aGlobOwner, true);
1978 }
1979 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1980 {
1981 aManip->Transform (myGL.Dragging.PointTo.x(), myGL.Dragging.PointTo.y(), theView);
1982 }
1983 theView->Invalidate();
1984 return;
1985 }
1986 case AIS_DragAction_Abort:
1987 {
1988 if (myDragObject.IsNull())
1989 {
1990 return;
1991 }
1992
1993 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
1994 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
1995
1996 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1997 {
1998 aManip->StopTransform (false);
1999 }
2000 Standard_FALLTHROUGH
2001 }
2002 case AIS_DragAction_Stop:
2003 {
2004 if (myDragObject.IsNull())
2005 {
2006 return;
2007 }
2008
2009 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2010 {
2011 theCtx->SetSelectedState (aGlobOwner, false);
2012 }
2013
2014 theView->Invalidate();
2015 myDragObject.Nullify();
2016 return;
2017 }
2018 }
2019}
2020
2021// =======================================================================
2022// function : contextLazyMoveTo
2023// purpose :
2024// =======================================================================
2025void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2026 const Handle(V3d_View)& theView,
2027 const Graphic3d_Vec2i& thePnt)
2028{
2029 if (myPrevMoveTo == thePnt)
2030 {
2031 return;
2032 }
2033
2034 myPrevMoveTo = thePnt;
2035
2036 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2037 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2038 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2039
2040 if (theView->Viewer()->Grid()->IsActive()
2041 && theView->Viewer()->GridEcho())
2042 {
2043 if (aNewPicked.IsNull())
2044 {
2045 Graphic3d_Vec3d aPnt3d;
2046 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2047 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2048 theView->InvalidateImmediate();
2049 }
2050 else
2051 {
2052 theView->Viewer()->HideGridEcho (theView);
2053 theView->InvalidateImmediate();
2054 }
2055 }
2056
2057 if (aLastPicked != aNewPicked
2058 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2059 {
2060 // dynamic highlight affects all Views
2061 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2062 {
2063 const Handle(V3d_View)& aView = aViewIter.Value();
2064 aView->InvalidateImmediate();
2065 }
2066 }
2067}
2068
2069// =======================================================================
2070// function : handleSelectionPick
2071// purpose :
2072// =======================================================================
2073void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2074 const Handle(V3d_View)& theView)
2075{
2076 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2077 && !myGL.Selection.Points.IsEmpty())
2078 {
2079 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2080 {
49582f9d 2081 const bool hadPrevMoveTo = HasPreviousMoveTo();
2082 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2083 if (!hadPrevMoveTo)
2084 {
2085 ResetPreviousMoveTo();
2086 }
2087
2088 if (myGL.Selection.IsXOR)
2089 {
2090 theCtx->ShiftSelect (false);
2091 }
2092 else
2093 {
2094 theCtx->Select (false);
2095 }
2096
2097 // selection affects all Views
2098 theView->Viewer()->Invalidate();
2099
2100 OnSelectionChanged (theCtx, theView);
2101 }
2102
2103 myGL.Selection.Points.Clear();
2104 }
2105}
2106
2107// =======================================================================
2108// function : handleSelectionPoly
2109// purpose :
2110// =======================================================================
2111void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2112 const Handle(V3d_View)& theView)
2113{
2114 // rubber-band & window polygon selection
2115 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2116 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon)
2117 {
2118 if (!myGL.Selection.Points.IsEmpty())
2119 {
2120 myRubberBand->ClearPoints();
2121 myRubberBand->SetToUpdate();
2122
2123 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand;
2124 if (anIsRubber)
2125 {
2126 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2127 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2128 }
2129 else
2130 {
2131 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2132 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2133 {
2134 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2135 if (aPntNew != aPrev)
2136 {
2137 aPrev = aPntNew;
2138 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2139 }
2140 }
2141 }
2142
2143 myRubberBand->SetPolygonClosed (anIsRubber);
2144 try
2145 {
2146 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2147 }
2148 catch (const Standard_Failure& theEx)
2149 {
2150 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2151 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString(), Message_Warning);
2152 myRubberBand->ClearPoints();
2153 }
2154 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2155 {
2156 theView->Invalidate();
2157 }
2158 else
2159 {
2160 theView->InvalidateImmediate();
2161 }
2162 }
2163 else if (!myRubberBand.IsNull()
2164 && myRubberBand->HasInteractiveContext())
2165 {
2166 theCtx->Remove (myRubberBand, false);
2167 myRubberBand->ClearPoints();
2168 }
2169 }
2170
2171 if (myGL.Selection.ToApplyTool)
2172 {
2173 myGL.Selection.ToApplyTool = false;
2174 if (theCtx->IsDisplayed (myRubberBand))
2175 {
2176 theCtx->Remove (myRubberBand, false);
2177 {
2178 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2179 if (aPoints.Size() == 4
2180 && aPoints.Value (1).x() == aPoints.Value (2).x()
2181 && aPoints.Value (3).x() == aPoints.Value (4).x()
2182 && aPoints.Value (1).y() == aPoints.Value (4).y()
2183 && aPoints.Value (2).y() == aPoints.Value (3).y())
2184 {
2185 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2186 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
2187 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2188 if (myGL.Selection.IsXOR)
2189 {
2190 theCtx->ShiftSelect (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2191 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2192 theView, false);
2193 }
2194 else
2195 {
2196 theCtx->Select (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2197 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2198 theView, false);
2199 }
2200 theCtx->MainSelector()->AllowOverlapDetection (false);
2201 }
2202 else if (aPoints.Length() >= 3)
2203 {
2204 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2205 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2206 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2207 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2208 {
2209 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2210 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2211 }
2212
2213 theCtx->MainSelector()->AllowOverlapDetection (false);
2214 if (myGL.Selection.IsXOR)
2215 {
2216 theCtx->ShiftSelect (aPolyline, theView, false);
2217 }
2218 else
2219 {
2220 theCtx->Select (aPolyline, theView, false);
2221 }
2222 }
2223 }
2224
2225 // selection affects all Views
2226 theView->Viewer()->Invalidate();
2227
2228 myRubberBand->ClearPoints();
2229 OnSelectionChanged (theCtx, theView);
2230 }
2231 }
2232}
2233
2234// =======================================================================
2235// function : handleDynamicHighlight
2236// purpose :
2237// =======================================================================
2238void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2239 const Handle(V3d_View)& theView)
2240{
2241 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2242 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2243 {
2244 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2245 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2246 && !HasPreviousMoveTo())
2247 {
2248 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2249 ResetPreviousMoveTo();
2250 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2251 theCtx->ClearDetected();
2252 }
2253 else if (myToAllowHighlight)
2254 {
2255 if (myPrevMoveTo != aMoveToPnt
2256 || myGL.OrbitRotation.ToRotate
2257 || myGL.ViewRotation.ToRotate
2258 || theView->IsInvalidated())
2259 {
2260 ResetPreviousMoveTo();
2261 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2262 }
2263 if (myGL.Dragging.ToStart)
2264 {
2265 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2266 }
2267 }
2268
2269 myGL.MoveTo.ToHilight = false;
2270 }
2271
2272 if (!myDragObject.IsNull())
2273 {
2274 if (myGL.Dragging.ToAbort)
2275 {
2276 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2277 myGL.OrbitRotation.ToRotate = false;
2278 myGL.ViewRotation .ToRotate = false;
2279 }
2280 else if (myGL.Dragging.ToStop)
2281 {
2282 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2283 myGL.OrbitRotation.ToRotate = false;
2284 myGL.ViewRotation .ToRotate = false;
2285 }
2286 else if (myGL.OrbitRotation.ToRotate
2287 || myGL.ViewRotation.ToRotate)
2288 {
2289 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2290 myGL.OrbitRotation.ToRotate = false;
2291 myGL.ViewRotation .ToRotate = false;
2292 }
2293 }
2294}
2295
2296// =======================================================================
2297// function : handleMoveTo
2298// purpose :
2299// =======================================================================
2300void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2301 const Handle(V3d_View)& theView)
2302{
2303 handleSelectionPick (theCtx, theView);
2304 handleDynamicHighlight(theCtx, theView);
2305 handleSelectionPoly (theCtx, theView);
2306}
2307
2308// =======================================================================
2309// function : handleViewRedraw
2310// purpose :
2311// =======================================================================
2312void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2313 const Handle(V3d_View)& theView)
2314{
2108d9a2 2315 // manage animation state
2316 if (!myViewAnimation.IsNull()
2317 && !myViewAnimation->IsStopped())
2318 {
2319 myViewAnimation->UpdateTimer();
2320 ResetPreviousMoveTo();
2321 setAskNextFrame();
2322 }
2323
49582f9d 2324 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2325 {
2326 const Handle(V3d_View)& aView = aViewIter.Value();
2327 if (aView->IsInvalidated()
2328 || myToAskNextFrame)
2329 {
2330 if (aView->ComputedMode())
2331 {
2332 aView->Update();
2333 }
2334 else
2335 {
2336 aView->Redraw();
2337 }
2338 }
2339 else if (aView->IsInvalidatedImmediate())
2340 {
2341 aView->RedrawImmediate();
2342 }
2343 }
2344
2345 if (myToAskNextFrame)
2346 {
2347 // ask more frames
2348 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
2349 }
2350}
2351
2352// =======================================================================
2353// function : HandleViewEvents
2354// purpose :
2355// =======================================================================
2356void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
2357 const Handle(V3d_View)& theView)
2358{
2359 handleMoveTo (theCtx, theView);
2360
2361 const AIS_WalkDelta aWalk = FetchNavigationKeys (1.0, 1.0);
2362 handleCameraActions (theCtx, theView, aWalk);
2363 handleViewRedraw (theCtx, theView);
2364
2365 // make sure to not process the same events twice
2366 myGL.Reset();
2367 myToAskNextFrame = false;
2368}