attach vtk context to gcompose
This commit is contained in:
150
src/Vtk/vtkObjectsContext.cpp
Normal file
150
src/Vtk/vtkObjectsContext.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "vtkObjectsContext.h"
|
||||
#include "vtkContainerBox.h"
|
||||
#include "HEP/Detectors/vtkDetectorChamber.h"
|
||||
|
||||
#include <vtkAssembly.h>
|
||||
#include <vtkPropCollection.h>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
namespace uLib {
|
||||
namespace Vtk {
|
||||
|
||||
vtkObjectsContext::vtkObjectsContext(uLib::ObjectsContext *context)
|
||||
: m_Context(context), m_Assembly(::vtkAssembly::New()) {
|
||||
this->SetProp(m_Assembly);
|
||||
if (m_Context) {
|
||||
Object::connect(m_Context, &uLib::ObjectsContext::ObjectAdded, this, &vtkObjectsContext::OnObjectAdded);
|
||||
Object::connect(m_Context, &uLib::ObjectsContext::ObjectRemoved, this, &vtkObjectsContext::OnObjectRemoved);
|
||||
this->Synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
vtkObjectsContext::~vtkObjectsContext() {
|
||||
for (auto const& [obj, puppet] : m_Puppets) {
|
||||
delete puppet;
|
||||
}
|
||||
m_Assembly->Delete();
|
||||
}
|
||||
|
||||
void vtkObjectsContext::Synchronize() {
|
||||
if (!m_Context) return;
|
||||
|
||||
// 1. Identify objects to add and remove
|
||||
const auto& objects = m_Context->GetObjects();
|
||||
std::map<uLib::Object*, bool> currentObjects;
|
||||
for (auto obj : objects) currentObjects[obj] = true;
|
||||
|
||||
// Remove puppets for objects no longer in context
|
||||
for (auto it = m_Puppets.begin(); it != m_Puppets.end(); ) {
|
||||
if (currentObjects.find(it->first) == currentObjects.end()) {
|
||||
it->second->DisconnectRenderer(nullptr); // If we have a ref to a renderer we should disconnect but Puppet doesn't store it easily
|
||||
// Actually Puppet::DisconnectRenderer(vtkRenderer*) needs the renderer.
|
||||
// For now we just remove from assembly
|
||||
vtkPropCollection* props = it->second->GetProps();
|
||||
props->InitTraversal();
|
||||
while(vtkProp* prop = props->GetNextProp()) {
|
||||
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||
m_Assembly->RemovePart(p3d);
|
||||
}
|
||||
this->PuppetRemoved(it->second);
|
||||
delete it->second;
|
||||
it = m_Puppets.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Add puppets for new objects
|
||||
for (auto obj : objects) {
|
||||
if (m_Puppets.find(obj) == m_Puppets.end()) {
|
||||
Puppet* puppet = this->CreatePuppet(obj);
|
||||
if (puppet) {
|
||||
m_Puppets[obj] = puppet;
|
||||
vtkPropCollection* props = puppet->GetProps();
|
||||
props->InitTraversal();
|
||||
while(vtkProp* prop = props->GetNextProp()) {
|
||||
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||
m_Assembly->AddPart(p3d);
|
||||
}
|
||||
this->PuppetAdded(puppet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vtkObjectsContext::OnObjectAdded(uLib::Object* obj) {
|
||||
if (!obj) return;
|
||||
if (m_Puppets.find(obj) == m_Puppets.end()) {
|
||||
Puppet* puppet = this->CreatePuppet(obj);
|
||||
if (puppet) {
|
||||
m_Puppets[obj] = puppet;
|
||||
vtkPropCollection* props = puppet->GetProps();
|
||||
props->InitTraversal();
|
||||
while(vtkProp* prop = props->GetNextProp()) {
|
||||
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||
m_Assembly->AddPart(p3d);
|
||||
}
|
||||
this->PuppetAdded(puppet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vtkObjectsContext::OnObjectRemoved(uLib::Object* obj) {
|
||||
if (!obj) return;
|
||||
auto it = m_Puppets.find(obj);
|
||||
if (it != m_Puppets.end()) {
|
||||
// For now we just remove from assembly.
|
||||
// Puppet::DisconnectRenderer(vtkRenderer*) needs the renderer, but we don't have it here easily.
|
||||
vtkPropCollection* props = it->second->GetProps();
|
||||
props->InitTraversal();
|
||||
while(vtkProp* prop = props->GetNextProp()) {
|
||||
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||
m_Assembly->RemovePart(p3d);
|
||||
}
|
||||
this->PuppetRemoved(it->second);
|
||||
delete it->second;
|
||||
m_Puppets.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
Puppet* vtkObjectsContext::GetPuppet(uLib::Object* obj) {
|
||||
auto it = m_Puppets.find(obj);
|
||||
if (it != m_Puppets.end()) return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void vtkObjectsContext::Update() {
|
||||
for (auto const& [obj, puppet] : m_Puppets) {
|
||||
puppet->Update();
|
||||
}
|
||||
}
|
||||
|
||||
Puppet* vtkObjectsContext::CreatePuppet(uLib::Object* obj) {
|
||||
if (!obj) return nullptr;
|
||||
|
||||
const char* className = obj->GetClassName();
|
||||
if (std::strcmp(className, "ContainerBox") == 0) {
|
||||
return new vtkContainerBox(static_cast<uLib::ContainerBox*>(obj));
|
||||
} else if (std::strcmp(className, "DetectorChamber") == 0) {
|
||||
return new vtkDetectorChamber(static_cast<uLib::DetectorChamber*>(obj));
|
||||
}
|
||||
|
||||
// Fallback if we don't know the exact class but it might be a context itself
|
||||
if (auto subCtx = dynamic_cast<uLib::ObjectsContext*>(obj)) {
|
||||
return new vtkObjectsContext(subCtx);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void vtkObjectsContext::PuppetAdded(Puppet* puppet) {
|
||||
ULIB_SIGNAL_EMIT(vtkObjectsContext::PuppetAdded, puppet);
|
||||
}
|
||||
|
||||
void vtkObjectsContext::PuppetRemoved(Puppet* puppet) {
|
||||
ULIB_SIGNAL_EMIT(vtkObjectsContext::PuppetRemoved, puppet);
|
||||
}
|
||||
|
||||
} // namespace Vtk
|
||||
} // namespace uLib
|
||||
Reference in New Issue
Block a user