vtkAbstractWidget this->CallbackMapper->SetCallbackMethod Exception

#include <vtkActor.h>
#include <vtkAxesActor.h>
#include <vtkCamera.h>
#include <vtkCommand.h>
#include <vtkConeSource.h>
#include <vtkCubeAxesActor.h>
#include <vtkCubeSource.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkOrientationMarkerWidget.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>

#include “modernTransformRepresentation.hpp”
#include “transformWidget.hpp”

// This does the actual work.
// Callback for the interaction
class transformCallback : public vtkCommand
{
public:
static transformCallback *New()
{
return new transformCallback;
}

virtual void Execute(vtkObject *caller, unsigned long, void *)
{
    vtkSmartPointer<transformWidget> widget =
        dynamic_cast<transformWidget *>(caller);

    if (widget != nullptr && actor_ != nullptr)
    {
        if (auto rep = dynamic_cast<transformRepresentation *>(
                widget->GetRepresentation()))
        {
            vtkNew<vtkTransform> trans;
            rep->GetTransform(trans);

            vtkNew<vtkMatrix4x4> newMatrix;
            newMatrix->DeepCopy(trans->GetMatrix());

            actor_->SetUserMatrix(newMatrix);
        }
    }
}

void setActor(vtkSmartPointer<vtkActor> actor)
{
    actor_ = actor;
};

transformCallback() : actor_(nullptr)
{
}

private:
vtkSmartPointer actor_;
};

int main(int, char *)
{
vtkNew camera;
camera->SetParallelProjection(true);

vtkNew<vtkNamedColors> colors;

// A mainRenderer and render window
vtkNew<vtkRenderer> mainRenderer;
mainRenderer->SetBackground(colors->GetColor3d("BurlyWood").GetData());
mainRenderer->SetActiveCamera(camera);
mainRenderer->SetLayer(0);

vtkNew<vtkRenderer> frontRenderer;
frontRenderer->SetActiveCamera(camera);
frontRenderer->SetLayer(1);

vtkNew<vtkRenderWindow> renderWindow;
renderWindow->SetNumberOfLayers(2);
renderWindow->AddRenderer(mainRenderer);
renderWindow->AddRenderer(frontRenderer);

// An interactor
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);

vtkNew<vtkSphereSource> sphereSource;
sphereSource->Update();

// Create a mapper and actor
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(sphereSource->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(colors->GetColor3d("MistyRose").GetData());

// Cube Actor
vtkNew<vtkConeSource> cone;
cone->SetCenter(1.0, 1.0, 1.0);
cone->SetHeight(5);
cone->SetRadius(2.5);
cone->Update();

vtkNew<vtkPolyDataMapper> coneMapper;
coneMapper->SetInputData(cone->GetOutput());

vtkNew<vtkActor> coneActor;
coneActor->SetMapper(coneMapper);
coneActor->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());
coneActor->SetVisibility(true);
mainRenderer->AddActor(coneActor);

// Add transformWidget
vtkNew<modernTransformRepresentation> rep;
vtkNew<transformWidget> myWidget;
myWidget->SetInteractor(renderWindowInteractor);
myWidget->SetRepresentation(rep);

double bounds[6] = {-2.0, 4.0, -2.0, 4.0, -2.0, 4.0};
myWidget->GetRepresentation()->PlaceWidget(bounds);

vtkNew<transformCallback> callback;
callback->setActor(coneActor);
myWidget->AddObserver(vtkCommand::InteractionEvent, callback);
myWidget->SetEnabled(1);

// Add vtkCubeAxesActor
auto cubeAxesActor = vtkSmartPointer<vtkCubeAxesActor>::New();
cubeAxesActor->SetBounds(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0);
cubeAxesActor->SetCamera(mainRenderer->GetActiveCamera());
mainRenderer->AddActor(cubeAxesActor);

// Axes Widget
auto vtkAxes = vtkSmartPointer<vtkAxesActor>::New();
auto axesWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
axesWidget->SetOrientationMarker(vtkAxes);
axesWidget->SetDefaultRenderer(mainRenderer);
axesWidget->SetInteractor(renderWindowInteractor);
axesWidget->SetViewport(0.0, 0.0, 0.20, 0.20);
axesWidget->SetEnabled(1);
axesWidget->InteractiveOff();

// Reset camera
double allBounds[6];
mainRenderer->ComputeVisiblePropBounds(allBounds);
if (vtkMath::AreBoundsInitialized(allBounds))
{
    mainRenderer->ResetCamera(allBounds);
}

// Render
renderWindow->Render();

renderWindowInteractor->Initialize();
renderWindow->Render();

// Begin mouse interaction
renderWindowInteractor->Start();

return EXIT_SUCCESS;

}

#include <vtkActor.h>
#include <vtkCallbackCommand.h>
#include <vtkCollection.h>
#include <vtkCommand.h>
#include <vtkObjectFactory.h>
#include <vtkPropCollection.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkWidgetCallbackMapper.h>
#include <vtkWidgetEvent.h>

#include “simpleTransformRepresentation.hpp”
#include “transformWidget.hpp”

vtkStandardNewMacro(transformWidget);

transformWidget::transformWidget()
{
this->state_ = WIDGETSTATE::start;

// define widget events
{
    this->CallbackMapper->SetCallbackMethod(
        vtkCommand::LeftButtonPressEvent, vtkWidgetEvent::Select, this,
        transformWidget::SelectAction);

    this->CallbackMapper->SetCallbackMethod(
        vtkCommand::LeftButtonReleaseEvent, vtkWidgetEvent::EndSelect, this,
        transformWidget::EndSelectAction);

    this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent,
                                            vtkWidgetEvent::Move, this,
                                            transformWidget::MoveAction);

    this->keyEventCallbackCommand_ = vtkCallbackCommand::New();
    this->keyEventCallbackCommand_->SetClientData(this);
    this->keyEventCallbackCommand_->SetCallback(
        transformWidget::ProcessKeyEvents);
}

}

transformWidget::~transformWidget()
{
this->keyEventCallbackCommand_->Delete();
}

void transformWidget::SetEnabled(int enabling)
{
const int enabled = this->Enabled;

if (enabling && !enabled)
{
    // We do this step first because it sets the CurrentRenderer
    vtkAbstractWidget::SetEnabled(enabling);

    this->CreateDefaultRepresentation();

    if (this->Parent)
    {
        this->Parent->AddObserver(vtkCommand::KeyPressEvent,
                                  this->keyEventCallbackCommand_,
                                  this->Priority);
        this->Parent->AddObserver(vtkCommand::KeyReleaseEvent,
                                  this->keyEventCallbackCommand_,
                                  this->Priority);
    }
    else
    {
        this->Interactor->AddObserver(vtkCommand::KeyPressEvent,
                                      this->keyEventCallbackCommand_,
                                      this->Priority);
        this->Interactor->AddObserver(vtkCommand::KeyReleaseEvent,
                                      this->keyEventCallbackCommand_,
                                      this->Priority);
    }

    // Add the actor
    {
        vtkNew<vtkPropCollection> propsCollection;
        this->WidgetRep->GetActors(propsCollection);

        vtkCollectionSimpleIterator sIt;
        propsCollection->InitTraversal(sIt);

        const int nProps = propsCollection->GetNumberOfItems();
        for (int i = 0; i < nProps; i++)
        {
            vtkProp *actor =
                vtkProp::SafeDownCast(propsCollection->GetNextProp(sIt));
            if (actor != nullptr)
            {
                this->CurrentRenderer->AddActor(actor);
            }
        }
    }
}
else if (!enabling && enabled)
{
    if (this->Parent)
    {
        this->Parent->RemoveObserver(this->keyEventCallbackCommand_);
    }
    else
    {
        this->Interactor->RemoveObserver(this->keyEventCallbackCommand_);
    }

    // Remove the actor
    {
        vtkNew<vtkPropCollection> propsCollection;
        this->WidgetRep->GetActors(propsCollection);

        vtkCollectionSimpleIterator sIt;
        propsCollection->InitTraversal(sIt);

        const int nProps = propsCollection->GetNumberOfItems();
        for (int i = 0; i < nProps; i++)
        {
            vtkProp *actor =
                vtkProp::SafeDownCast(propsCollection->GetNextProp(sIt));
            if (actor != nullptr)
            {
                this->CurrentRenderer->RemoveActor(actor);
            }
        }
    }

    // We do this step last because the CurrentRenderer is still useful
    vtkAbstractWidget::SetEnabled(enabling);
}

this->Interactor->Render();

}

void transformWidget::CreateDefaultRepresentation()
{
if (!this->WidgetRep)
{
this->WidgetRep = simpleTransformRepresentation::New();
}
}

void transformWidget::SetRepresentation(transformRepresentation *rep)
{
this->Superclass::SetWidgetRepresentation(
vtkWidgetRepresentation::SafeDownCast(rep));
}

void transformWidget::PrintSelf(ostream &os, vtkIndent indent)
{
vtkAbstractWidget::PrintSelf(os, indent);
}

void transformWidget::SelectAction(vtkAbstractWidget *w)
{
auto self = reinterpret_cast<transformWidget *>(w);
if (self->WidgetRep->GetInteractionState() == INTERACTIONSTATE::outside)
{
return;
}

const int x = self->Interactor->GetEventPosition()[0];
const int y = self->Interactor->GetEventPosition()[1];

self->state_ = transformWidget::WIDGETSTATE::active;

self->GrabFocus(self->EventCallbackCommand);

double eventPos[2];
eventPos[0] = static_cast<double>(x);
eventPos[1] = static_cast<double>(y);
self->WidgetRep->StartWidgetInteraction(eventPos);

// start the interaction
self->EventCallbackCommand->SetAbortFlag(1);
self->StartInteraction();
self->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
self->Render();

}

void transformWidget::EndSelectAction(vtkAbstractWidget *w)
{
auto self = reinterpret_cast<transformWidget *>(w);
if (self->state_ == transformWidget::WIDGETSTATE::start)
{
return;
}

// Return state to not active
self->state_ = transformWidget::WIDGETSTATE::start;
self->ReleaseFocus();
self->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,
                  nullptr);  // handles observe this
self->EventCallbackCommand->SetAbortFlag(1);
self->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
self->EndInteraction();
self->Render();

}

void transformWidget::MoveAction(vtkAbstractWidget *w)
{
auto self = reinterpret_cast<transformWidget *>(w);

const int x = self->Interactor->GetEventPosition()[0];
const int y = self->Interactor->GetEventPosition()[1];

if (self->state_ ==
    transformWidget::WIDGETSTATE::start)  // if is not active
{
    self->Interactor->Disable();  // avoid extra renders

    const int prevState = self->WidgetRep->GetInteractionState();
    const int currState = self->WidgetRep->ComputeInteractionState(x, y);
    int cursorChanged = 0;

    {
        if (currState == INTERACTIONSTATE::outside)
        {
            cursorChanged = self->RequestCursorShape(VTK_CURSOR_DEFAULT);
        }
        else
        {
            cursorChanged = self->RequestCursorShape(VTK_CURSOR_HAND);
        }
    }

    self->WidgetRep->Highlight(1);

    self->Interactor->Enable();  // avoid extra renders

    if (cursorChanged || (prevState != currState))
    {
        self->Render();
    }
}
else  // if is active
{
    double e[2];
    e[0] = static_cast<double>(x);
    e[1] = static_cast<double>(y);

    self->InvokeEvent(vtkCommand::MouseMoveEvent,
                      nullptr);  // handles observe this

    self->WidgetRep->WidgetInteraction(e);

    self->EventCallbackCommand->SetAbortFlag(1);
    self->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
    self->Render();
}

}

void transformWidget::ProcessKeyEvents(vtkObject *, unsigned long, void *,
void *)
{
}

#pragma once

#include “vtkAbstractWidget.h”

class vtkCallbackCommand;

class transformRepresentation;

class transformWidget : public vtkAbstractWidget
{
public:
static transformWidget *New();

vtkTypeMacro(transformWidget, vtkAbstractWidget);
void PrintSelf(ostream &os, vtkIndent indent) override;

void SetEnabled(int enabling) override;

void CreateDefaultRepresentation() override;

void SetRepresentation(transformRepresentation *rep);

protected:
transformWidget();
~transformWidget() override;

static void SelectAction(vtkAbstractWidget *w);
static void EndSelectAction(vtkAbstractWidget *w);
static void MoveAction(vtkAbstractWidget *w);
static void ProcessKeyEvents(vtkObject *, unsigned long, void *, void *);

private:
enum WIDGETSTATE
{
start = 0,
active
};

int state_;
vtkCallbackCommand *keyEventCallbackCommand_;

transformWidget(const transformWidget &) = delete;
void operator=(const transformWidget &) = delete;

};