Commit 70e09ef6 authored by Marcus D. Hanwell's avatar Marcus D. Hanwell

ENH: Fixes to interaction/render window issues with views.

Moving most of the interactor mode related code to vtkRenderView. Fixed
vtkRenderViewBase so that it does the minimal amount of work to preserve
the interactor style.
parent 09b485f5
......@@ -24,6 +24,7 @@
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyle.h"
#include "vtkContextActor.h"
#include "vtkInteractorStyleRubberBand2D.h"
#include "vtkObjectFactory.h"
......@@ -46,9 +47,11 @@ vtkContextView::vtkContextView()
this->Scene = actor->GetScene(); // We keep a pointer to this for convenience
// Should not need to do this...
this->Scene->SetRenderer(this->Renderer);
this->Scene->SetInteractorStyle(
vtkInteractorStyle::SafeDownCast(this->RenderWindow->GetInteractor()
->GetInteractorStyle()));
vtkInteractorStyleRubberBand2D* style = vtkInteractorStyleRubberBand2D::New();
this->GetInteractor()->SetInteractorStyle(style);
this->Scene->SetInteractorStyle(style);
style->Delete();
// Single color background by default.
this->Renderer->SetBackground(1.0, 1.0, 1.0);
......
......@@ -67,6 +67,8 @@ vtkCxxSetObjectMacro(vtkRenderView, IconTexture, vtkTexture);
vtkRenderView::vtkRenderView()
{
this->RenderOnMouseMove = false;
this->InteractionMode = -1;
this->LabelRenderer = vtkSmartPointer<vtkRenderer>::New();
this->Transform = vtkTransform::New();
this->DisplayHoverText = false;
......@@ -101,13 +103,14 @@ vtkRenderView::vtkRenderView()
this->Selector->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_CELLS);
this->RenderWindow->AddObserver(vtkCommand::EndEvent, this->GetObserver());
vtkRenderWindowInteractor* iren = this->RenderWindow->GetInteractor();
// this ensure that the observer is added to the interactor correctly.
this->SetInteractor(iren);
// The interaction mode is -1 before calling SetInteractionMode,
// this will force an initialization of the interaction mode/style.
this->SetInteractionModeTo3D();
vtkRenderWindowInteractor* iren = this->RenderWindow->GetInteractor();
this->HoverWidget->SetInteractor(iren);
this->HoverWidget->AddObserver(vtkCommand::TimerEvent, this->GetObserver());
this->LabelActor->SetMapper(this->LabelPlacementMapper);
......@@ -148,8 +151,18 @@ void vtkRenderView::SetInteractor(vtkRenderWindowInteractor* interactor)
return;
}
this->vtkRenderViewBase::SetInteractor(interactor);
if (this->GetInteractor())
{
this->GetInteractor()->RemoveObserver(this->GetObserver());
}
this->Superclass::SetInteractor(interactor);
this->HoverWidget->SetInteractor(interactor);
interactor->EnableRenderOff();
interactor->AddObserver(vtkCommand::RenderEvent, this->GetObserver());
interactor->AddObserver(vtkCommand::StartInteractionEvent, this->GetObserver());
interactor->AddObserver(vtkCommand::EndInteractionEvent, this->GetObserver());
}
void vtkRenderView::SetInteractorStyle(vtkInteractorObserver* style)
......@@ -190,6 +203,95 @@ void vtkRenderView::SetInteractorStyle(vtkInteractorObserver* style)
}
}
vtkInteractorObserver* vtkRenderView::GetInteractorStyle()
{
if (this->GetInteractor())
{
return this->GetInteractor()->GetInteractorStyle();
}
return NULL;
}
void vtkRenderView::SetRenderOnMouseMove(bool b)
{
if (b == this->RenderOnMouseMove)
{
return;
}
vtkInteractorObserver* style = this->GetInteractor()->GetInteractorStyle();
vtkInteractorStyleRubberBand2D* style2D =
vtkInteractorStyleRubberBand2D::SafeDownCast(style);
if (style2D)
{
style2D->SetRenderOnMouseMove(b);
}
vtkInteractorStyleRubberBand3D* style3D =
vtkInteractorStyleRubberBand3D::SafeDownCast(style);
if (style3D)
{
style3D->SetRenderOnMouseMove(b);
}
this->RenderOnMouseMove = b;
}
void vtkRenderView::SetInteractionMode(int mode)
{
if (this->InteractionMode != mode)
{
this->InteractionMode = mode;
vtkInteractorObserver* oldStyle = this->GetInteractor()->GetInteractorStyle();
if (mode == INTERACTION_MODE_2D)
{
if (oldStyle)
{
oldStyle->RemoveObserver(this->GetObserver());
}
vtkInteractorStyleRubberBand2D* style = vtkInteractorStyleRubberBand2D::New();
this->GetInteractor()->SetInteractorStyle(style);
style->SetRenderOnMouseMove(this->GetRenderOnMouseMove());
style->AddObserver(vtkCommand::SelectionChangedEvent, this->GetObserver());
this->Renderer->GetActiveCamera()->ParallelProjectionOn();
style->Delete();
}
else if (mode == INTERACTION_MODE_3D)
{
if (oldStyle)
{
oldStyle->RemoveObserver(this->GetObserver());
}
vtkInteractorStyleRubberBand3D* style = vtkInteractorStyleRubberBand3D::New();
this->GetInteractor()->SetInteractorStyle(style);
style->SetRenderOnMouseMove(this->GetRenderOnMouseMove());
style->AddObserver(vtkCommand::SelectionChangedEvent, this->GetObserver());
this->Renderer->GetActiveCamera()->ParallelProjectionOff();
style->Delete();
}
else
{
vtkErrorMacro("Unknown interaction mode.");
}
}
}
void vtkRenderView::SetRenderWindow(vtkRenderWindow* win)
{
vtkSmartPointer<vtkRenderWindowInteractor> irenOld = this->GetInteractor();
this->Superclass::SetRenderWindow(win);
vtkRenderWindowInteractor* irenNew = this->GetInteractor();
if (irenOld != irenNew)
{
if (irenOld)
{
irenOld->RemoveObserver(this->GetObserver());
}
if (irenNew)
{
this->SetInteractor(irenNew);
}
}
}
void vtkRenderView::Render()
{
// Indirectly call this->RenderWindow->Start() without crashing.
......@@ -653,4 +755,6 @@ void vtkRenderView::PrintSelf(ostream& os, vtkIndent indent)
}
os << indent << "IconSize: " << this->IconSize[0] << "," << this->IconSize[1] << endl;
os << indent << "DisplaySize: " << this->DisplaySize[0] << "," << this->DisplaySize[1] << endl;
os << indent << "InteractionMode: " << this->InteractionMode << endl;
os << indent << "RenderOnMouseMove: " << this->RenderOnMouseMove << endl;
}
......@@ -68,6 +68,27 @@ public:
// The interactor style associated with the render view.
virtual void SetInteractorStyle(vtkInteractorObserver* style);
// Description:
// Get the interactor style associated with the render view.
virtual vtkInteractorObserver* GetInteractorStyle();
// Description:
// Set the render window for this view. Note that this requires special
// handling in order to do correctly - see the notes in the detailed
// description of vtkRenderViewBase.
virtual void SetRenderWindow(vtkRenderWindow *win);
//BTX
enum
{
INTERACTION_MODE_2D,
INTERACTION_MODE_3D,
INTERACTION_MODE_UNKNOWN
};
//ETX
void SetInteractionMode(int mode);
vtkGetMacro(InteractionMode, int);
// Description:
// Set the interaction mode for the view. Choices are:
// vtkRenderView::INTERACTION_MODE_2D - 2D interactor
......@@ -183,6 +204,11 @@ public:
virtual void SetLabelRenderModeToQt()
{ this->SetLabelRenderMode(QT); }
// Description:
// Whether to render on every mouse move.
void SetRenderOnMouseMove(bool b);
vtkGetMacro(RenderOnMouseMove, bool);
vtkBooleanMacro(RenderOnMouseMove, bool);
protected:
vtkRenderView();
~vtkRenderView();
......@@ -230,6 +256,9 @@ protected:
int IconSize[2];
int DisplaySize[2];
int InteractionMode;
bool RenderOnMouseMove;
//BTX
vtkSmartPointer<vtkRenderer> LabelRenderer;
vtkSmartPointer<vtkBalloonRepresentation> Balloon;
......
......@@ -16,22 +16,18 @@
#include "vtkRenderViewBase.h"
#include "vtkCamera.h"
#include "vtkCommand.h"
#include "vtkInteractorStyleRubberBand2D.h"
#include "vtkInteractorStyleRubberBand3D.h"
#include "vtkGenericRenderWindowInteractor.h"
#include "vtkInteractorObserver.h"
#include "vtkObjectFactory.h"
#include "vtkRendererCollection.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRendererCollection.h"
#include "vtkDataRepresentation.h"
vtkStandardNewMacro(vtkRenderViewBase);
vtkRenderViewBase::vtkRenderViewBase()
{
this->RenderOnMouseMove = false;
this->InteractionMode = -1;
this->Renderer = vtkSmartPointer<vtkRenderer>::New();
this->RenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
this->RenderWindow->AddRenderer(this->Renderer);
......@@ -40,12 +36,7 @@ vtkRenderViewBase::vtkRenderViewBase()
// in the interactor and listening to the interactor's render event.
vtkSmartPointer<vtkRenderWindowInteractor> iren =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->EnableRenderOff();
iren->AddObserver(vtkCommand::RenderEvent, this->GetObserver());
iren->AddObserver(vtkCommand::StartInteractionEvent, this->GetObserver());
iren->AddObserver(vtkCommand::EndInteractionEvent, this->GetObserver());
this->RenderWindow->SetInteractor(iren);
this->SetInteractionMode(INTERACTION_MODE_2D);
this->SetInteractor(iren);
}
vtkRenderViewBase::~vtkRenderViewBase()
......@@ -71,12 +62,6 @@ void vtkRenderViewBase::SetRenderWindow(vtkRenderWindow* win)
return;
}
// get rid of the render observer on the current window
if (this->RenderWindow)
{
this->RenderWindow->RemoveObserver(this->GetObserver());
}
// move renderers to new window
vtkRendererCollection* rens = this->RenderWindow->GetRenderers();
while(rens->GetNumberOfItems())
......@@ -87,18 +72,21 @@ void vtkRenderViewBase::SetRenderWindow(vtkRenderWindow* win)
this->RenderWindow->RemoveRenderer(ren);
}
// move interactor to new window
vtkSmartPointer<vtkRenderWindowInteractor> iren =
this->RenderWindow->GetInteractor();
this->RenderWindow->SetInteractor(NULL);
iren->SetRenderWindow(NULL);
win->SetInteractor(iren);
iren->SetRenderWindow(win);
this->RenderWindow->UnRegister(this);
vtkSmartPointer<vtkInteractorObserver> style = this->GetInteractor()?
this->GetInteractor()->GetInteractorStyle() : NULL;
this->RenderWindow = win;
this->RenderWindow->Register(this);
this->RenderWindow->AddObserver(vtkCommand::EndEvent, this->GetObserver());
if (this->GetInteractor())
{
this->GetInteractor()->SetInteractorStyle(style);
}
else if (style)
{
vtkGenericRenderWindowInteractor* iren =
vtkGenericRenderWindowInteractor::New();
win->SetInteractor(iren);
iren->SetInteractorStyle(style);
iren->Delete();
}
}
vtkRenderWindowInteractor* vtkRenderViewBase::GetInteractor()
......@@ -108,100 +96,23 @@ vtkRenderWindowInteractor* vtkRenderViewBase::GetInteractor()
void vtkRenderViewBase::SetInteractor(vtkRenderWindowInteractor* interactor)
{
if (!interactor)
if (interactor == this->GetInteractor())
{
vtkErrorMacro(<< "SetInteractor called with a null interactor pointer."
<< " That can't be right.");
return;
}
// get rid of the render observer on any current interactor
if (this->RenderWindow->GetInteractor())
{
this->RenderWindow->GetInteractor()->RemoveObserver(this->GetObserver());
}
// We need to preserve the interactor style currently present on the
// interactor.
vtkInteractorObserver *oldStyle = this->GetInteractorStyle();
oldStyle->Register(this);
// We will handle all interactor renders by turning off rendering
// in the interactor and listening to the interactor's render event.
interactor->EnableRenderOff();
interactor->AddObserver(vtkCommand::RenderEvent, this->GetObserver());
interactor->AddObserver(vtkCommand::StartInteractionEvent, this->GetObserver());
interactor->AddObserver(vtkCommand::EndInteractionEvent, this->GetObserver());
vtkSmartPointer<vtkInteractorObserver> style = this->GetInteractor() ?
this->GetInteractor()->GetInteractorStyle() : NULL;
this->RenderWindow->SetInteractor(interactor);
interactor->SetInteractorStyle(oldStyle);
oldStyle->UnRegister(this);
}
vtkInteractorObserver* vtkRenderViewBase::GetInteractorStyle()
{
return this->GetInteractor()->GetInteractorStyle();
}
void vtkRenderViewBase::SetInteractionMode(int mode)
{
if (this->InteractionMode != mode)
if (this->GetInteractor())
{
this->InteractionMode = mode;
vtkInteractorObserver* oldStyle = this->GetInteractor()->GetInteractorStyle();
if (mode == INTERACTION_MODE_2D)
{
if (oldStyle)
{
oldStyle->RemoveObserver(this->GetObserver());
}
vtkInteractorStyleRubberBand2D* style = vtkInteractorStyleRubberBand2D::New();
this->RenderWindow->GetInteractor()->SetInteractorStyle(style);
style->SetRenderOnMouseMove(this->GetRenderOnMouseMove());
style->AddObserver(vtkCommand::SelectionChangedEvent, this->GetObserver());
this->Renderer->GetActiveCamera()->ParallelProjectionOn();
style->Delete();
}
else if (mode == INTERACTION_MODE_3D)
{
if (oldStyle)
{
oldStyle->RemoveObserver(this->GetObserver());
}
vtkInteractorStyleRubberBand3D* style = vtkInteractorStyleRubberBand3D::New();
this->RenderWindow->GetInteractor()->SetInteractorStyle(style);
style->SetRenderOnMouseMove(this->GetRenderOnMouseMove());
style->AddObserver(vtkCommand::SelectionChangedEvent, this->GetObserver());
this->Renderer->GetActiveCamera()->ParallelProjectionOff();
style->Delete();
}
else
{
vtkErrorMacro("Unknown interaction mode.");
}
this->GetInteractor()->SetInteractorStyle(style);
}
}
void vtkRenderViewBase::SetRenderOnMouseMove(bool b)
{
if (b == this->RenderOnMouseMove)
else if (style)
{
return;
vtkWarningMacro("RenderWindow has no interactor, so the style will be lost.");
}
vtkInteractorObserver* style = this->GetInteractor()->GetInteractorStyle();
vtkInteractorStyleRubberBand2D* style2D =
vtkInteractorStyleRubberBand2D::SafeDownCast(style);
if (style2D)
{
style2D->SetRenderOnMouseMove(b);
}
vtkInteractorStyleRubberBand3D* style3D =
vtkInteractorStyleRubberBand3D::SafeDownCast(style);
if (style3D)
{
style3D->SetRenderOnMouseMove(b);
}
this->RenderOnMouseMove = b;
}
void vtkRenderViewBase::Render()
......@@ -227,32 +138,6 @@ void vtkRenderViewBase::PrepareForRendering()
this->Update();
}
void vtkRenderViewBase::ProcessEvents(
vtkObject* caller, unsigned long eventId, void* callData)
{
if (caller == this->GetInteractor() && eventId == vtkCommand::RenderEvent)
{
vtkDebugMacro(<< "interactor causing a render event.");
this->Render();
}
if (vtkDataRepresentation::SafeDownCast(caller) &&
eventId == vtkCommand::SelectionChangedEvent)
{
vtkDebugMacro("selection changed causing a render event");
this->Render();
}
else if (vtkDataRepresentation::SafeDownCast(caller) &&
eventId == vtkCommand::UpdateEvent)
{
// UpdateEvent is called from push pipeline executions from
// vtkExecutionScheduler. We want to automatically render the view
// when one of our representations is updated.
vtkDebugMacro("push pipeline causing a render event");
this->Render();
}
this->Superclass::ProcessEvents(caller, eventId, callData);
}
void vtkRenderViewBase::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
......@@ -276,6 +161,4 @@ void vtkRenderViewBase::PrintSelf(ostream& os, vtkIndent indent)
{
os << "(none)\n";
}
os << indent << "InteractionMode: " << this->InteractionMode << endl;
os << indent << "RenderOnMouseMove: " << this->RenderOnMouseMove << endl;
}
......@@ -68,22 +68,7 @@ public:
// handling in order to do correctly - see the notes in the detailed
// description of vtkRenderViewBase.
virtual vtkRenderWindowInteractor* GetInteractor();
virtual void SetInteractor(vtkRenderWindowInteractor *interactor);
// Description:
// Get the interactor style associated with the render view.
virtual vtkInteractorObserver* GetInteractorStyle();
//BTX
enum
{
INTERACTION_MODE_2D,
INTERACTION_MODE_3D,
INTERACTION_MODE_UNKNOWN
};
//ETX
void SetInteractionMode(int mode);
vtkGetMacro(InteractionMode, int);
virtual void SetInteractor(vtkRenderWindowInteractor*);
// Description:
// Updates the representations, then calls Render() on the render window
......@@ -100,31 +85,16 @@ public:
// renderer associated with this view.
virtual void ResetCameraClippingRange();
// Description:
// Whether to render on every mouse move.
void SetRenderOnMouseMove(bool b);
vtkGetMacro(RenderOnMouseMove, bool);
vtkBooleanMacro(RenderOnMouseMove, bool);
protected:
vtkRenderViewBase();
~vtkRenderViewBase();
// Description:
// Called to process events.
// Captures StartEvent events from the renderer and calls Update().
// This may be overridden by subclasses to process additional events.
virtual void ProcessEvents(vtkObject* caller, unsigned long eventId,
void* callData);
// Description:
// Called by the view when the renderer is about to render.
virtual void PrepareForRendering();
vtkSmartPointer<vtkRenderer> Renderer;
vtkSmartPointer<vtkRenderWindow> RenderWindow;
int InteractionMode;
bool RenderOnMouseMove;
private:
vtkRenderViewBase(const vtkRenderViewBase&); // Not implemented.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment