# Observe camera node events in a loadable module logic

**URL:** <https://discourse.slicer.org/t/observe-camera-node-events-in-a-loadable-module-logic/17879>\
**Category:** Development\
**Created:** [May 31, 2021, 6:02am UTC](https://discourse.slicer.org/t/observe-camera-node-events-in-a-loadable-module-logic/17879 "2021-05-31T06:02:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mik](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@Mik](https://discourse.slicer.org/u/Mik)\
**Post date:** [May 31, 2021, 6:02am UTC](https://discourse.slicer.org/t/observe-camera-node-events-in-a-loadable-module-logic/17879/1 "2021-05-31T06:02:45Z")

</div>

Are there any specific requirements to observe vtkMRMLCameraNode events in C++ module logic?

Python code works as it should, and i can see “update beam” message

```auto
def updateBeamFromCamera(caller=None, event=None):
  print("update beam")

cameraObs = threeDcamera.AddObserver( vtk.vtkCommand.ModifiedEvent, updateBeamFromCamera)

```

But i can’t observe any camera node events in C++ module.

Did i miss something obvious?

Here is a part of C++ code

```auto
//-----------------------------------------------------------------------------
void vtkSlicerSomeLogic::RegisterNodes()
{
  vtkMRMLScene* scene = this->GetMRMLScene(); 
  if (!scene)
  {
    vtkErrorMacro("RegisterNodes: Invalid MRML scene");
    return;
  }
  if (!scene->IsNodeClassRegistered("vtkMRMLCameraNode"))
  {
    vtkWarningMacro("OnMRMLSceneNodeAdded: camera registered");
    scene->RegisterNodeClass(vtkSmartPointer<vtkMRMLCameraNode>::New());
  }
}

//---------------------------------------------------------------------------
void vtkSlicerSomeLogic::OnMRMLSceneNodeAdded(vtkMRMLNode* node)
{
  if (!node || !this->GetMRMLScene())
  {
    vtkErrorMacro("OnMRMLSceneNodeAdded: Invalid MRML scene or input node");
    return;
  }

  if (node->IsA("vtkMRMLCameraNode"))
  {
    vtkWarningMacro("OnMRMLSceneNodeAdded: Observe camera events");
    // Observe camera events
    vtkNew<vtkIntArray> events;
    events->InsertNextValue(vtkCommand::ModifiedEvent);
    vtkObserveMRMLNodeEventsMacro(node, events);
  }
}

//----------------------------------------------------------------------------
void vtkSlicerSomeLogic::ProcessMRMLNodesEvents(vtkObject* caller, unsigned long event, void* callData)
{
  Superclass::ProcessMRMLNodesEvents(caller, event, callData);

  vtkMRMLScene* mrmlScene = this->GetMRMLScene();
  if (!mrmlScene)
  {
    vtkErrorMacro("ProcessMRMLNodesEvents: Invalid MRML scene");
    return;
  }
  if (mrmlScene->IsBatchProcessing())
  {
    return;
  }

  if (caller->IsA("vtkMRMLCameraNode"))
  {
    vtkMRMLCameraNode* cameraNode = vtkMRMLCameraNode::SafeDownCast(caller);
    if (event == vtkCommand::ModifiedEvent)
    {
      vtkWarningMacro("ProcessMRMLNodesEvents: Camera modified");
    }
    else
    {
      vtkWarningMacro("ProcessMRMLNodesEvents: Other events");
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [May 31, 2021, 6:52pm UTC](https://discourse.slicer.org/t/observe-camera-node-events-in-a-loadable-module-logic/17879/2 "2021-05-31T18:52:28Z")

</div>

> [@Mik](#):
>
> `scene->RegisterNodeClass(vtkSmartPointer<vtkMRMLCameraNode>::New());`

This would re-register the vtkMRMLCameraNode class, this must not be done.

> [@Mik](#):
>
> ```auto
> if (node->IsA("vtkMRMLCameraNode"))
> {
> vtkWarningMacro("OnMRMLSceneNodeAdded: Observe camera events");
> // Observe camera events
> vtkNew<vtkIntArray> events;
> events->InsertNextValue(vtkCommand::ModifiedEvent);
> vtkObserveMRMLNodeEventsMacro(node, events);
> }
> 
> ```

This would add observer to the last added camera node. Instead of this, you should either observe all the camera nodes or one that the user selected.

---

<div class="post-metadata">

**Author:** ![Mik](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@Mik](https://discourse.slicer.org/u/Mik)\
**Post date:** [May 31, 2021, 8:27pm UTC](https://discourse.slicer.org/t/observe-camera-node-events-in-a-loadable-module-logic/17879/3 "2021-05-31T20:27:05Z")

</div>

Thank you! I understood what was the problem.

Another question. Should i remove observe from previously observed camera if i change one camera to the other or it is an automatic process?

for example

```auto
//----------------------------------------------------------------------------
void vtkMRMLMyCustomNode::SetAndObserveCameraNode(vtkMRMLCameraNode* node)
{
  if (node && this->Scene != node->GetScene())
  {
    vtkErrorMacro("SetAndObserveCameraNode: Cannot set reference");
    return;
  }

  if(vtkMRMLCameraNode* previouslyObservedNode = this->GetCameraNode())
  {
    vtkUnObserveMRMLObjectMacro(previouslyObservedNode );
  }

  this->SetNodeReferenceID(CAMERA_REFERENCE_ROLE, (node ? node->GetID() : nullptr));

  if (node)
  {
    vtkNew<vtkIntArray> events;
    events->InsertNextValue(vtkCommand::ModifiedEvent);
    vtkObserveMRMLObjectEventsMacro(node, events);
  }
}

```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [May 31, 2021, 9:18pm UTC](https://discourse.slicer.org/t/observe-camera-node-events-in-a-loadable-module-logic/17879/4 "2021-05-31T21:18:28Z")

</div>

> [@Mik](#):
>
> Another question. Should i remove observe from previously observed camera if i change one camera to the other or it is an automatic process?

`vtkObserveMRMLObjectEventsMacro` only adds the observer, never removes it, so you either need to use `vtkUnObserveMRMLObjectEventsMacro` for the previously observed node; or use `vtkSetAndObserveMRMLObjectMacro`, which automatically removes the previous observation.
