Update VTK widget state on viewport change

21 Views Asked by At

Below, I’ve provided a minimal running example for a problem I encounter frequently in my projects. To reproduce, do the following:

  1. Place the mouse over the border of one of the border widgets.
  2. Press “t” to toggle the viewports of the two renderers.
  3. Press the left mouse button and drag the border of the border widget.
  4. Observe that the border widget being changed is the one that was “selected” before the “t” was pressed, not the one in the current renderer.

The problem occurs, because the widget is in an interactable state when the “t” is pressed. This state is only updated when the mouse is moved. In this example, the mouse is not moved, but the content below the mouse pointer is changed, so the widget state is outdated. I encounter this kind of problem in similar ways for slightly other use cases. What is the preferred way to deal with this problem?

#include <vtkObjectFactory.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleUser.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkBorderWidget.h>

static double constexpr viewportTop[ 4 ]{ 0., .5, 1., 1. };
static double constexpr viewportBottom[ 4 ]{ 0., 0., 1., .5 };

class InteractorStyle : public vtkInteractorStyleUser
{
public:
  static InteractorStyle * New();
  vtkTypeMacro( InteractorStyle, vtkInteractorStyleUser );

  void setEnvironment( vtkRenderer * renderer1, vtkRenderer * renderer2 )
  {
    m_renderer1 = renderer1;
    m_renderer2 = renderer2;
  }

  void OnChar() override
  {
    if( 't' == Interactor->GetKeyCode() )
    {
      m_toggled = !m_toggled;
      m_renderer1->SetViewport( m_toggled ? viewportBottom : viewportTop );
      m_renderer2->SetViewport( m_toggled ? viewportTop : viewportBottom );
      Interactor->Render();
    }
    else InteractorStyle::OnChar();
  }

private:
  vtkRenderer * m_renderer1{};
  vtkRenderer * m_renderer2{};
  bool m_toggled{ false };
};

vtkStandardNewMacro( InteractorStyle );

int main( int, char * [] )
{
  vtkNew< vtkRenderWindow > renderWindow;

  vtkNew< InteractorStyle > interactorStyle;
  vtkNew< vtkRenderWindowInteractor > renderWindowInteractor;
  renderWindowInteractor->SetInteractorStyle( interactorStyle );
  renderWindowInteractor->SetRenderWindow( renderWindow );

  vtkNew< vtkRenderer > renderer1;
  vtkNew< vtkRenderer > renderer2;
  renderer1->SetBackground( 0.3, 0.3, 0.3 );
  renderer2->SetBackground( .5, .5, .5 );
  renderer1->SetViewport( viewportTop );
  renderer2->SetViewport( viewportBottom );
  renderWindow->AddRenderer( renderer1 );
  renderWindow->AddRenderer( renderer2 );

  vtkNew< vtkBorderWidget > borderWidget1;
  vtkNew< vtkBorderWidget > borderWidget2;
  borderWidget1->SetInteractor( renderWindowInteractor );
  borderWidget2->SetInteractor( renderWindowInteractor );
  borderWidget1->CreateDefaultRepresentation();
  borderWidget2->CreateDefaultRepresentation();
  borderWidget1->SetDefaultRenderer( renderer1 );
  borderWidget2->SetDefaultRenderer( renderer2 );
  borderWidget1->SetEnabled( true );
  borderWidget2->SetEnabled( true );

  interactorStyle->setEnvironment( renderer1, renderer2 );

  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}
0

There are 0 best solutions below