/*========================================================================= Program: Visualization Toolkit Module: vtkRenderWindowInteractor.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkRenderWindowInteractor.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkGraphicsFactory.h" #include "vtkInteractorStyleSwitchBase.h" #include "vtkMath.h" #include "vtkPropPicker.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkRendererCollection.h" #include "vtkDebugLeaks.h" #include "vtkObserverMediator.h" #include "vtkPickingManager.h" #include // PIMPL'd class to keep track of timers. It maps the ids returned by CreateTimer() // to the platform-specific representation for timer ids. struct vtkTimerStruct { int Id; int Type; unsigned long Duration; vtkTimerStruct() : Id(0),Type(vtkRenderWindowInteractor::OneShotTimer),Duration(10) {} vtkTimerStruct(int platformTimerId, int timerType, unsigned long duration) { this->Id = platformTimerId; this->Type = timerType; this->Duration = duration; } }; class vtkTimerIdMap : public std::map {}; typedef std::map::iterator vtkTimerIdMapIterator; // Initialize static variable that keeps track of timer ids for // render window interactors. static int vtkTimerId = 1; //---------------------------------------------------------------------------- vtkCxxSetObjectMacro(vtkRenderWindowInteractor,Picker,vtkAbstractPicker); //---------------------------------------------------------------------- // Construct object so that light follows camera motion. vtkRenderWindowInteractor::vtkRenderWindowInteractor() { this->RenderWindow = nullptr; // Here we are using base, and relying on the graphics factory or standard // object factory logic to create the correct instance, which should be the // vtkInteractorStyleSwitch when linked to the interactor styles, or // vtkInteractorStyleSwitchBase if the style module is not linked. this->InteractorStyle = nullptr; this->SetInteractorStyle(vtkInteractorStyleSwitchBase::New()); this->InteractorStyle->Delete(); this->LightFollowCamera = 1; this->Initialized = 0; this->Enabled = 0; this->EnableRender = true; this->DesiredUpdateRate = 15; // default limit is 3 hours per frame this->StillUpdateRate = 0.0001; this->Picker = this->CreateDefaultPicker(); this->Picker->Register(this); this->Picker->Delete(); this->PickingManager = nullptr; vtkPickingManager* pm = this->CreateDefaultPickingManager(); this->SetPickingManager(pm); pm->Delete(); this->EventPosition[0] = this->LastEventPosition[0] = 0; this->EventPosition[1] = this->LastEventPosition[1] = 0; for (int i = 0; i < VTKI_MAX_POINTERS; ++i) { this->EventPositions[i][0] = this->LastEventPositions[i][0] = 0; this->EventPositions[i][1] = this->LastEventPositions[i][1] = 0; } this->PointerIndex = 0; this->EventSize[0] = 0; this->EventSize[1] = 0; this->Size[0] = 0; this->Size[1] = 0; this->NumberOfFlyFrames = 15; this->Dolly = 0.30; this->AltKey = 0; this->ControlKey = 0; this->ShiftKey = 0; this->KeyCode = 0; this->Rotation = 0; this->LastRotation = 0; this->Scale = 0; this->LastScale = 0; this->RepeatCount = 0; this->KeySym = nullptr; this->TimerEventId = 0; this->TimerEventType = 0; this->TimerEventDuration = 0; this->TimerEventPlatformId = 0; this->TimerMap = new vtkTimerIdMap; this->TimerDuration = 10; this->ObserverMediator = nullptr; this->HandleEventLoop = false; this->UseTDx=false; // 3DConnexion device. for (int i=0; i < VTKI_MAX_POINTERS; i++) { this->PointerIndexLookup[i] = 0; this->PointersDown[i] = 0; } this->RecognizeGestures = true; this->PointersDownCount = 0; this->CurrentGesture = vtkCommand::StartEvent; } //---------------------------------------------------------------------- vtkRenderWindowInteractor::~vtkRenderWindowInteractor() { if (this->InteractorStyle != nullptr) { this->InteractorStyle->UnRegister(this); } if ( this->Picker) { this->Picker->UnRegister(this); } delete [] this->KeySym; if ( this->ObserverMediator) { this->ObserverMediator->Delete(); } delete this->TimerMap; this->SetPickingManager(nullptr); this->SetRenderWindow(nullptr); } //---------------------------------------------------------------------- vtkRenderWindowInteractor *vtkRenderWindowInteractor::New() { // First try to create the object from the vtkObjectFactory vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkRenderWindowInteractor"); if ( ret ) { return static_cast(ret); } vtkRenderWindowInteractor *o = new vtkRenderWindowInteractor; o->InitializeObjectBase(); return o; } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::Render() { if (this->RenderWindow && this->Enabled && this->EnableRender) { this->RenderWindow->Render(); } // outside the above test so that third-party code can redirect // the render to the appropriate class this->InvokeEvent(vtkCommand::RenderEvent, nullptr); } //---------------------------------------------------------------------- // treat renderWindow and interactor as one object. // it might be easier if the GetReference count method were redefined. void vtkRenderWindowInteractor::UnRegister(vtkObjectBase *o) { if (this->RenderWindow && this->RenderWindow->GetInteractor() == this && this->RenderWindow != o) { if (this->GetReferenceCount()+this->RenderWindow->GetReferenceCount() == 3) { this->RenderWindow->SetInteractor(nullptr); this->SetRenderWindow(nullptr); } } this->vtkObject::UnRegister(o); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::Start() { // Let the compositing handle the event loop if it wants to. if (this->HasObserver(vtkCommand::StartEvent) && !this->HandleEventLoop) { this->InvokeEvent(vtkCommand::StartEvent,nullptr); return; } // As a convenience, initialize if we aren't initialized yet. if (!this->Initialized) { this->Initialize(); if (!this->Initialized) { return; } } // Pass execution to the subclass which will run the event loop, // this will not return until TerminateApp is called. this->StartEventLoop(); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::SetRenderWindow(vtkRenderWindow *aren) { if (this->RenderWindow != aren) { // to avoid destructor recursion vtkRenderWindow *temp = this->RenderWindow; this->RenderWindow = aren; if (temp != nullptr) { temp->UnRegister(this); } if (this->RenderWindow != nullptr) { this->RenderWindow->Register(this); if (this->RenderWindow->GetInteractor() != this) { this->RenderWindow->SetInteractor(this); } } } } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::SetInteractorStyle(vtkInteractorObserver *style) { if (this->InteractorStyle != style) { // to avoid destructor recursion vtkInteractorObserver *temp = this->InteractorStyle; this->InteractorStyle = style; if (temp != nullptr) { temp->SetInteractor(nullptr); temp->UnRegister(this); } if (this->InteractorStyle != nullptr) { this->InteractorStyle->Register(this); if (this->InteractorStyle->GetInteractor() != this) { this->InteractorStyle->SetInteractor(this); } } } } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::UpdateSize(int x,int y) { // if the size changed send this on to the RenderWindow if ((x != this->Size[0])||(y != this->Size[1])) { this->Size[0] = this->EventSize[0] = x; this->Size[1] = this->EventSize[1] = y; this->RenderWindow->SetSize(x,y); } } // This function is used to return an index given an ID // and allocate one if needed int vtkRenderWindowInteractor::GetPointerIndexForContact(size_t dwID) { for (int i=0; i < VTKI_MAX_POINTERS; i++) { if (this->PointerIndexLookup[i] == dwID+1) { return i; } } for (int i=0; i < VTKI_MAX_POINTERS; i++) { if (this->PointerIndexLookup[i] == 0) { this->PointerIndexLookup[i] = dwID+1; return i; } } // Out of contacts return -1; } // This function is used to return an index given an ID int vtkRenderWindowInteractor::GetPointerIndexForExistingContact(size_t dwID) { for (int i=0; i < VTKI_MAX_POINTERS; i++) { if (this->PointerIndexLookup[i] == dwID+1) { return i; } } // Not found return -1; } void vtkRenderWindowInteractor::ClearContact(size_t dwID) { for (int i=0; i < VTKI_MAX_POINTERS; i++) { if (this->PointerIndexLookup[i] == dwID+1) { this->PointerIndexLookup[i] = 0; return; } } } void vtkRenderWindowInteractor::ClearPointerIndex(int i) { if (i < VTKI_MAX_POINTERS) { this->PointerIndexLookup[i] = 0; } } // This function is used to return an index given an ID bool vtkRenderWindowInteractor::IsPointerIndexSet(int i) { if (i < VTKI_MAX_POINTERS) { return (this->PointerIndexLookup[i] != 0); } return false; } //---------------------------------------------------------------------- // Creates an instance of vtkPropPicker by default vtkAbstractPropPicker *vtkRenderWindowInteractor::CreateDefaultPicker() { return vtkPropPicker::New(); } //---------------------------------------------------------------------- // Creates an instance of vtkPickingManager by default vtkPickingManager* vtkRenderWindowInteractor::CreateDefaultPickingManager() { return vtkPickingManager::New(); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::SetPickingManager(vtkPickingManager* pm) { if(this->PickingManager == pm) { return; } vtkPickingManager* tempPickingManager = this->PickingManager; this->PickingManager = pm; if (this->PickingManager) { this->PickingManager->Register(this); this->PickingManager->SetInteractor(this); } if(tempPickingManager) { tempPickingManager->SetInteractor(nullptr); tempPickingManager->UnRegister(this); } this->Modified(); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::ExitCallback() { if (this->HasObserver(vtkCommand::ExitEvent)) { this->InvokeEvent(vtkCommand::ExitEvent,nullptr); } else { this->TerminateApp(); } } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::UserCallback() { this->InvokeEvent(vtkCommand::UserEvent,nullptr); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::StartPickCallback() { this->InvokeEvent(vtkCommand::StartPickEvent,nullptr); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::EndPickCallback() { this->InvokeEvent(vtkCommand::EndPickEvent,nullptr); } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::FlyTo(vtkRenderer *ren, double x, double y, double z) { double flyFrom[3], flyTo[3]; double d[3], focalPt[3]; int i, j; flyTo[0]=x; flyTo[1]=y; flyTo[2]=z; ren->GetActiveCamera()->GetFocalPoint(flyFrom); for (i=0; i<3; i++) { d[i] = flyTo[i] - flyFrom[i]; } double distance = vtkMath::Normalize(d); double delta = distance/this->NumberOfFlyFrames; for (i=1; i<=NumberOfFlyFrames; i++) { for (j=0; j<3; j++) { focalPt[j] = flyFrom[j] + d[j]*i*delta; } ren->GetActiveCamera()->SetFocalPoint(focalPt); ren->GetActiveCamera()->Dolly(this->Dolly/this->NumberOfFlyFrames + 1.0); ren->GetActiveCamera()->OrthogonalizeViewUp(); ren->ResetCameraClippingRange(); this->Render(); } } //---------------------------------------------------------------------- void vtkRenderWindowInteractor::FlyToImage(vtkRenderer *ren, double x, double y) { double flyFrom[3], flyTo[3]; double d[3], focalPt[3], position[3], positionFrom[3]; int i, j; flyTo[0]=x; flyTo[1]=y; ren->GetActiveCamera()->GetFocalPoint(flyFrom); flyTo[2] = flyFrom[2]; ren->GetActiveCamera()->GetPosition(positionFrom); for (i=0; i<2; i++) { d[i] = flyTo[i] - flyFrom[i]; } d[2] = 0.0; double distance = vtkMath::Normalize(d); double delta = distance/this->NumberOfFlyFrames; for (i=1; i<=NumberOfFlyFrames; i++) { for (j=0; j<3; j++) { focalPt[j] = flyFrom[j] + d[j]*i*delta; position[j] = positionFrom[j] + d[j]*i*delta; } ren->GetActiveCamera()->SetFocalPoint(focalPt); ren->GetActiveCamera()->SetPosition(position); ren->GetActiveCamera()->Dolly(this->Dolly/this->NumberOfFlyFrames + 1.0); ren->ResetCameraClippingRange(); this->Render(); } } //---------------------------------------------------------------------------- vtkRenderer* vtkRenderWindowInteractor::FindPokedRenderer(int x,int y) { if (this->RenderWindow == nullptr) { return nullptr; } vtkRenderer *currentRenderer = nullptr, *interactiveren = nullptr, *viewportren = nullptr; vtkRendererCollection* rc = this->RenderWindow->GetRenderers(); int numRens = rc->GetNumberOfItems(); for (int i = numRens -1; (i >= 0) && !currentRenderer; i--) { vtkRenderer *aren = static_cast(rc->GetItemAsObject(i)); if (aren->IsInViewport(x,y) && aren->GetInteractive()) { currentRenderer = aren; } if (interactiveren == nullptr && aren->GetInteractive()) { // Save this renderer in case we can't find one in the viewport that // is interactive. interactiveren = aren; } if (viewportren == nullptr && aren->IsInViewport(x, y)) { // Save this renderer in case we can't find one in the viewport that // is interactive. viewportren = aren; } }//for all renderers // We must have a value. If we found an interactive renderer before, that's // better than a non-interactive renderer. if (currentRenderer == nullptr ) { currentRenderer = interactiveren; } // We must have a value. If we found a renderer that is in the viewport, // that is better than any old viewport (but not as good as an interactive // one). if (currentRenderer == nullptr ) { currentRenderer = viewportren; } // We must have a value - take anything. if (currentRenderer == nullptr) { currentRenderer = rc->GetFirstRenderer(); } return currentRenderer; } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::SetScale(double scale) { this->LastScale = this->Scale; if (this->Scale != scale) { this->Scale = scale; this->Modified(); } } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::SetRotation(double rot) { this->LastRotation = this->Rotation; if (this->Rotation != rot) { this->Rotation = rot; this->Modified(); } } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::SetTranslation(double val[2]) { this->LastTranslation[0] = this->Translation[0]; this->LastTranslation[1] = this->Translation[1]; if (this->Translation[0] != val[0] || this->Translation[1] != val[1]) { this->Translation[0] = val[0]; this->Translation[1] = val[1]; this->Modified(); } } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::RecognizeGesture(vtkCommand::EventIds event) { // we know we are in multitouch now, so start recognizing // more than two pointers we ignore if (this->PointersDownCount > 2) { return; } // store the initial positions if (event == vtkCommand::LeftButtonPressEvent) { for (int i = 0; i < VTKI_MAX_POINTERS; i++) { if (this->PointersDown[i]) { this->StartingEventPositions[i][0] = this->EventPositions[i][0]; this->StartingEventPositions[i][1] = this->EventPositions[i][1]; } } // we do not know what the gesture is yet this->CurrentGesture = vtkCommand::StartEvent; return; } // end the gesture if needed if (event == vtkCommand::LeftButtonReleaseEvent) { if (this->CurrentGesture == vtkCommand::PinchEvent) { this->EndPinchEvent(); } if (this->CurrentGesture == vtkCommand::RotateEvent) { this->EndRotateEvent(); } if (this->CurrentGesture == vtkCommand::PanEvent) { this->EndPanEvent(); } this->CurrentGesture = vtkCommand::StartEvent; return; } // what are the two pointers we are working with int count = 0; int *posVals[2]; int *startVals[2]; for (int i = 0; i < VTKI_MAX_POINTERS; i++) { if (this->PointersDown[i]) { posVals[count] = this->EventPositions[i]; startVals[count] = this->StartingEventPositions[i]; count++; } } // The meat of the algorithm // on move events we analyze them to determine what type // of movement it is and then deal with it. if (event == vtkCommand::MouseMoveEvent) { // calculate the distances double originalDistance = sqrt( static_cast( (startVals[0][0] - startVals[1][0])*(startVals[0][0] - startVals[1][0]) + (startVals[0][1] - startVals[1][1])*(startVals[0][1] - startVals[1][1]))); double newDistance = sqrt( static_cast( (posVals[0][0] - posVals[1][0])*(posVals[0][0] - posVals[1][0]) + (posVals[0][1] - posVals[1][1])*(posVals[0][1] - posVals[1][1]))); // calculate rotations double originalAngle = vtkMath::DegreesFromRadians( atan2((double)startVals[1][1] - startVals[0][1], (double)startVals[1][0] - startVals[0][0])); double newAngle = vtkMath::DegreesFromRadians( atan2( (double)posVals[1][1] - posVals[0][1], (double)posVals[1][0] - posVals[0][0])); // angles are cyclic so watch for that, 1 and 359 are only 2 apart :) double angleDeviation = newAngle - originalAngle; newAngle = (newAngle+180.0 >= 360.0 ? newAngle - 180.0 : newAngle + 180.0); originalAngle = (originalAngle+180.0 >= 360.0 ? originalAngle - 180.0 : originalAngle + 180.0); if (fabs(newAngle - originalAngle) < fabs(angleDeviation)) { angleDeviation = newAngle - originalAngle; } // calculate the translations double trans[2]; trans[0] = (posVals[0][0] - startVals[0][0] + posVals[1][0] - startVals[1][0])/2.0; trans[1] = (posVals[0][1] - startVals[0][1] + posVals[1][1] - startVals[1][1])/2.0; // OK we want to // - immediately respond to the user // - allow the user to zoom without panning (saves focal point) // - allow the user to rotate without panning (saves focal point) // do we know what gesture we are doing yet? If not // see if we can figure it out if (this->CurrentGesture == vtkCommand::StartEvent) { // pinch is a move to/from the center point // rotate is a move along the circumference // pan is a move of the center point // compute the distance along each of these axes in pixels // the first to break thresh wins double thresh = 0.01*sqrt( static_cast(this->Size[0]*this->Size[0] + this->Size[1]*this->Size[1])); if (thresh < 15.0) { thresh = 15.0; } double pinchDistance = fabs(newDistance - originalDistance); double rotateDistance = newDistance*3.1415926*fabs(angleDeviation)/360.0; double panDistance = sqrt(trans[0]*trans[0] + trans[1]*trans[1]); if (pinchDistance > thresh && pinchDistance > rotateDistance && pinchDistance > panDistance) { this->CurrentGesture = vtkCommand::PinchEvent; this->Scale = 1.0; this->StartPinchEvent(); } else if (rotateDistance > thresh && rotateDistance > panDistance) { this->CurrentGesture = vtkCommand::RotateEvent; this->Rotation = 0.0; this->StartRotateEvent(); } else if (panDistance > thresh) { this->CurrentGesture = vtkCommand::PanEvent; this->Translation[0] = 0.0; this->Translation[1] = 0.0; this->StartPanEvent(); } } // if we have found a specific type of movement then // handle it if (this->CurrentGesture == vtkCommand::RotateEvent) { this->SetRotation(angleDeviation); this->RotateEvent(); } if (this->CurrentGesture == vtkCommand::PinchEvent) { vtkErrorMacro("See pinch"); this->SetScale(newDistance/originalDistance); this->PinchEvent(); } if (this->CurrentGesture == vtkCommand::PanEvent) { this->SetTranslation(trans); this->PanEvent(); } } } // Timer methods. There are two basic groups of methods, those for backward // compatibility (group #1) and those that operate on specific timers (i.e., // use timer ids). The first group of methods implicitly assume that there is // only one timer at a time running. This was okay in the old days of VTK when // only the interactors used timers. However with the introduction of new 3D // widgets into VTK multiple timers often run simultaneously. // //old-style group #1 int vtkRenderWindowInteractor::CreateTimer(int timerType) { int platformTimerId, timerId; if ( timerType == VTKI_TIMER_FIRST ) { unsigned long duration = this->TimerDuration; timerId = vtkTimerId; //just use current id, assume we don't have multiple timers platformTimerId = this->InternalCreateTimer(timerId,RepeatingTimer,duration); if ( 0 == platformTimerId ) { return 0; } (*this->TimerMap)[timerId] = vtkTimerStruct(platformTimerId,RepeatingTimer,duration); return timerId; } else //VTKI_TIMER_UPDATE is just updating last created timer { return 1; //do nothing because repeating timer has been created } } //old-style group #1 //just destroy last one created int vtkRenderWindowInteractor::DestroyTimer() { int timerId = vtkTimerId; vtkTimerIdMapIterator iter = this->TimerMap->find(timerId); if ( iter != this->TimerMap->end() ) { this->InternalDestroyTimer((*iter).second.Id); this->TimerMap->erase(iter); return 1; } return 0; } //new-style group #2 returns timer id int vtkRenderWindowInteractor::CreateRepeatingTimer(unsigned long duration) { int timerId = ++vtkTimerId; int platformTimerId = this->InternalCreateTimer(timerId,RepeatingTimer,duration); if ( 0 == platformTimerId ) { return 0; } (*this->TimerMap)[timerId] = vtkTimerStruct(platformTimerId,RepeatingTimer,duration); return timerId; } //new-style group #2 returns timer id int vtkRenderWindowInteractor::CreateOneShotTimer(unsigned long duration) { int timerId = ++vtkTimerId; int platformTimerId = this->InternalCreateTimer(timerId,OneShotTimer,duration); if ( 0 == platformTimerId ) { return 0; } (*this->TimerMap)[timerId] = vtkTimerStruct(platformTimerId,OneShotTimer,duration); return timerId; } //new-style group #2 returns type (non-zero unless bad timerId) int vtkRenderWindowInteractor::IsOneShotTimer(int timerId) { vtkTimerIdMapIterator iter = this->TimerMap->find(timerId); if ( iter != this->TimerMap->end() ) { return ((*iter).second.Type == OneShotTimer); } return 0; } //new-style group #2 returns duration (non-zero unless bad timerId) unsigned long vtkRenderWindowInteractor::GetTimerDuration(int timerId) { vtkTimerIdMapIterator iter = this->TimerMap->find(timerId); if ( iter != this->TimerMap->end() ) { return (*iter).second.Duration; } return 0; } //new-style group #2 returns non-zero if timer reset int vtkRenderWindowInteractor::ResetTimer(int timerId) { vtkTimerIdMapIterator iter = this->TimerMap->find(timerId); if ( iter != this->TimerMap->end() ) { this->InternalDestroyTimer((*iter).second.Id); int platformTimerId = this->InternalCreateTimer(timerId, (*iter).second.Type, (*iter).second.Duration); if ( platformTimerId != 0 ) { (*iter).second.Id = platformTimerId; return 1; } else { this->TimerMap->erase(iter); } } return 0; } //new-style group #2 returns non-zero if timer destroyed int vtkRenderWindowInteractor::DestroyTimer(int timerId) { vtkTimerIdMapIterator iter = this->TimerMap->find(timerId); if ( iter != this->TimerMap->end() ) { this->InternalDestroyTimer((*iter).second.Id); this->TimerMap->erase(iter); return 1; } return 0; } // Stubbed out dummys int vtkRenderWindowInteractor::InternalCreateTimer(int vtkNotUsed(timerId), int vtkNotUsed(timerType), unsigned long vtkNotUsed(duration)) { return 0; } int vtkRenderWindowInteractor::InternalDestroyTimer(int vtkNotUsed(platformTimerId)) { return 0; } // Translate from platformTimerId to the corresponding (VTK) timerId. // Returns 0 (invalid VTK timerId) if platformTimerId is not found in the map. // This first stab at an implementation just iterates the map until it finds // the sought platformTimerId. If performance becomes an issue (lots of timers, // all firing frequently...) we could speed this up by making a reverse map so // this method is a quick map lookup. int vtkRenderWindowInteractor::GetVTKTimerId(int platformTimerId) { int timerId = 0; vtkTimerIdMapIterator iter = this->TimerMap->begin(); for ( ; iter != this->TimerMap->end(); ++iter ) { if ((*iter).second.Id == platformTimerId) { timerId = (*iter).first; break; } } return timerId; } // Access to the static variable int vtkRenderWindowInteractor::GetCurrentTimerId() { return vtkTimerId; } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "InteractorStyle: " << this->InteractorStyle << "\n"; os << indent << "RenderWindow: " << this->RenderWindow << "\n"; if ( this->Picker ) { os << indent << "Picker: " << this->Picker << "\n"; } else { os << indent << "Picker: (none)\n"; } if ( this->ObserverMediator ) { os << indent << "Observer Mediator: " << this->ObserverMediator << "\n"; } else { os << indent << "Observer Mediator: (none)\n"; } os << indent << "LightFollowCamera: " << (this->LightFollowCamera ? "On\n" : "Off\n"); os << indent << "DesiredUpdateRate: " << this->DesiredUpdateRate << "\n"; os << indent << "StillUpdateRate: " << this->StillUpdateRate << "\n"; os << indent << "Initialized: " << this->Initialized << "\n"; os << indent << "Enabled: " << this->Enabled << "\n"; os << indent << "EnableRender: " << this->EnableRender << "\n"; os << indent << "EventPosition: " << "( " << this->EventPosition[0] << ", " << this->EventPosition[1] << " )\n"; os << indent << "LastEventPosition: " << "( " << this->LastEventPosition[0] << ", " << this->LastEventPosition[1] << " )\n"; os << indent << "EventSize: " << "( " << this->EventSize[0] << ", " << this->EventSize[1] << " )\n"; os << indent << "Viewport Size: " << "( " << this->Size[0] << ", " << this->Size[1] << " )\n"; os << indent << "Number of Fly Frames: " << this->NumberOfFlyFrames <<"\n"; os << indent << "Dolly: " << this->Dolly <<"\n"; os << indent << "ControlKey: " << this->ControlKey << "\n"; os << indent << "AltKey: " << this->AltKey << "\n"; os << indent << "ShiftKey: " << this->ShiftKey << "\n"; os << indent << "KeyCode: " << this->KeyCode << "\n"; os << indent << "KeySym: " << (this->KeySym ? this->KeySym : "(null)") << "\n"; os << indent << "RepeatCount: " << this->RepeatCount << "\n"; os << indent << "Timer Duration: " << this->TimerDuration << "\n"; os << indent << "TimerEventId: " << this->TimerEventId << "\n"; os << indent << "TimerEventType: " << this->TimerEventType << "\n"; os << indent << "TimerEventDuration: " << this->TimerEventDuration << "\n"; os << indent << "TimerEventPlatformId: " << this->TimerEventPlatformId << "\n"; os << indent << "UseTDx: " << this->UseTDx << endl; os << indent << "Recognize Gestures: " << this->RecognizeGestures << endl; } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::Initialize() { this->Initialized=1; this->Enable(); this->Render(); } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::HideCursor() { this->RenderWindow->HideCursor(); } //---------------------------------------------------------------------------- void vtkRenderWindowInteractor::ShowCursor() { this->RenderWindow->ShowCursor(); } //---------------------------------------------------------------------------- vtkObserverMediator *vtkRenderWindowInteractor::GetObserverMediator() { if ( !this->ObserverMediator ) { this->ObserverMediator = vtkObserverMediator::New(); this->ObserverMediator->SetInteractor(this); } return this->ObserverMediator; } //------------------------------------------------------------------ void vtkRenderWindowInteractor::MouseMoveEvent() { if (!this->Enabled) { return; } // handle gestures or not? if (this->RecognizeGestures && this->PointersDownCount > 1) { // handle the gesture this->RecognizeGesture(vtkCommand::MouseMoveEvent); } else { this->InvokeEvent(vtkCommand::MouseMoveEvent, nullptr); } } //------------------------------------------------------------------ void vtkRenderWindowInteractor::RightButtonPressEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::RightButtonPressEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::RightButtonReleaseEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::RightButtonReleaseEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::LeftButtonPressEvent() { if (!this->Enabled) { return; } // are we translating multitouch into gestures? if (this->RecognizeGestures) { if (!this->PointersDown[this->PointerIndex]) { this->PointersDown[this->PointerIndex] = 1; this->PointersDownCount++; } // do we have multitouch if (this->PointersDownCount > 1) { // did we just transition to multitouch? if (this->PointersDownCount == 2) { this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, nullptr); } // handle the gesture this->RecognizeGesture(vtkCommand::LeftButtonPressEvent); return; } } this->InvokeEvent(vtkCommand::LeftButtonPressEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::LeftButtonReleaseEvent() { if (!this->Enabled) { return; } if (this->RecognizeGestures) { if (this->PointersDown[this->PointerIndex]) { this->PointersDown[this->PointerIndex] = 0; this->PointersDownCount--; } // do we have multitouch if (this->PointersDownCount > 1) { // handle the gesture this->RecognizeGesture(vtkCommand::LeftButtonReleaseEvent); return; } } this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::MiddleButtonPressEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::MiddleButtonPressEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::MiddleButtonReleaseEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::MouseWheelForwardEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::MouseWheelForwardEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::MouseWheelBackwardEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::ExposeEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::ExposeEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::ConfigureEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::ConfigureEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::EnterEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::EnterEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::LeaveEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::LeaveEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::KeyPressEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::KeyPressEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::KeyReleaseEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::KeyReleaseEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::CharEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::CharEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::ExitEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::ExitEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::FourthButtonPressEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::FourthButtonPressEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::FourthButtonReleaseEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::FourthButtonReleaseEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::FifthButtonPressEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::FifthButtonPressEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::FifthButtonReleaseEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::FifthButtonReleaseEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::StartPinchEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::StartPinchEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::PinchEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::PinchEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::EndPinchEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::EndPinchEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::StartRotateEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::StartRotateEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::RotateEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::RotateEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::EndRotateEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::EndRotateEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::StartPanEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::StartPanEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::PanEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::PanEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::EndPanEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::EndPanEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::TapEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::TapEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::LongTapEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::LongTapEvent, nullptr); } //------------------------------------------------------------------ void vtkRenderWindowInteractor::SwipeEvent() { if (!this->Enabled) { return; } this->InvokeEvent(vtkCommand::SwipeEvent, nullptr); }