0031519: Visualization, AIS_ViewController - add AIS_MouseGesture_ZoomWindow gesture
[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:
e1c9a103 724 case AIS_MouseGesture_ZoomWindow:
49582f9d 725 {
726 if (!myToAllowZooming)
727 {
728 myMouseActiveGesture = AIS_MouseGesture_NONE;
729 }
730 break;
731 }
732 case AIS_MouseGesture_SelectRectangle:
733 {
734 break;
735 }
736 case AIS_MouseGesture_SelectLasso:
737 {
738 UpdatePolySelection (thePoint, true);
739 break;
740 }
741 case AIS_MouseGesture_NONE:
742 {
743 break;
744 }
745 }
746 }
747
748 if (theButtons == Aspect_VKeyMouse_LeftButton
749 && theModifiers == Aspect_VKeyFlags_NONE
750 && myToAllowDragging)
751 {
752 myUI.Dragging.ToStart = true;
753 myUI.Dragging.PointStart = thePoint;
754 }
755 }
756
757 if (aPrevGesture != myMouseActiveGesture)
758 {
759 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
e1c9a103 760 || aPrevGesture == AIS_MouseGesture_SelectLasso
761 || aPrevGesture == AIS_MouseGesture_ZoomWindow)
49582f9d 762 {
763 myUI.Selection.ToApplyTool = true;
764 }
765
766 myUI.IsNewGesture = true;
767 toUpdateView = true;
768 }
769 return toUpdateView;
770}
771
772// =======================================================================
773// function : UpdateMousePosition
774// purpose :
775// =======================================================================
776bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
777 Aspect_VKeyMouse theButtons,
778 Aspect_VKeyFlags theModifiers,
779 bool theIsEmulated)
780{
781 myMousePositionLast = thePoint;
782 if (myMouseSingleButton > 0)
783 {
784 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
785 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
786 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
787 {
788 myMouseClickTimer.Stop();
789 myMouseClickCounter = 0;
790 myMouseSingleButton = -1;
215dd331 791 myMouseStopDragOnUnclick = true;
49582f9d 792 }
793 }
794
795 bool toUpdateView = false;
796 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
797 if (!theIsEmulated
798 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
799 {
800 if (!myMouseActiveIdleRotation
801 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
802 {
803 myMouseActiveIdleRotation = true;
804 myMouseActiveGesture = AIS_MouseGesture_RotateView;
805 myMousePressPoint = thePoint;
806 myMouseProgressPoint = thePoint;
807 myUpdateStartPointRot = false;
808 myUI.ViewRotation.ToStart = true;
809 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
810 myUI.ViewRotation.ToRotate = false;
811 aDelta.SetValues (0, 0);
812 }
813 }
814 else
815 {
816 if (myMouseActiveIdleRotation
817 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
818 {
819 myMouseActiveGesture = AIS_MouseGesture_NONE;
820 }
821 myMouseActiveIdleRotation = false;
822 }
823
824 if (myMouseModifiers != theModifiers
825 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
826 {
827 toUpdateView = true;
828 }
829
830 switch (myMouseActiveGesture)
831 {
832 case AIS_MouseGesture_SelectRectangle:
e1c9a103 833 case AIS_MouseGesture_ZoomWindow:
49582f9d 834 {
835 UpdateRubberBand (myMousePressPoint, thePoint);
e1c9a103 836 if (myMouseActiveGesture == AIS_MouseGesture_ZoomWindow)
837 {
838 myUI.Selection.Tool = AIS_ViewSelectionTool_ZoomWindow;
839 }
49582f9d 840 toUpdateView = true;
841 break;
842 }
843 case AIS_MouseGesture_SelectLasso:
844 {
845 UpdatePolySelection (thePoint, true);
846 toUpdateView = true;
847 break;
848 }
849 case AIS_MouseGesture_RotateOrbit:
850 case AIS_MouseGesture_RotateView:
851 {
852 if (!myToAllowRotation)
853 {
854 break;
855 }
856 if (myUpdateStartPointRot)
857 {
858 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
859 {
860 myUI.OrbitRotation.ToStart = true;
861 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
862 }
863 else
864 {
865 myUI.ViewRotation.ToStart = true;
866 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
867 }
868 myUpdateStartPointRot = false;
869 }
870
871 const double aRotTol = theIsEmulated
872 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
873 : 0.0;
874 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
875 {
876 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
877 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
878 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
879 {
880 myUI.OrbitRotation.ToRotate = true;
881 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
882 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
883 }
884 else
885 {
886 myUI.ViewRotation.ToRotate = true;
887 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
888 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
889 }
890 myUI.Dragging.PointTo = thePoint;
891
892 myMouseProgressPoint = thePoint;
893 toUpdateView = true;
894 }
895 break;
896 }
897 case AIS_MouseGesture_Zoom:
898 {
899 if (!myToAllowZooming)
900 {
901 break;
902 }
903 const double aZoomTol = theIsEmulated
904 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
905 : 0.0;
906 if (double (Abs (aDelta.x())) > aZoomTol)
907 {
908 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
909 {
910 toUpdateView = true;
911 }
912 myMouseProgressPoint = thePoint;
913 }
914 break;
915 }
916 case AIS_MouseGesture_Pan:
917 {
918 if (!myToAllowPanning)
919 {
920 break;
921 }
922 const double aPanTol = theIsEmulated
923 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
924 : 0.0;
925 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
926 {
927 if (myUpdateStartPointPan)
928 {
929 myUI.Panning.ToStart = true;
930 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
931 myUpdateStartPointPan = false;
932 }
933
934 aDelta.y() = -aDelta.y();
935 myMouseProgressPoint = thePoint;
936 if (myUI.Panning.ToPan)
937 {
938 myUI.Panning.Delta += aDelta;
939 }
940 else
941 {
942 myUI.Panning.ToPan = true;
943 myUI.Panning.Delta = aDelta;
944 }
945 toUpdateView = true;
946 }
947 break;
948 }
949 default:
950 {
951 break;
952 }
953 }
954
955 if (theButtons == Aspect_VKeyMouse_NONE
956 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
957 && !theIsEmulated
958 && !HasTouchPoints()
959 && myToAllowHighlight)
960 {
961 myUI.MoveTo.ToHilight = true;
962 myUI.MoveTo.Point = thePoint;
963 toUpdateView = true;
964 }
965 return toUpdateView;
966}
967
968// =======================================================================
969// function : AddTouchPoint
970// purpose :
971// =======================================================================
972void AIS_ViewController::AddTouchPoint (Standard_Size theId,
973 const Graphic3d_Vec2d& thePnt,
974 Standard_Boolean theClearBefore)
975{
976 myUI.MoveTo.ToHilight = false;
977 if (theClearBefore)
978 {
979 RemoveTouchPoint ((Standard_Size )-1);
980 }
981
982 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
983 if (myTouchPoints.Extent() == 1)
984 {
985 myUpdateStartPointRot = true;
986 myStartRotCoord = thePnt;
987 if (myToAllowDragging)
988 {
989 myUI.Dragging.ToStart = true;
990 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
991 }
992 }
993 else if (myTouchPoints.Extent() == 2)
994 {
995 myUI.Dragging.ToAbort = true;
996
997 myUpdateStartPointPan = true;
998 myStartPanCoord = thePnt;
999 }
1000 myUI.IsNewGesture = true;
1001}
1002
1003// =======================================================================
1004// function : RemoveTouchPoint
1005// purpose :
1006// =======================================================================
1007bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
1008 Standard_Boolean theClearSelectPnts)
1009{
1010 if (theId == (Standard_Size )-1)
1011 {
1012 myTouchPoints.Clear (false);
1013 }
1014 else
1015 {
1016 const Standard_Integer anOldExtent = myTouchPoints.Extent();
1017 myTouchPoints.RemoveKey (theId);
1018 if (myTouchPoints.Extent() == anOldExtent)
1019 {
1020 return false;
1021 }
1022 }
1023
1024 if (myTouchPoints.Extent() == 1)
1025 {
1026 // avoid incorrect transition from pinch to one finger
1027 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1028 aFirstTouch.To = aFirstTouch.From;
1029
1030 myStartRotCoord = aFirstTouch.To;
1031 myUpdateStartPointRot = true;
1032 }
1033 else if (myTouchPoints.Extent() == 2)
1034 {
1035 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1036 myUpdateStartPointPan = true;
1037 }
1038 else if (myTouchPoints.IsEmpty())
1039 {
1040 if (theClearSelectPnts)
1041 {
1042 myUI.Selection.ToApplyTool = true;
1043 }
1044
1045 myUI.Dragging.ToStop = true;
1046 }
1047 myUI.IsNewGesture = true;
1048 return true;
1049}
1050
1051// =======================================================================
1052// function : UpdateTouchPoint
1053// purpose :
1054// =======================================================================
1055void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1056 const Graphic3d_Vec2d& thePnt)
1057{
1058 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1059 {
1060 aTouch->To = thePnt;
1061 }
1062 else
1063 {
1064 AddTouchPoint (theId, thePnt);
1065 }
1066}
1067
1068// =======================================================================
1069// function : SetNavigationMode
1070// purpose :
1071// =======================================================================
1072void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1073{
1074 myNavigationMode = theMode;
1075
1076 // abort rotation
1077 myUI.OrbitRotation.ToStart = false;
1078 myUI.OrbitRotation.ToRotate = false;
1079 myUI.ViewRotation.ToStart = false;
1080 myUI.ViewRotation.ToRotate = false;
1081}
1082
1083// =======================================================================
1084// function : KeyDown
1085// purpose :
1086// =======================================================================
1087void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1088 double theTime,
1089 double thePressure)
1090{
1091 myKeys.KeyDown (theKey, theTime, thePressure);
1092}
1093
1094// =======================================================================
1095// function : KeyUp
1096// purpose :
1097// =======================================================================
1098void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1099 double theTime)
1100{
1101 myKeys.KeyUp (theKey, theTime);
1102}
1103
1104// =======================================================================
1105// function : KeyFromAxis
1106// purpose :
1107// =======================================================================
1108void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1109 Aspect_VKey thePositive,
1110 double theTime,
1111 double thePressure)
1112{
1113 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1114}
1115
1116// =======================================================================
1117// function : FetchNavigationKeys
1118// purpose :
1119// =======================================================================
1120AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1121 Standard_Real theRunRatio)
1122{
1123 AIS_WalkDelta aWalk;
1124
1125 // navigation keys
1126 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1127 updateEventsTime (aPrevEventTime, aNewEventTime);
1128
1129 double aDuration = 0.0, aPressure = 1.0;
1130 if (Abs (myThrustSpeed) > gp::Resolution())
1131 {
1132 if (myHasThrust)
1133 {
1134 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1135 }
1136 myHasThrust = true;
1137 myToAskNextFrame = true;
1138 }
1139 else
1140 {
1141 myHasThrust = false;
1142 }
1143
1144 aWalk.SetRunning (theRunRatio > 1.0
1145 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1146 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1147 {
1148 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1149 aWalk.SetJumping (true);
1150 }
1151 if (!aWalk.IsJumping()
1152 && theCrouchRatio < 1.0
1153 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1154 {
1155 aWalk.SetRunning (false);
1156 aWalk.SetCrouching (true);
1157 }
1158
1159 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1160 const double aRunRatio = aWalk.IsRunning()
1161 ? theRunRatio
1162 : aWalk.IsCrouching()
1163 ? theCrouchRatio
1164 : 1.0;
1165 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1166 {
1167 double aProgress = Abs (Min (aMaxDuration, aDuration));
1168 aProgress *= aRunRatio;
1169 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1170 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1171 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1172 }
1173 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1174 {
1175 double aProgress = Abs (Min (aMaxDuration, aDuration));
1176 aProgress *= aRunRatio;
1177 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1178 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1179 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1180 }
1181 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1182 {
1183 double aProgress = Abs (Min (aMaxDuration, aDuration));
1184 aProgress *= aRunRatio;
1185 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1186 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1187 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1188 }
1189 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1190 {
1191 double aProgress = Abs (Min (aMaxDuration, aDuration));
1192 aProgress *= aRunRatio;
1193 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1194 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1195 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1196 }
1197 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, 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_NavLookRight, aNewEventTime, aDuration, aPressure))
1205 {
1206 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1207 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1208 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1209 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1210 }
1211 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, 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_NavLookDown, aNewEventTime, aDuration, aPressure))
1219 {
1220 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1221 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1222 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1223 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1224 }
1225 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, 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_NavRollCW, aNewEventTime, aDuration, aPressure))
1233 {
1234 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1235 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1236 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1237 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1238 }
1239 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, 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 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1247 {
1248 double aProgress = Abs (Min (aMaxDuration, aDuration));
1249 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1250 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1251 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1252 }
1253 return aWalk;
1254}
1255
2108d9a2 1256// =======================================================================
1257// function : AbortViewAnimation
1258// purpose :
1259// =======================================================================
1260void AIS_ViewController::AbortViewAnimation()
1261{
1262 if (!myViewAnimation.IsNull()
1263 && !myViewAnimation->IsStopped())
1264 {
1265 myViewAnimation->Stop();
1266 myViewAnimation->SetView (Handle(V3d_View)());
1267 }
1268}
1269
49582f9d 1270// =======================================================================
1271// function : handlePanning
1272// purpose :
1273// =======================================================================
1274void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1275{
1276 if (!myGL.Panning.ToPan
1277 || !myToAllowPanning)
1278 {
1279 return;
1280 }
1281
2108d9a2 1282 AbortViewAnimation();
1283
49582f9d 1284 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1285 if (aCam->IsOrthographic()
1286 || !hasPanningAnchorPoint())
1287 {
1288 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1289 theView->Invalidate();
1290 return;
1291 }
1292
1293 Graphic3d_Vec2i aWinSize;
1294 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1295
1296 const gp_Dir& aDir = aCam->Direction();
1297 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1298 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1299 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1300 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1301 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1302
1303 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1304 gp_Trsf aPanTrsf;
1305 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1306 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1307 aPanTrsf.SetTranslation (aCameraPan);
1308 aCam->Transform (aPanTrsf);
1309 theView->Invalidate();
1310}
1311
1312// =======================================================================
1313// function : handleZRotate
1314// purpose :
1315// =======================================================================
1316void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1317{
1318 if (!myGL.ZRotate.ToRotate
1319 || !myToAllowRotation)
1320 {
1321 return;
1322 }
1323
2108d9a2 1324 AbortViewAnimation();
1325
49582f9d 1326 Graphic3d_Vec2i aViewPort;
1327 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1328 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1329 0.5 * aViewPort.y());
1330 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1331 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1332 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1333 theView->Invalidate();
1334}
1335
1336// =======================================================================
1337// function : handleZoom
1338// purpose :
1339// =======================================================================
1340void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1341 const Aspect_ScrollDelta& theParams,
1342 const gp_Pnt* thePnt)
1343{
1344 if (!myToAllowZooming)
1345 {
1346 return;
1347 }
1348
2108d9a2 1349 AbortViewAnimation();
1350
49582f9d 1351 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1352 if (thePnt != NULL)
1353 {
1354 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1355 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1356 }
1357
1358 if (!theParams.HasPoint())
1359 {
1360 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1361 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1362 theView->SetZoom (aCoeff, true);
1363 theView->Invalidate();
1364 return;
1365 }
1366
1367 // integer delta is too rough for small smooth increments
1368 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1369 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1370
1371 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1372 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1373 if (aDZoom <= 0.0)
1374 {
1375 return;
1376 }
1377
1378 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1379
1380 // ensure that zoom will not be too small or too big
1381 double aCoef = aDZoom;
1382 if (aViewDims.x() < aCoef * Precision::Confusion())
1383 {
1384 aCoef = aViewDims.x() / Precision::Confusion();
1385 }
1386 else if (aViewDims.x() > aCoef * 1e12)
1387 {
1388 aCoef = aViewDims.x() / 1e12;
1389 }
1390 if (aViewDims.y() < aCoef * Precision::Confusion())
1391 {
1392 aCoef = aViewDims.y() / Precision::Confusion();
1393 }
1394 else if (aViewDims.y() > aCoef * 1e12)
1395 {
1396 aCoef = aViewDims.y() / 1e12;
1397 }
1398
1399 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1400 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1401 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1402 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1403 aCam->SetScale (aCam->Scale() / aCoef);
1404
1405 const gp_Dir& aDir = aCam->Direction();
1406 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1407
1408 // pan back to the point
1409 aDxy = aZoomAtPointXYv - aDxy;
1410 if (thePnt != NULL)
1411 {
1412 // zoom at 3D point with perspective projection
1413 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1414 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1415 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1416
1417 // view dimensions at 3D point
1418 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1419
1420 Graphic3d_Vec2i aWinSize;
1421 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1422 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
9460f8c0 1423 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
49582f9d 1424 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
9460f8c0 1425 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
49582f9d 1426 }
1427
1428 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1429 gp_Trsf aPanTrsf;
1430 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1431 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1432 aPanTrsf.SetTranslation (aCameraPan);
1433 aCam->Transform (aPanTrsf);
1434 theView->Invalidate();
1435}
1436
1437// =======================================================================
1438// function : handleZFocusScroll
1439// purpose :
1440// =======================================================================
1441void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1442 const Aspect_ScrollDelta& theParams)
1443{
1444 if (!myToAllowZFocus
1445 || !theView->Camera()->IsStereo())
1446 {
1447 return;
1448 }
1449
1450 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1451 if (aFocus > 0.2
1452 && aFocus < 2.0)
1453 {
1454 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1455 theView->Redraw();
1456 }
1457}
1458
1459// =======================================================================
1460// function : handleOrbitRotation
1461// purpose :
1462// =======================================================================
1463void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1464 const gp_Pnt& thePnt,
1465 bool theToLockZUp)
1466{
1467 if (!myToAllowRotation)
1468 {
1469 return;
1470 }
1471
1472 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1473 if (myGL.OrbitRotation.ToStart)
1474 {
1475 // default alternatives
1476 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1477 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1478
1479 myRotatePnt3d = thePnt;
1480 myCamStartOpUp = aCam->Up();
607e5e62 1481 myCamStartOpDir = aCam->Direction();
49582f9d 1482 myCamStartOpEye = aCam->Eye();
1483 myCamStartOpCenter = aCam->Center();
1484
1485 gp_Trsf aTrsf;
1486 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1487 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1488 const gp_Quaternion aRot = aTrsf.GetRotation();
1489 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1490
1491 aTrsf.Invert();
1492 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1493 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1494
1495 theView->Invalidate();
1496 }
1497
1498 if (!myGL.OrbitRotation.ToRotate)
1499 {
1500 return;
1501 }
1502
2108d9a2 1503 AbortViewAnimation();
49582f9d 1504 if (theToLockZUp)
1505 {
1506 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1507 Graphic3d_Vec2i aWinXY;
1508 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1509 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1510 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1511 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1512 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1513 const double aRoll = 0.0;
1514
1515 gp_Quaternion aRot;
1516 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1517 gp_Trsf aTrsfRot;
1518 aTrsfRot.SetRotation (aRot);
1519
1520 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1521 aCam->SetUp (aNewUp);
607e5e62 1522 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1523 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1524
49582f9d 1525 aCam->OrthogonalizeUp();
1526 }
1527 else
1528 {
1529 // default alternatives
1530 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1531 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1532
1533 // restore previous camera state
607e5e62 1534 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1535 aCam->SetUp (myCamStartOpUp);
1536 aCam->SetDirectionFromEye (myCamStartOpDir);
49582f9d 1537
1538 Graphic3d_Vec2d aWinXY;
1539 theView->Size (aWinXY.x(), aWinXY.y());
1540 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1541 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1542
1543 const double THE_2PI = M_PI * 2.0;
1544 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1545 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1546
1547 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1548 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1549 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1550 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1551
1552 // rotate camera around 3 initial axes
1553 gp_Dir aCamDir (aCam->Direction().Reversed());
1554 gp_Dir aCamUp (aCam->Up());
1555 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1556
1557 gp_Trsf aRot[2], aTrsf;
1558 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1559 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1560 aTrsf.Multiply (aRot[0]);
1561 aTrsf.Multiply (aRot[1]);
1562
1563 aCam->Transform (aTrsf);
1564 }
1565
1566 theView->Invalidate();
1567}
1568
1569// =======================================================================
1570// function : handleViewRotation
1571// purpose :
1572// =======================================================================
1573void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1574 double theYawExtra,
1575 double thePitchExtra,
1576 double theRoll,
1577 bool theToRestartOnIncrement)
1578{
1579 if (!myToAllowRotation)
1580 {
1581 return;
1582 }
1583
1584 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1585 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1586 || Abs (thePitchExtra) > gp::Resolution()
1587 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1588 if (toRotateAnyway
1589 && theToRestartOnIncrement)
1590 {
1591 myGL.ViewRotation.ToStart = true;
1592 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1593 }
1594 if (myGL.ViewRotation.ToStart)
1595 {
1596 gp_Trsf aTrsf;
1597 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1598 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1599 const gp_Quaternion aRot = aTrsf.GetRotation();
1600 double aRollDummy = 0.0;
1601 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1602 }
1603 if (toRotateAnyway)
1604 {
1605 myRotateStartYawPitchRoll[0] += theYawExtra;
1606 myRotateStartYawPitchRoll[1] += thePitchExtra;
1607 myRotateStartYawPitchRoll[2] = theRoll;
1608 myGL.ViewRotation.ToRotate = true;
1609 }
1610
1611 if (!myGL.ViewRotation.ToRotate)
1612 {
1613 return;
1614 }
1615
2108d9a2 1616 AbortViewAnimation();
1617
49582f9d 1618 Graphic3d_Vec2i aWinXY;
1619 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1620 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1621 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1622 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1623 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1624 gp_Quaternion aRot;
1625 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1626 gp_Trsf aTrsfRot;
1627 aTrsfRot.SetRotation (aRot);
1628
49582f9d 1629 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1630 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
607e5e62 1631 aCam->SetUp (aNewUp);
1632 aCam->SetDirectionFromEye (aNewDir);
49582f9d 1633 aCam->OrthogonalizeUp();
1634 theView->Invalidate();
1635}
1636
1637// =======================================================================
1638// function : PickPoint
1639// purpose :
1640// =======================================================================
1641bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1642 const Handle(AIS_InteractiveContext)& theCtx,
1643 const Handle(V3d_View)& theView,
1644 const Graphic3d_Vec2i& theCursor,
1645 bool theToStickToPickRay)
1646{
1647 ResetPreviousMoveTo();
1648
1649 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1650 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1651 if (aSelector->NbPicked() < 1)
1652 {
1653 return false;
1654 }
1655
1656 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1657 if (theToStickToPickRay
1658 && !Precision::IsInfinite (aPicked.Depth))
1659 {
1660 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1661 }
1662 else
1663 {
1664 thePnt = aSelector->PickedPoint (1);
1665 }
1666 return !Precision::IsInfinite (thePnt.X())
1667 && !Precision::IsInfinite (thePnt.Y())
1668 && !Precision::IsInfinite (thePnt.Z());
1669}
1670
1671// =======================================================================
1672// function : GravityPoint
1673// purpose :
1674// =======================================================================
1675gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1676 const Handle(V3d_View)& theView)
1677{
1678 switch (myRotationMode)
1679 {
1680 case AIS_RotationMode_PickLast:
1681 case AIS_RotationMode_PickCenter:
1682 {
1683 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1684 if (myRotationMode == AIS_RotationMode_PickCenter)
1685 {
1686 Graphic3d_Vec2i aViewPort;
1687 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1688 aCursor = aViewPort / 2;
1689 }
1690
1691 gp_Pnt aPnt;
9460f8c0 1692 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
49582f9d 1693 {
1694 return aPnt;
1695 }
1696 break;
1697 }
1698 case AIS_RotationMode_CameraAt:
1699 {
1700 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1701 return aCam->Center();
1702 }
1703 case AIS_RotationMode_BndBoxScene:
1704 {
1705 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1706 if (!aBndBox.IsVoid())
1707 {
1708 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1709 }
1710 break;
1711 }
1712 case AIS_RotationMode_BndBoxActive:
1713 break;
1714 }
1715
1716 return theCtx ->GravityPoint (theView);
1717}
1718
1719// =======================================================================
1720// function : handleCameraActions
1721// purpose :
1722// =======================================================================
1723void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
1724 const Handle(V3d_View)& theView,
1725 const AIS_WalkDelta& theWalk)
1726{
1727 // apply view actions
1728 if (myGL.Orientation.ToSetViewOrient)
1729 {
1730 theView->SetProj (myGL.Orientation.ViewOrient);
1731 myGL.Orientation.ToFitAll = true;
1732 }
1733
1734 // apply fit all
1735 if (myGL.Orientation.ToFitAll)
1736 {
1737 const double aFitMargin = 0.01;
1738 theView->FitAll (aFitMargin, false);
1739 theView->Invalidate();
1740 myGL.Orientation.ToFitAll = false;
1741 }
1742
1743 if (myGL.IsNewGesture)
1744 {
1745 if (myAnchorPointPrs1->HasInteractiveContext())
1746 {
1747 theCtx->Remove (myAnchorPointPrs1, false);
1748 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
1749 {
1750 theView->Invalidate();
1751 }
1752 else
1753 {
1754 theView->InvalidateImmediate();
1755 }
1756 }
1757 if (myAnchorPointPrs2->HasInteractiveContext())
1758 {
1759 theCtx->Remove (myAnchorPointPrs2, false);
1760 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
1761 {
1762 theView->Invalidate();
1763 }
1764 else
1765 {
1766 theView->InvalidateImmediate();
1767 }
1768 }
1769
1770 if (myHasHlrOnBeforeRotation)
1771 {
1772 myHasHlrOnBeforeRotation = false;
1773 theView->SetComputedMode (true);
1774 theView->Invalidate();
1775 }
1776 }
1777
1778 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
1779 {
1780 if (myGL.Panning.ToStart
1781 && myToAllowPanning)
1782 {
1783 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
1784 if (!theView->Camera()->IsOrthographic())
1785 {
1786 bool toStickToRay = false;
1787 if (myGL.Panning.PointStart.x() >= 0
1788 && myGL.Panning.PointStart.y() >= 0)
1789 {
1790 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
1791 }
1792 if (Precision::IsInfinite (aPanPnt.X()))
1793 {
1794 Graphic3d_Vec2i aWinSize;
1795 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1796 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
1797 }
1798 if (!Precision::IsInfinite (aPanPnt.X())
1799 && myToShowPanAnchorPoint)
1800 {
1801 gp_Trsf aPntTrsf;
1802 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
1803 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1804 }
1805 }
1806 setPanningAnchorPoint (aPanPnt);
1807 }
1808
1809 if (myToShowPanAnchorPoint
1810 && hasPanningAnchorPoint()
1811 && myGL.Panning.ToPan
1812 && !myGL.IsNewGesture
1813 && !myAnchorPointPrs2->HasInteractiveContext())
1814 {
1815 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1816 }
1817
1818 handlePanning (theView);
1819 handleZRotate (theView);
1820 }
1821
1822 if ((myNavigationMode == AIS_NavigationMode_Orbit
1823 || myGL.OrbitRotation.ToStart
1824 || myGL.OrbitRotation.ToRotate)
1825 && myToAllowRotation)
1826 {
1827 if (myGL.OrbitRotation.ToStart
1828 && !myHasHlrOnBeforeRotation)
1829 {
1830 myHasHlrOnBeforeRotation = theView->ComputedMode();
1831 if (myHasHlrOnBeforeRotation)
1832 {
1833 theView->SetComputedMode (false);
1834 }
1835 }
1836
1837 gp_Pnt aGravPnt;
1838 if (myGL.OrbitRotation.ToStart)
1839 {
1840 aGravPnt = GravityPoint (theCtx, theView);
1841 if (myToShowRotateCenter)
1842 {
1843 gp_Trsf aPntTrsf;
1844 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
1845 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
1846 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
1847 }
1848 }
1849
1850 if (myToShowRotateCenter
1851 && myGL.OrbitRotation.ToRotate
1852 && !myGL.IsNewGesture
1853 && !myAnchorPointPrs1->HasInteractiveContext())
1854 {
1855 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
1856 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
1857 }
1858 handleOrbitRotation (theView, aGravPnt,
1859 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
1860 }
1861
1862 if ((myNavigationMode != AIS_NavigationMode_Orbit
1863 || myGL.ViewRotation.ToStart
1864 || myGL.ViewRotation.ToRotate)
1865 && myToAllowRotation)
1866 {
1867 if (myGL.ViewRotation.ToStart
1868 && !myHasHlrOnBeforeRotation)
1869 {
1870 myHasHlrOnBeforeRotation = theView->ComputedMode();
1871 if (myHasHlrOnBeforeRotation)
1872 {
1873 theView->SetComputedMode (false);
1874 }
1875 }
1876
1877 double aRoll = 0.0;
1878 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
1879 && !myToLockOrbitZUp)
1880 {
1881 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
1882 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
1883 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
1884 {
1885 aRoll = -aRoll;
1886 }
1887 }
1888
1889 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
1890 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
1891 }
1892
1893 if (!myGL.ZoomActions.IsEmpty())
1894 {
1895 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
1896 {
1897 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
1898 if (myToAllowZFocus
1899 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
1900 && theView->Camera()->IsStereo())
1901 {
1902 handleZFocusScroll (theView, aZoomParams);
1903 continue;
1904 }
1905
1906 if (!myToAllowZooming)
1907 {
1908 continue;
1909 }
1910
1911 if (!theView->Camera()->IsOrthographic())
1912 {
49582f9d 1913 gp_Pnt aPnt;
1914 if (aZoomParams.HasPoint()
9460f8c0 1915 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
49582f9d 1916 {
1917 handleZoom (theView, aZoomParams, &aPnt);
1918 continue;
1919 }
1920
1921 Graphic3d_Vec2i aWinSize;
1922 theView->Window()->Size (aWinSize.x(), aWinSize.y());
9460f8c0 1923 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom))
49582f9d 1924 {
1925 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
1926 handleZoom (theView, aZoomParams, &aPnt);
1927 continue;
1928 }
1929 }
1930 handleZoom (theView, aZoomParams, NULL);
1931 }
1932 myGL.ZoomActions.Clear();
1933 }
1934}
1935
1936// =======================================================================
1937// function : OnSelectionChanged
1938// purpose :
1939// =======================================================================
1940void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
1941 const Handle(V3d_View)& )
1942{
1943 //
1944}
1945
1946// =======================================================================
1947// function : OnObjectDragged
1948// purpose :
1949// =======================================================================
1950void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
1951 const Handle(V3d_View)& theView,
1952 AIS_DragAction theAction)
1953{
1954 switch (theAction)
1955 {
1956 case AIS_DragAction_Start:
1957 {
1958 myDragObject.Nullify();
1959 if (!theCtx->HasDetected())
1960 {
1961 return;
1962 }
1963
1964 Handle(AIS_InteractiveObject) aPrs = theCtx->DetectedInteractive();
1965 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (aPrs))
1966 {
1967 if (aManip->HasActiveMode())
1968 {
1969 myDragObject = aManip;
1970 aManip->StartTransform (myGL.Dragging.PointStart.x(), myGL.Dragging.PointStart.y(), theView);
1971 }
1972 }
1973 return;
1974 }
1975 case AIS_DragAction_Update:
1976 {
1977 if (myDragObject.IsNull())
1978 {
1979 return;
1980 }
1981
1982 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
1983 {
1984 theCtx->SetSelectedState (aGlobOwner, true);
1985 }
1986 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
1987 {
1988 aManip->Transform (myGL.Dragging.PointTo.x(), myGL.Dragging.PointTo.y(), theView);
1989 }
1990 theView->Invalidate();
1991 return;
1992 }
1993 case AIS_DragAction_Abort:
1994 {
1995 if (myDragObject.IsNull())
1996 {
1997 return;
1998 }
1999
2000 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
2001 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2002
2003 if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject))
2004 {
2005 aManip->StopTransform (false);
2006 }
2007 Standard_FALLTHROUGH
2008 }
2009 case AIS_DragAction_Stop:
2010 {
2011 if (myDragObject.IsNull())
2012 {
2013 return;
2014 }
2015
2016 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2017 {
2018 theCtx->SetSelectedState (aGlobOwner, false);
2019 }
2020
2021 theView->Invalidate();
2022 myDragObject.Nullify();
2023 return;
2024 }
2025 }
2026}
2027
2028// =======================================================================
2029// function : contextLazyMoveTo
2030// purpose :
2031// =======================================================================
2032void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2033 const Handle(V3d_View)& theView,
2034 const Graphic3d_Vec2i& thePnt)
2035{
2036 if (myPrevMoveTo == thePnt)
2037 {
2038 return;
2039 }
2040
2041 myPrevMoveTo = thePnt;
2042
2043 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2044 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2045 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2046
2047 if (theView->Viewer()->Grid()->IsActive()
2048 && theView->Viewer()->GridEcho())
2049 {
2050 if (aNewPicked.IsNull())
2051 {
2052 Graphic3d_Vec3d aPnt3d;
2053 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2054 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2055 theView->InvalidateImmediate();
2056 }
2057 else
2058 {
2059 theView->Viewer()->HideGridEcho (theView);
2060 theView->InvalidateImmediate();
2061 }
2062 }
2063
2064 if (aLastPicked != aNewPicked
2065 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2066 {
2067 // dynamic highlight affects all Views
2068 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2069 {
2070 const Handle(V3d_View)& aView = aViewIter.Value();
2071 aView->InvalidateImmediate();
2072 }
2073 }
2074}
2075
2076// =======================================================================
2077// function : handleSelectionPick
2078// purpose :
2079// =======================================================================
2080void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2081 const Handle(V3d_View)& theView)
2082{
2083 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2084 && !myGL.Selection.Points.IsEmpty())
2085 {
2086 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2087 {
49582f9d 2088 const bool hadPrevMoveTo = HasPreviousMoveTo();
2089 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2090 if (!hadPrevMoveTo)
2091 {
2092 ResetPreviousMoveTo();
2093 }
2094
2095 if (myGL.Selection.IsXOR)
2096 {
2097 theCtx->ShiftSelect (false);
2098 }
2099 else
2100 {
2101 theCtx->Select (false);
2102 }
2103
2104 // selection affects all Views
2105 theView->Viewer()->Invalidate();
2106
2107 OnSelectionChanged (theCtx, theView);
2108 }
2109
2110 myGL.Selection.Points.Clear();
2111 }
2112}
2113
2114// =======================================================================
2115// function : handleSelectionPoly
2116// purpose :
2117// =======================================================================
2118void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2119 const Handle(V3d_View)& theView)
2120{
2121 // rubber-band & window polygon selection
2122 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
e1c9a103 2123 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon
2124 || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow)
49582f9d 2125 {
2126 if (!myGL.Selection.Points.IsEmpty())
2127 {
2128 myRubberBand->ClearPoints();
2129 myRubberBand->SetToUpdate();
2130
e1c9a103 2131 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2132 || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow;
49582f9d 2133 if (anIsRubber)
2134 {
2135 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2136 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2137 }
2138 else
2139 {
2140 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2141 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2142 {
2143 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2144 if (aPntNew != aPrev)
2145 {
2146 aPrev = aPntNew;
2147 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2148 }
2149 }
2150 }
2151
2152 myRubberBand->SetPolygonClosed (anIsRubber);
2153 try
2154 {
2155 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2156 }
2157 catch (const Standard_Failure& theEx)
2158 {
2159 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2160 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString(), Message_Warning);
2161 myRubberBand->ClearPoints();
2162 }
2163 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2164 {
2165 theView->Invalidate();
2166 }
2167 else
2168 {
2169 theView->InvalidateImmediate();
2170 }
2171 }
2172 else if (!myRubberBand.IsNull()
2173 && myRubberBand->HasInteractiveContext())
2174 {
2175 theCtx->Remove (myRubberBand, false);
2176 myRubberBand->ClearPoints();
2177 }
2178 }
2179
2180 if (myGL.Selection.ToApplyTool)
2181 {
2182 myGL.Selection.ToApplyTool = false;
2183 if (theCtx->IsDisplayed (myRubberBand))
2184 {
2185 theCtx->Remove (myRubberBand, false);
2186 {
2187 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2188 if (aPoints.Size() == 4
2189 && aPoints.Value (1).x() == aPoints.Value (2).x()
2190 && aPoints.Value (3).x() == aPoints.Value (4).x()
2191 && aPoints.Value (1).y() == aPoints.Value (4).y()
2192 && aPoints.Value (2).y() == aPoints.Value (3).y())
2193 {
2194 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2195 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
e1c9a103 2196 if (myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow)
49582f9d 2197 {
e1c9a103 2198 theView->WindowFitAll (aPnt1.x(), aPnt1.y(), aPnt2.x(), aPnt2.y());
2199 theView->Invalidate();
49582f9d 2200 }
2201 else
2202 {
e1c9a103 2203 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2204 if (myGL.Selection.IsXOR)
2205 {
2206 theCtx->ShiftSelect (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2207 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2208 theView, false);
2209 }
2210 else
2211 {
2212 theCtx->Select (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()),
2213 Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()),
2214 theView, false);
2215 }
2216 theCtx->MainSelector()->AllowOverlapDetection (false);
49582f9d 2217 }
49582f9d 2218 }
2219 else if (aPoints.Length() >= 3)
2220 {
2221 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2222 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2223 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2224 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2225 {
2226 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2227 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2228 }
2229
49582f9d 2230 if (myGL.Selection.IsXOR)
2231 {
2232 theCtx->ShiftSelect (aPolyline, theView, false);
2233 }
2234 else
2235 {
2236 theCtx->Select (aPolyline, theView, false);
2237 }
a24a7821 2238 theCtx->MainSelector()->AllowOverlapDetection (false);
49582f9d 2239 }
2240 }
2241
49582f9d 2242 myRubberBand->ClearPoints();
e1c9a103 2243 if (myGL.Selection.Tool != AIS_ViewSelectionTool_ZoomWindow)
2244 {
2245 // selection affects all Views
2246 theView->Viewer()->Invalidate();
2247 OnSelectionChanged (theCtx, theView);
2248 }
49582f9d 2249 }
2250 }
2251}
2252
2253// =======================================================================
2254// function : handleDynamicHighlight
2255// purpose :
2256// =======================================================================
2257void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2258 const Handle(V3d_View)& theView)
2259{
2260 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2261 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2262 {
2263 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2264 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2265 && !HasPreviousMoveTo())
2266 {
2267 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2268 ResetPreviousMoveTo();
2269 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2270 theCtx->ClearDetected();
2271 }
2272 else if (myToAllowHighlight)
2273 {
2274 if (myPrevMoveTo != aMoveToPnt
2275 || myGL.OrbitRotation.ToRotate
2276 || myGL.ViewRotation.ToRotate
2277 || theView->IsInvalidated())
2278 {
2279 ResetPreviousMoveTo();
2280 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2281 }
2282 if (myGL.Dragging.ToStart)
2283 {
2284 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2285 }
2286 }
2287
2288 myGL.MoveTo.ToHilight = false;
2289 }
2290
2291 if (!myDragObject.IsNull())
2292 {
2293 if (myGL.Dragging.ToAbort)
2294 {
2295 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2296 myGL.OrbitRotation.ToRotate = false;
2297 myGL.ViewRotation .ToRotate = false;
2298 }
2299 else if (myGL.Dragging.ToStop)
2300 {
2301 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2302 myGL.OrbitRotation.ToRotate = false;
2303 myGL.ViewRotation .ToRotate = false;
2304 }
2305 else if (myGL.OrbitRotation.ToRotate
2306 || myGL.ViewRotation.ToRotate)
2307 {
2308 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2309 myGL.OrbitRotation.ToRotate = false;
2310 myGL.ViewRotation .ToRotate = false;
2311 }
2312 }
2313}
2314
2315// =======================================================================
2316// function : handleMoveTo
2317// purpose :
2318// =======================================================================
2319void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2320 const Handle(V3d_View)& theView)
2321{
2322 handleSelectionPick (theCtx, theView);
2323 handleDynamicHighlight(theCtx, theView);
2324 handleSelectionPoly (theCtx, theView);
2325}
2326
2327// =======================================================================
2328// function : handleViewRedraw
2329// purpose :
2330// =======================================================================
2331void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2332 const Handle(V3d_View)& theView)
2333{
2108d9a2 2334 // manage animation state
2335 if (!myViewAnimation.IsNull()
2336 && !myViewAnimation->IsStopped())
2337 {
2338 myViewAnimation->UpdateTimer();
2339 ResetPreviousMoveTo();
2340 setAskNextFrame();
2341 }
2342
49582f9d 2343 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2344 {
2345 const Handle(V3d_View)& aView = aViewIter.Value();
2346 if (aView->IsInvalidated()
2347 || myToAskNextFrame)
2348 {
2349 if (aView->ComputedMode())
2350 {
2351 aView->Update();
2352 }
2353 else
2354 {
2355 aView->Redraw();
2356 }
2357 }
2358 else if (aView->IsInvalidatedImmediate())
2359 {
2360 aView->RedrawImmediate();
2361 }
2362 }
2363
2364 if (myToAskNextFrame)
2365 {
2366 // ask more frames
2367 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
2368 }
2369}
2370
2371// =======================================================================
2372// function : HandleViewEvents
2373// purpose :
2374// =======================================================================
2375void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
2376 const Handle(V3d_View)& theView)
2377{
2378 handleMoveTo (theCtx, theView);
2379
2380 const AIS_WalkDelta aWalk = FetchNavigationKeys (1.0, 1.0);
2381 handleCameraActions (theCtx, theView, aWalk);
2382 handleViewRedraw (theCtx, theView);
2383
2384 // make sure to not process the same events twice
2385 myGL.Reset();
2386 myToAskNextFrame = false;
2387}