jspanchu/vtkGlfw

Can't handle button callback function.

Opened this issue · 1 comments

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkButtonWidget.h>
#include <vtkPNGReader.h>
#include <vtkTexturedButtonRepresentation2D.h>
#include <vtkCoordinate.h>
#include "../vtkGlfw/vtkGlfwOpenGLRenderWindow.h"
#include "../vtkGlfw/vtkGlfwRenderWindowInteractor.h"

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

enum ButtonType { E_Button0, E_Button1, E_ButtonCount };

vtkSPtr<vtkButtonWidget> m_Button[E_ButtonCount];
//vtkSPtr<vtkRenderWindowInteractor> m_RenderWindowInteractor;
vtkSPtr<vtkGlfwRenderWindowInteractor> m_RenderWindowInteractor;
vtkSPtr<vtkRenderer> m_Renderer;

ButtonType GetButtonType(const vtkButtonWidget *const buttonWidget)
{
	ButtonType result = E_ButtonCount;
	for (int i = 0; i < E_ButtonCount; ++i)
	{
		if (buttonWidget == m_Button[i])
		{
			result = (ButtonType)i;
			break;
		}
	}
	return result;
}

class ButtonCallBack : public vtkCommand
{
public:
	static ButtonCallBack *New() { return new ButtonCallBack(); }
	virtual void Execute(vtkObject *caller, unsigned long eventId, void *callData)
	{
		vtkButtonWidget* buttonWidget = reinterpret_cast<vtkButtonWidget*>(caller);
		vtkTexturedButtonRepresentation2D* rep = reinterpret_cast<vtkTexturedButtonRepresentation2D*>(buttonWidget->GetRepresentation());
		int state = rep->GetState();
		ButtonType buttonT = GetButtonType(buttonWidget);
		cout << "state: " << state << ", buttonT: " << buttonT << endl;
		// add your costum click function for different button.
	}
};

void InitButton(const ButtonType buttonType, const std::string& beforeImagePath, const std::string& afterImagePath)
{
	vtkSPtrNew(pngReader, vtkPNGReader);
	pngReader->SetFileName(beforeImagePath.c_str());
	pngReader->Update();

	vtkSPtrNew(pngReader1, vtkPNGReader);
	pngReader1->SetFileName(afterImagePath.c_str());
	pngReader1->Update();

	vtkSPtrNew(buttonRep, vtkTexturedButtonRepresentation2D);
	if (beforeImagePath != afterImagePath)
	{
		buttonRep->SetNumberOfStates(2);
		buttonRep->SetButtonTexture(0, pngReader->GetOutput());
		buttonRep->SetButtonTexture(1, pngReader1->GetOutput());
	}
	else
	{
		buttonRep->SetNumberOfStates(1);
		buttonRep->SetButtonTexture(0, pngReader->GetOutput());
	}

	m_Button[buttonType]->SetInteractor(m_RenderWindowInteractor);
	m_Button[buttonType]->SetRepresentation(buttonRep);

	buttonRep->SetPlaceFactor(1);
	m_Button[buttonType]->On();

	vtkSPtrNew(buttonCB, ButtonCallBack);
	m_Button[buttonType]->AddObserver(vtkCommand::StateChangedEvent, buttonCB);
}

void UpdateButtonsPosition()
{
	vtkWidgetRepresentation* buttonRep = m_Button[E_Button0]->GetRepresentation();

	vtkSPtrNew(coordinate, vtkCoordinate);
	coordinate->SetCoordinateSystemToNormalizedDisplay();
	coordinate->SetValue(1.0, 0.8);
	double bds[6];
	double sz = 50;
	bds[0] = coordinate->GetComputedDisplayValue(m_Renderer)[0] - sz;
	bds[1] = bds[0] + sz;
	bds[2] = coordinate->GetComputedDisplayValue(m_Renderer)[1] - sz;
	bds[3] = bds[2] + sz;
	bds[4] = bds[5] = 0;
	buttonRep->PlaceWidget(bds);

	// ================== Put the second button ==================
	double tmpBds[6] = { bds[0], bds[1], bds[2], bds[3], bds[4], bds[5] };
	buttonRep = m_Button[E_Button1]->GetRepresentation();
	bds[0] = tmpBds[0];
	bds[1] = bds[0] + sz;
	bds[2] = tmpBds[2] - sz - 5;
	bds[3] = bds[2] + sz;
	bds[4] = bds[5] = 0;
	buttonRep->PlaceWidget(bds);
}

int main()
{
	vtkSPtrNew(cone, vtkConeSource);
	vtkSPtrNew(mapper, vtkPolyDataMapper);
	mapper->SetInputConnection(cone->GetOutputPort());

	vtkSPtrNew(actor, vtkActor);
	actor->SetMapper(mapper);

	m_Renderer = vtkSPtr<vtkRenderer>::New();
	m_Renderer->AddActor(actor);
	m_Renderer->SetBackground(0, 0, 0);

	//vtkSPtrNew(renderWindow, vtkRenderWindow);
	vtkNew<vtkGlfwOpenGLRenderWindow> renderWindow;
	renderWindow->SetSize(300, 300);

	renderWindow->AddRenderer(m_Renderer);

	renderWindow->SetWindowName("Cylinder");
	renderWindow->SetMultiSamples(8);

	m_RenderWindowInteractor = vtkSPtr<vtkGlfwRenderWindowInteractor>::New();
	m_RenderWindowInteractor->SetRenderWindow(renderWindow);

	for (int i = 0; i < 2; ++i)
	{
		m_Button[i] = vtkSmartPointer<vtkButtonWidget>::New();
	}
	std::string path0 = "F:/bullet3-3.17/Extras/sphereOctree.png";
	std::string path1 = "F:/bullet3-3.17/Extras/LA_closed.png";
	InitButton(E_Button0, path0, path1);
	InitButton(E_Button1, path1, path0);

	m_Renderer->ResetCamera();
	renderWindow->Render();

	UpdateButtonsPosition();

	m_RenderWindowInteractor->Start();
	return 0;
}

Hi,
I use vtkButtonWidget to Create 2D button. The vtkWidgetRepresentation object controls the button’s position and show button pictures. Write class ButtonCallBack that inherits vtkCommand and use it to listen for vtkCommand::StateChangedEvent, then I can add our button click function in it.

It worked fine in native vtk, but crashed in vtkGlfwOpenGLRenderWindow.

Many thanks in advance.
Video_20211213152253