attach vtk context to gcompose
This commit is contained in:
@@ -5,6 +5,7 @@ set(HEADERS uLibVtkInterface.h
|
||||
vtkQViewport.h
|
||||
vtkViewport.h
|
||||
vtkPolydata.h
|
||||
vtkObjectsContext.h
|
||||
)
|
||||
|
||||
set(SOURCES uLibVtkInterface.cxx
|
||||
@@ -14,6 +15,7 @@ set(SOURCES uLibVtkInterface.cxx
|
||||
vtkQViewport.cpp
|
||||
vtkViewport.cpp
|
||||
vtkPolydata.cpp
|
||||
vtkObjectsContext.cpp
|
||||
)
|
||||
|
||||
## Pull in Math VTK wrappers (sets MATH_SOURCES / MATH_HEADERS)
|
||||
|
||||
@@ -103,6 +103,10 @@ private:
|
||||
class PuppetData *d;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Vtk
|
||||
} // namespace uLib
|
||||
|
||||
|
||||
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
|
||||
54
src/Vtk/vtkObjectsContext.h
Normal file
54
src/Vtk/vtkObjectsContext.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef U_VTKOBJECTSCONTEXT_H
|
||||
#define U_VTKOBJECTSCONTEXT_H
|
||||
|
||||
#include <map>
|
||||
#include "Core/ObjectsContext.h"
|
||||
#include "uLibVtkInterface.h"
|
||||
|
||||
class vtkAssembly;
|
||||
|
||||
namespace uLib {
|
||||
namespace Vtk {
|
||||
|
||||
/**
|
||||
* @brief vtkObjectsContext manages VTK representations (Puppets) for a collection of uLib::Objects.
|
||||
*/
|
||||
class vtkObjectsContext : public uLib::Object, public Puppet {
|
||||
public:
|
||||
virtual const char* GetClassName() const override { return "vtkObjectsContext"; }
|
||||
vtkObjectsContext(uLib::ObjectsContext *context);
|
||||
virtual ~vtkObjectsContext();
|
||||
|
||||
/** @brief Synchronizes the VTK puppets with the core ObjectsContext. */
|
||||
void Synchronize();
|
||||
|
||||
/** @brief Returns the puppet associated with a specific core object. */
|
||||
Puppet* GetPuppet(uLib::Object* obj);
|
||||
|
||||
/** @brief Updates all managed puppets. */
|
||||
virtual void Update() override;
|
||||
|
||||
public:
|
||||
virtual void PuppetAdded(Puppet* puppet);
|
||||
virtual void PuppetRemoved(Puppet* puppet);
|
||||
|
||||
public:
|
||||
/** @brief Slot called when an object is added to the core context. */
|
||||
void OnObjectAdded(uLib::Object* obj);
|
||||
/** @brief Slot called when an object is removed from the core context. */
|
||||
void OnObjectRemoved(uLib::Object* obj);
|
||||
|
||||
protected:
|
||||
/** @brief Factory method to create a puppet for a core object. */
|
||||
Puppet* CreatePuppet(uLib::Object* obj);
|
||||
|
||||
private:
|
||||
uLib::ObjectsContext *m_Context;
|
||||
std::map<uLib::Object*, Puppet*> m_Puppets;
|
||||
vtkAssembly *m_Assembly;
|
||||
};
|
||||
|
||||
} // namespace Vtk
|
||||
} // namespace uLib
|
||||
|
||||
#endif // U_VTKOBJECTSCONTEXT_H
|
||||
Reference in New Issue
Block a user