refactor: rename Puppet class to Prop3D across the codebase

This commit is contained in:
AndreaRigoni
2026-04-08 15:47:33 +00:00
parent 77f00a2b8a
commit f7ba4b1a17
63 changed files with 412 additions and 413 deletions

View File

@@ -6,4 +6,4 @@ When this rule is active, restrict the operational context to libraries excludin
- **Exclude Path**: `src/Vtk`
- **Include Paths**: `src/Core`, `src/Math`, `src/HEP`, `src/Root`, `src/Python`, `src/utils`
- **Focus**: Tomographic reconstruction algorithms, data structures in `Core`, and physical modeling in `HEP`.
- **Constraint**: Avoid referencing `Puppet`, `Viewport`, or any VTK-specific headers unless the user overrides this restriction.
- **Constraint**: Avoid referencing `Prop3D`, `Viewport`, or any VTK-specific headers unless the user overrides this restriction.

View File

@@ -4,6 +4,6 @@ trigger: always_on
# Context Inclusion: VTK
When this rule is active, include the VTK visualization layer in the operational context.
- **Priority Path**: `src/Vtk`
- **Focus**: `Puppet` hierarchy, `Viewport` management, and the synchronization between domain objects and VTK props.
- **Focus**: `Prop3D` hierarchy, `Viewport` management, and the synchronization between domain objects and VTK props.
- **Key Classes**: `vtkViewport`, `vtkQViewport`, `vtkObjectsContext`, and all classes in `src/Vtk/HEP/Geant`.
- **Logic**: Ensure transformations (TRS) applied to domain objects are correctly mirrored in the visualization layer and vice versa.

View File

@@ -71,32 +71,32 @@ mutomCore → mutomMath → mutomDetectors → mutomGeant
- `ObjectsContext` is a container owning a list of `Object*` pointers; signals `ObjectAdded`/`ObjectRemoved`
### VTK Layer (`src/Vtk/`)
- `Puppet` (inherits `uLib::Object`): wraps a VTK `vtkProp` for rendering. Has `GetContent()` returning the underlying domain object. Display-only properties are registered via `ULIB_ACTIVATE_DISPLAY_PROPERTIES` macro.
- `Viewport`: base class managing the VTK renderer, picking, selection logic. Maintains `m_Puppets` vector and `m_ObjectToPuppet` map.
- `QViewport` (inherits `QWidget` + `Viewport`): Qt-embedded VTK widget. Emits Qt signal `puppetSelected(Puppet*)` on click-selection via `OnSelectionChanged`.
- `vtkObjectsContext`: wraps `ObjectsContext`, creating/destroying `Puppet`s as objects come/go. Emits `PuppetAdded`/`PuppetRemoved`.
- Display properties: `serialize_display()` + `display_properties_archive` registers selected `hrp<T>` fields as `PropertyBase*` in the puppet's `m_DisplayProperties`. `PropertyEditor::setObject(obj, displayOnly=true)` shows only those.
- `Prop3D` (inherits `uLib::Object`): wraps a VTK `vtkProp` for rendering. Has `GetContent()` returning the underlying domain object. Display-only properties are registered via `ULIB_ACTIVATE_DISPLAY_PROPERTIES` macro.
- `Viewport`: base class managing the VTK renderer, picking, selection logic. Maintains `m_Prop3Ds` vector and `m_ObjectToProp3D` map.
- `QViewport` (inherits `QWidget` + `Viewport`): Qt-embedded VTK widget. Emits Qt signal `prop3dSelected(Prop3D*)` on click-selection via `OnSelectionChanged`.
- `vtkObjectsContext`: wraps `ObjectsContext`, creating/destroying `Prop3D`s as objects come/go. Emits `Prop3DAdded`/`Prop3DRemoved`.
- Display properties: `serialize_display()` + `display_properties_archive` registers selected `hrp<T>` fields as `PropertyBase*` in the prop3d's `m_DisplayProperties`. `PropertyEditor::setObject(obj, displayOnly=true)` shows only those.
### gcompose GUI App (`app/gcompose/src/`)
- `MainPanel`: top-level widget. Owns `ContextPanel` (left) and `ViewportPane` (right). Wires together viewport↔context selection via signals.
- `ContextPanel`: tree view of `ObjectsContext`. Emits `objectSelected(Object*)`. Contains an embedded `PropertiesPanel`.
- `PropertiesPanel`: shows `uLib::Object` properties via `PropertyEditor`.
- `ViewportPane`: embeds `QViewport` + a slide-out "Display Properties" panel (`PropertyEditor` in display-only mode).
- `PropertyEditor`: populates widgets from `Object::GetProperties()` (all) or `Puppet::GetDisplayProperties()` (display-only mode).
- `PropertyEditor`: populates widgets from `Object::GetProperties()` (all) or `Prop3D::GetDisplayProperties()` (display-only mode).
### Selection Sync Flow
```
Viewport click → Viewport::SelectPuppet() → QViewport::OnSelectionChanged()
→ emit puppetSelected(p)
Viewport click → Viewport::SelectProp3D() → QViewport::OnSelectionChanged()
→ emit prop3dSelected(p)
→ MainPanel: contextPanel->selectObject(p->GetContent()) [updates tree + PropertiesPanel]
→ MainPanel: firstPane->setObject(p) [updates Display Properties panel]
ContextPanel tree click → emit objectSelected(obj)
→ MainPanel: viewport->SelectPuppet(puppet) [visual selection in VTK]
→ MainPanel: firstPane->setObject(puppet) [updates Display Properties panel]
→ MainPanel: viewport->SelectProp3D(prop3d) [visual selection in VTK]
→ MainPanel: firstPane->setObject(prop3d) [updates Display Properties panel]
```
### Key Patterns
- **Two signal systems coexist**: Qt signals (`Q_OBJECT`, `connect(...)`) for GUI; `uLib::Object::connect(...)` for domain signals.
- **Display properties** flow: `Puppet::serialize_display()``display_properties_archive``RegisterDisplayProperty()``PropertyEditor(displayOnly=true)`. Must call `ULIB_ACTIVATE_DISPLAY_PROPERTIES` in the puppet constructor.
- **Puppet ↔ Object map**: `Viewport::m_ObjectToPuppet` allows lookup by domain object; `vtkObjectsContext::GetPuppet(obj)` does the same.
- **Display properties** flow: `Prop3D::serialize_display()``display_properties_archive``RegisterDisplayProperty()``PropertyEditor(displayOnly=true)`. Must call `ULIB_ACTIVATE_DISPLAY_PROPERTIES` in the prop3d constructor.
- **Prop3D ↔ Object map**: `Viewport::m_ObjectToProp3D` allows lookup by domain object; `vtkObjectsContext::GetProp3D(obj)` does the same.

View File

@@ -90,13 +90,13 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent), m_context(nullptr), m_m
connect(m_contextPanel, &ContextPanel::objectSelected, [this](uLib::Object* obj) {
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
uLib::Vtk::Puppet* puppet = nullptr;
uLib::Vtk::Prop3D* prop3d = nullptr;
if (m_mainVtkContext) {
puppet = m_mainVtkContext->GetPuppet(obj);
prop3d = m_mainVtkContext->GetProp3D(obj);
}
viewport->SelectPuppet(puppet);
// Update the display properties in the viewport pane itself - use the puppet proxy if possible
m_firstPane->setObject(puppet ? (uLib::Object*)puppet : obj);
viewport->SelectProp3D(prop3d);
// Update the display properties in the viewport pane itself - use the prop3d proxy if possible
m_firstPane->setObject(prop3d ? (uLib::Object*)prop3d : obj);
} else {
m_firstPane->setObject(obj);
}
@@ -116,7 +116,7 @@ void MainPanel::setContext(uLib::ObjectsContext* context) {
if (m_mainVtkContext) {
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
viewport->RemovePuppet(*m_mainVtkContext);
viewport->RemoveProp3D(*m_mainVtkContext);
}
delete m_mainVtkContext;
m_mainVtkContext = nullptr;
@@ -125,9 +125,9 @@ void MainPanel::setContext(uLib::ObjectsContext* context) {
if (context) {
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
m_mainVtkContext = new uLib::Vtk::ObjectsContext(context);
// viewport->AddPuppet(*m_mainVtkContext); // redundant
// viewport->AddProp3D(*m_mainVtkContext); // redundant
auto syncSelection = [this](uLib::Vtk::Puppet* p) {
auto syncSelection = [this](uLib::Vtk::Prop3D* p) {
if (!p) {
m_contextPanel->clearSelection();
m_firstPane->setObject(nullptr);
@@ -136,14 +136,14 @@ void MainPanel::setContext(uLib::ObjectsContext* context) {
m_firstPane->setObject(p);
}
};
connect(viewport, &uLib::Vtk::QViewport::puppetSelected, syncSelection);
connect(viewport, &uLib::Vtk::QViewport::prop3dSelected, syncSelection);
uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::ObjectsContext::PuppetAdded, [this](uLib::Vtk::Puppet* p) {
uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::ObjectsContext::Prop3DAdded, [this](uLib::Vtk::Prop3D* p) {
if (p) {
auto panes = this->findChildren<ViewportPane*>();
for (auto* pane : panes) {
if (auto* vp = qobject_cast<uLib::Vtk::QViewport*>(pane->currentViewport())) {
vp->AddPuppet(*p);
vp->AddProp3D(*p);
vp->ZoomAuto();
vp->Render();
}
@@ -151,25 +151,25 @@ void MainPanel::setContext(uLib::ObjectsContext* context) {
}
});
uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::ObjectsContext::PuppetRemoved, [this](uLib::Vtk::Puppet* p) {
uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::ObjectsContext::Prop3DRemoved, [this](uLib::Vtk::Prop3D* p) {
if (p) {
auto panes = this->findChildren<ViewportPane*>();
for (auto* pane : panes) {
if (auto* vp = qobject_cast<uLib::Vtk::QViewport*>(pane->currentViewport())) {
vp->RemovePuppet(*p);
vp->RemoveProp3D(*p);
vp->Render();
}
}
}
});
// Add any puppets that were created during m_mainVtkContext's construction to all panes
// Add any prop3ds that were created during m_mainVtkContext's construction to all panes
auto panes = this->findChildren<ViewportPane*>();
for (auto* obj : context->GetObjects()) {
if (auto* p = m_mainVtkContext->GetPuppet(obj)) {
if (auto* p = m_mainVtkContext->GetProp3D(obj)) {
for (auto* pane : panes) {
if (auto* vp = qobject_cast<uLib::Vtk::QViewport*>(pane->currentViewport())) {
vp->AddPuppet(*p);
vp->AddProp3D(*p);
}
}
}

View File

@@ -403,10 +403,10 @@ void PropertyEditor::setObject(::uLib::Object* obj, bool displayOnly) {
const std::vector<::uLib::PropertyBase*>* props = &obj->GetProperties();
if (displayOnly) {
if (auto* puppet = dynamic_cast<::uLib::Vtk::Puppet*>(obj)) {
props = &puppet->GetDisplayProperties();
if (auto* prop3d = dynamic_cast<::uLib::Vtk::Prop3D*>(obj)) {
props = &prop3d->GetDisplayProperties();
} else {
// If it's not a puppet but displayOnly is requested, showing nothing or fallback?
// If it's not a prop3d but displayOnly is requested, showing nothing or fallback?
// Fallback: core properties.
}
}

View File

@@ -88,7 +88,7 @@ void QViewportPane::toggleDisplayPanel() {
void QViewportPane::setObject(uLib::Object* obj) {
m_displayEditor->setObject(obj, true);
// Auto-show panel if it's a puppet and we want to highlight this feature?
// Auto-show panel if it's a prop3d and we want to highlight this feature?
// User asked for "hiding panel", so maybe we don't auto-show.
}
@@ -179,9 +179,9 @@ void QViewportPane::AttemptSplit(Qt::Orientation orientation) {
if (currentVtk) {
auto* newVtk = qobject_cast<uLib::Vtk::QViewport*>(newPane->currentViewport());
if (newVtk) {
// Copy puppets
for (auto* puppet : currentVtk->getPuppets()) {
newVtk->AddPuppet(*puppet);
// Copy prop3ds
for (auto* prop3d : currentVtk->getProp3Ds()) {
newVtk->AddProp3D(*prop3d);
}
// Copy camera
if (currentVtk->GetRenderer() && newVtk->GetRenderer()) {

View File

@@ -99,15 +99,15 @@ void ViewportPane::toggleDisplayPanel() {
void ViewportPane::setObject(uLib::Object* obj) {
m_displayEditor->setObject(obj, true);
// Check if the object is a Puppet (meaning it has display properties)
bool isPuppet = (dynamic_cast<::uLib::Vtk::Puppet*>(obj) != nullptr);
// Check if the object is a Prop3D (meaning it has display properties)
bool isProp3D = (dynamic_cast<::uLib::Vtk::Prop3D*>(obj) != nullptr);
// Only show the "Display" toggle button if it's a puppet
m_toggleBtn->setVisible(isPuppet);
// Only show the "Display" toggle button if it's a prop3d
m_toggleBtn->setVisible(isProp3D);
// If it's a puppet, we might want to keep the panel state if it was already open,
// or if it's NOT a puppet, definitely hide the toggle and panel.
if (!isPuppet) {
// If it's a prop3d, we might want to keep the panel state if it was already open,
// or if it's NOT a prop3d, definitely hide the toggle and panel.
if (!isProp3D) {
m_toggleBtn->setChecked(false);
m_displayPanel->hide();
}

View File

@@ -1,21 +1,21 @@
# Properties and the vtk-gui representation
This is the rationale behind the connection between TRS properties and Puppet Transformation.
This is the rationale behind the connection between TRS properties and Prop3D Transformation.
The properties from model get propoagated via Object signalling system (the Update signal) to the vtkRepresentation and to the Qt widgets so that the overall transformation of the model reflects into a modification of its representation in vtk and in the gui.
In addition the properties need to be adjusted also from vtk, for example if user uses handlerwidget to change the transformation this is eventually applied to Puppet and Puppet should propagate the transformation change to the vtk representation object (for instance vtkContainerBox) and the latter eventually propagates the change into the model.
In addition the properties need to be adjusted also from vtk, for example if user uses handlerwidget to change the transformation this is eventually applied to Prop3D and Prop3D should propagate the transformation change to the vtk representation object (for instance vtkContainerBox) and the latter eventually propagates the change into the model.
the Puppet or the vtk representation wrapper ( vtkContainerBox for instance is the wrapper od ContainerBox ) should not directly show the transformation of the handlerwidget but it should show the transformation of the model once applied so we are always seeing the actual aspect of the model reflected to the vtk representation and not the other way around.
the Prop3D or the vtk representation wrapper ( vtkContainerBox for instance is the wrapper od ContainerBox ) should not directly show the transformation of the handlerwidget but it should show the transformation of the model once applied so we are always seeing the actual aspect of the model reflected to the vtk representation and not the other way around.
So in syntesis the model is the master and the vtk representation and the gui are the slaves of any modification, but the vtkHandlerWidget is able to apply a transform that should be applied to the model and then the model should propagate the transformation change to the vtk representation and to the gui.
## The Puppet
## The Prop3D
The puppet is the proxy of the spatial placement of objects in the scene. Puppets should have an internal ContainerBox that is shown in the scene around the content to be able to pick Puppet from vtkViewport using the handler widget. The HandlerWidget moves the Puppet ContainerBox (the red Highlight element whe selected) to reflect the handler current transformation, but the transformation is propagated to the derived Puppet classes like vtkContainerBox.
The prop3d is the proxy of the spatial placement of objects in the scene. Prop3Ds should have an internal ContainerBox that is shown in the scene around the content to be able to pick Prop3D from vtkViewport using the handler widget. The HandlerWidget moves the Prop3D ContainerBox (the red Highlight element whe selected) to reflect the handler current transformation, but the transformation is propagated to the derived Prop3D classes like vtkContainerBox.
The vtkHandlerWidget should handle the transformation of the puppet internal ContainerBox. The changes of the ContainerBox will be propagated to the derived classes and eventually to the model.
The vtkHandlerWidget should handle the transformation of the prop3d internal ContainerBox. The changes of the ContainerBox will be propagated to the derived classes and eventually to the model.

View File

@@ -39,7 +39,7 @@ EmitterPrimary::EmitterPrimary()
// Initial position and direction through AffineTransform
// 10m on Z axis, pointing towards origin
this->SetPosition(Vector3f(0, 0, 10000.0));
// Default orientation is identity (pointing along -Z if we rotate the puppet accordingly)
// Default orientation is identity (pointing along -Z if we rotate the prop3d accordingly)
// But fParticleGun defaults are set here and overridden in GeneratePrimaries
}

View File

@@ -41,7 +41,7 @@ namespace uLib {
* transformation that is applied on top of each child's own transform.
*
* A bounding box is automatically computed from all contained objects and
* can be queried or shown/hidden through the VTK puppet.
* can be queried or shown/hidden through the VTK prop3d.
*/
class Assembly : public ObjectsContext, public TRS {
public:
@@ -81,7 +81,7 @@ public:
/**
* @brief Controls whether the bounding box wireframe should be shown
* in the viewer (used by the VTK puppet).
* in the viewer (used by the VTK prop3d).
*/
void SetShowBoundingBox(bool show);
bool GetShowBoundingBox() const;

View File

@@ -45,8 +45,8 @@ BOOST_AUTO_TEST_CASE(vtkDetectorChamberTest) {
Vtk::DetectorChamber v_d1(&d1);
Vtk::DetectorChamber v_d2(&d2);
v_d1.SetRepresentation(Vtk::Puppet::Surface);
v_d2.SetRepresentation(Vtk::Puppet::Surface);
v_d1.SetRepresentation(Vtk::Prop3D::Surface);
v_d2.SetRepresentation(Vtk::Prop3D::Surface);
if (!v_d1.GetProp()) {
BOOST_FAIL("DetectorChamber::GetProp() returned NULL");
@@ -55,8 +55,8 @@ BOOST_AUTO_TEST_CASE(vtkDetectorChamberTest) {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.SetGridAxis(Vtk::Viewport::Y);
viewer.AddPuppet(v_d1);
viewer.AddPuppet(v_d2);
viewer.AddProp3D(v_d1);
viewer.AddProp3D(v_d2);
viewer.Start();
}

View File

@@ -42,10 +42,10 @@
using namespace uLib;
// A simple puppet class to represent an arrow indicative of a projected muon hit
class vtkArrowPuppet : public Vtk::Puppet {
// A simple prop3d class to represent an arrow indicative of a projected muon hit
class vtkArrowProp3D : public Vtk::Prop3D {
public:
vtkArrowPuppet() : m_Actor(vtkActor::New()) {
vtkArrowProp3D() : m_Actor(vtkActor::New()) {
vtkNew<vtkArrowSource> arrow;
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(arrow->GetOutputPort());
@@ -54,7 +54,7 @@ public:
m_Actor->GetProperty()->SetColor(1, 1, 0); // Yellow color for visibility
}
virtual ~vtkArrowPuppet() { m_Actor->Delete(); }
virtual ~vtkArrowProp3D() { m_Actor->Delete(); }
void SetProjection(const HLine3f &line) {
HPoint3f p = line.origin;
@@ -131,24 +131,24 @@ BOOST_AUTO_TEST_CASE(vtkDetectorMuonProjectionTest) {
v_event.AddPocaPoint(HPoint3f(0, 0, 0));
v_event.SetColor(1, 0, 0); // Red muon event
v_d1.SetRepresentation(Vtk::Puppet::Surface);
v_d1.SetRepresentation(Vtk::Prop3D::Surface);
v_d1.SetOpacity(0.3);
v_d2.SetRepresentation(Vtk::Puppet::Surface);
v_d2.SetRepresentation(Vtk::Prop3D::Surface);
v_d2.SetOpacity(0.3);
// 5. Add two arrows to mark where the projection is located on the chambers
vtkArrowPuppet v_p1, v_p2;
vtkArrowProp3D v_p1, v_p2;
v_p1.SetProjection(mu_proj1.LineIn());
v_p2.SetProjection(mu_proj2.LineIn());
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.SetGridAxis(Vtk::Viewport::Z);
viewer.AddPuppet(v_d1);
viewer.AddPuppet(v_d2);
viewer.AddPuppet(v_event);
viewer.AddPuppet(v_p1);
viewer.AddPuppet(v_p2);
viewer.AddProp3D(v_d1);
viewer.AddProp3D(v_d2);
viewer.AddProp3D(v_event);
viewer.AddProp3D(v_p1);
viewer.AddProp3D(v_p2);
viewer.Start();
}

View File

@@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(vtkMuonScatterTest) {
// Vtk::Tie<Vtk::Viewer> vms;
// vms.DoAction();
viewer.AddPuppet(v_event);
viewer.AddProp3D(v_event);
viewer.Start();
}

View File

@@ -50,7 +50,7 @@
namespace uLib {
namespace Vtk {
class MuonEvent : public Puppet, public Polydata {
class MuonEvent : public Prop3D, public Polydata {
typedef MuonEventData Content;
public:

View File

@@ -54,7 +54,7 @@ class vtkRenderWindowInteractor;
namespace uLib {
namespace Vtk {
class MuonScatter : public Puppet, public Polydata {
class MuonScatter : public Prop3D, public Polydata {
typedef uLib::MuonScatter Content;
public:
@@ -66,9 +66,9 @@ public:
Content &GetModel();
uLib::Object* GetContent() const override { return (uLib::Object*)m_Content; }
void PrintSelf(std::ostream &o) const;
void PrintSelf(std::ostream &o) const override;
virtual vtkPolyData *GetPolyData() const;
virtual vtkPolyData *GetPolyData() const override;
void AddPocaPoint(HPoint3f poca);
@@ -77,7 +77,7 @@ public:
void vtkStartInteractive();
protected:
void ConnectInteractor(vtkRenderWindowInteractor *interactor);
void ConnectInteractor(vtkRenderWindowInteractor *interactor) override;
private:
void InstallPipe();

View File

@@ -59,7 +59,7 @@ void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void
<< " with " << lastEvent->Path().size() << " steps." << std::endl;
Vtk::GeantEvent* vtkEvent = new Vtk::GeantEvent(lastEvent);
state->viewer->AddPuppet(*vtkEvent);
state->viewer->AddProp3D(*vtkEvent);
state->viewer->GetRenderer()->Render();
state->viewer->GetRenderWindow()->Render();
@@ -99,19 +99,19 @@ int main(int argc, char** argv) {
Vtk::ContainerBox* vtkWorld = new Vtk::ContainerBox(scene.GetWorldBox());
vtkWorld->ShowScaleMeasures(true);
vtkWorld->SetRepresentation(Vtk::Puppet::Wireframe);
vtkWorld->SetRepresentation(Vtk::Prop3D::Wireframe);
vtkWorld->SetSelectable(false);
viewer.AddPuppet(*vtkWorld);
viewer.AddProp3D(*vtkWorld);
Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box);
vtkIron->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkIron);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron);
// Use vtkCylinderEmitterPrimary
Vtk::vtkCylinderEmitterPrimary* vtkEmitter = new Vtk::vtkCylinderEmitterPrimary(*emitter);
vtkEmitter->SetSelectable(false);
viewer.AddPuppet(*vtkEmitter);
viewer.AddProp3D(*vtkEmitter);
// 3. Event Handling
AppState state = { &scene, &viewer, {} };

View File

@@ -52,7 +52,7 @@ void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void
// Wrap it for VTK
Vtk::GeantEvent* vtkEvent = new Vtk::GeantEvent(lastEvent);
state->viewer->AddPuppet(*vtkEvent);
state->viewer->AddProp3D(*vtkEvent);
// Re-render
state->viewer->GetRenderer()->Render();
@@ -107,33 +107,33 @@ int main(int argc, char** argv) {
// Visualize world box
Vtk::ContainerBox* vtkWorld = new Vtk::ContainerBox(scene.GetWorldBox());
vtkWorld->ShowScaleMeasures(true);
vtkWorld->SetRepresentation(Vtk::Puppet::Wireframe);
vtkWorld->SetRepresentation(Vtk::Prop3D::Wireframe);
vtkWorld->SetSelectable(false);
viewer.AddPuppet(*vtkWorld);
viewer.AddProp3D(*vtkWorld);
// Visualize iron cube
Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box);
vtkIron->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkIron);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron);
// Visualize Top Chamber
Vtk::DetectorChamber* vtkTop = new Vtk::DetectorChamber(top_chamber_box);
vtkTop->SetOpacity(0.5);
vtkTop->SetColor(0.2, 0.8, 0.2);
vtkTop->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkTop);
vtkTop->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkTop);
// Visualize Bottom Chamber
Vtk::DetectorChamber* vtkBottom = new Vtk::DetectorChamber(bottom_chamber_box);
vtkBottom->SetOpacity(0.5);
vtkBottom->SetColor(0.2, 0.8, 0.2);
vtkBottom->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkBottom);
vtkBottom->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkBottom);
// Visualize Emitter
Vtk::EmitterPrimary* vtkEmitter = new Vtk::EmitterPrimary(*emitter);
viewer.AddPuppet(*vtkEmitter);
viewer.AddProp3D(*vtkEmitter);
// 3. Event Handling
AppState state = { &scene, &viewer, {} };

View File

@@ -83,7 +83,7 @@ void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void
// Wrap it for VTK
Vtk::GeantEvent* vtkEvent = new Vtk::GeantEvent(lastEvent);
state->viewer->AddPuppet(*vtkEvent);
state->viewer->AddProp3D(*vtkEvent);
// Re-render
state->viewer->GetRenderer()->Render();
@@ -120,13 +120,13 @@ int main(int argc, char** argv) {
Vtk::ContainerBox* vtkWorld = new Vtk::ContainerBox(scene.GetWorldBox());
// vtkWorld->ShowBoundingBox(true);
vtkWorld->ShowScaleMeasures(true);
viewer.AddPuppet(*vtkWorld);
viewer.AddProp3D(*vtkWorld);
// Visualize iron cube
Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box);
vtkIron->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkIron);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron);
// 3. Event Handling
AppState state = { &scene, &viewer, {} };

View File

@@ -50,7 +50,7 @@ void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void
<< " with " << lastEvent->Path().size() << " steps." << std::endl;
Vtk::GeantEvent* vtkEvent = new Vtk::GeantEvent(lastEvent);
state->viewer->AddPuppet(*vtkEvent);
state->viewer->AddProp3D(*vtkEvent);
state->viewer->GetRenderer()->Render();
state->viewer->GetRenderWindow()->Render();
@@ -109,33 +109,33 @@ int main(int argc, char** argv) {
Vtk::ContainerBox* vtkWorld = new Vtk::ContainerBox(scene.GetWorldBox());
vtkWorld->ShowScaleMeasures(true);
vtkWorld->SetRepresentation(Vtk::Puppet::Wireframe);
vtkWorld->SetRepresentation(Vtk::Prop3D::Wireframe);
vtkWorld->SetSelectable(false);
viewer.AddPuppet(*vtkWorld);
viewer.AddProp3D(*vtkWorld);
Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box);
vtkIron->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkIron);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron);
// Visualize Top Chamber
Vtk::DetectorChamber* vtkTop = new Vtk::DetectorChamber(top_chamber_box);
vtkTop->SetOpacity(0.5);
vtkTop->SetColor(0.2, 0.8, 0.2);
vtkTop->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkTop);
vtkTop->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkTop);
// Visualize Bottom Chamber
Vtk::DetectorChamber* vtkBottom = new Vtk::DetectorChamber(bottom_chamber_box);
vtkBottom->SetOpacity(0.5);
vtkBottom->SetColor(0.2, 0.8, 0.2);
vtkBottom->SetRepresentation(Vtk::Puppet::Surface);
viewer.AddPuppet(*vtkBottom);
vtkBottom->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkBottom);
// Use vtkSkyPlaneEmitterPrimary instead of EmitterPrimary
Vtk::vtkSkyPlaneEmitterPrimary* vtkEmitter = new Vtk::vtkSkyPlaneEmitterPrimary(*emitter);
vtkEmitter->SetSelectable(false);
viewer.AddPuppet(*vtkEmitter);
viewer.AddProp3D(*vtkEmitter);
// 3. Event Handling
AppState state = { &scene, &viewer, {} };

View File

@@ -41,12 +41,12 @@ BoxSolid::~BoxSolid() {
void BoxSolid::Update() {
ConnectionBlock blocker(m_UpdateConnection);
this->UpdateGeometry();
// Ensure base Puppet properties (color, opacity, etc) and transform are applied
this->Puppet::Update();
// Ensure base Prop3D properties (color, opacity, etc) and transform are applied
this->Prop3D::Update();
}
void BoxSolid::SyncFromVtk() {
this->Puppet::SyncFromVtk();
this->Prop3D::SyncFromVtk();
if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) {
if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) {
m_BoxContent->SetTransform(VtkToMatrix4f(mat));
@@ -60,14 +60,14 @@ void BoxSolid::UpdateGeometry() {
}
void BoxSolid::UpdateTransform() {
// Take transform from Puppet base (which uses GetContent() -> ContainerBox TRS)
this->Puppet::Update();
// Take transform from Prop3D base (which uses GetContent() -> ContainerBox TRS)
this->Prop3D::Update();
}
void BoxSolid::serialize_display(uLib::Archive::display_properties_archive &ar,
const unsigned int version) {
// Expose Geant solid properties and underlying Box/TRS properties
this->Puppet::serialize_display(ar, version);
this->Prop3D::serialize_display(ar, version);
if (m_BoxContent) {
ar & NVP("Box", *m_BoxContent);
if (m_BoxContent->GetObject()) {

View File

@@ -39,7 +39,7 @@ namespace uLib {
namespace Vtk {
/**
* @brief VTK Puppet for visualizing a Geant::BoxSolid.
* @brief VTK Prop3D for visualizing a Geant::BoxSolid.
*/
class BoxSolid : public GeantSolid {
uLibTypeMacro(BoxSolid, uLib::Vtk::GeantSolid)

View File

@@ -63,7 +63,7 @@ void EmitterPrimary::contentUpdate() {
Matrix4f transform = m_emitter.GetWorldMatrix();
Matrix4fToVtk(transform, vmat);
Puppet::Update();
Prop3D::Update();
}
void EmitterPrimary::Update() {

View File

@@ -14,7 +14,7 @@ class vtkCylinderSource;
namespace uLib {
namespace Vtk {
class EmitterPrimary : public Puppet {
class EmitterPrimary : public Prop3D {
public:
EmitterPrimary(Geant::EmitterPrimary &emitter);
virtual ~EmitterPrimary();

View File

@@ -34,7 +34,7 @@
namespace uLib {
namespace Vtk {
class GeantEvent : public Puppet, public Polydata {
class GeantEvent : public Prop3D, public Polydata {
typedef Geant::GeantEvent Content;
public:

View File

@@ -33,19 +33,19 @@ namespace uLib {
namespace Vtk {
GeantScene::GeantScene(Geant::Scene *scene)
: m_Scene(scene), m_WorldPuppet(nullptr) {
: m_Scene(scene), m_WorldProp3D(nullptr) {
if (!m_Scene)
return;
// 1. Create the world box wireframe puppet
// 1. Create the world box wireframe prop3d
uLib::ContainerBox *worldBox = m_Scene->GetWorldBox();
if (worldBox) {
m_WorldPuppet = new ContainerBox(worldBox);
m_WorldPuppet->SetRepresentation(Puppet::Wireframe);
m_WorldPuppet->ShowScaleMeasures(true);
m_WorldProp3D = new ContainerBox(worldBox);
m_WorldProp3D->SetRepresentation(Prop3D::Wireframe);
m_WorldProp3D->ShowScaleMeasures(true);
}
// 2. Create puppets for each non-world solid
// 2. Create prop3ds for each non-world solid
const Geant::Solid *world = m_Scene->GetWorld();
const Vector<Geant::Solid *> &solids = m_Scene->GetSolids();
@@ -54,7 +54,7 @@ GeantScene::GeantScene(Geant::Scene *scene)
if (solid == world)
continue;
// Only create a puppet if the solid has a valid G4VSolid
// Only create a prop3d if the solid has a valid G4VSolid
if (solid->GetG4Solid()) {
GeantSolid *vtkSolid = nullptr;
if (auto *box = dynamic_cast<Geant::BoxSolid *>(solid)) {
@@ -67,34 +67,34 @@ GeantScene::GeantScene(Geant::Scene *scene)
}
if (vtkSolid) {
m_SolidPuppets.push_back(vtkSolid);
m_SolidProp3Ds.push_back(vtkSolid);
}
}
}
}
GeantScene::~GeantScene() {
delete m_WorldPuppet;
for (auto *p : m_SolidPuppets) {
delete m_WorldProp3D;
for (auto *p : m_SolidProp3Ds) {
delete p;
}
}
void GeantScene::AddToViewer(Viewport &viewer) {
if (m_WorldPuppet) {
viewer.AddPuppet(*m_WorldPuppet);
if (m_WorldProp3D) {
viewer.AddProp3D(*m_WorldProp3D);
}
for (auto *p : m_SolidPuppets) {
viewer.AddPuppet(*p);
for (auto *p : m_SolidProp3Ds) {
viewer.AddProp3D(*p);
}
}
void GeantScene::RemoveFromViewer(Viewport &viewer) {
if (m_WorldPuppet) {
viewer.RemovePuppet(*m_WorldPuppet);
if (m_WorldProp3D) {
viewer.RemoveProp3D(*m_WorldProp3D);
}
for (auto *p : m_SolidPuppets) {
viewer.RemovePuppet(*p);
for (auto *p : m_SolidProp3Ds) {
viewer.RemoveProp3D(*p);
}
}

View File

@@ -39,9 +39,9 @@ namespace Vtk {
class GeantSolid;
/**
* @brief VTK Puppet representing the entire Geant::Scene.
* @brief VTK Prop3D representing the entire Geant::Scene.
*
* When constructed, it creates child puppets for the world box (as a
* When constructed, it creates child prop3ds for the world box (as a
* ContainerBox wireframe) and for each non-world Solid in the scene
* (as GeantSolid surfaces).
*
@@ -63,22 +63,22 @@ public:
GeantScene(Geant::Scene *scene);
~GeantScene();
/// Add all puppets (world box + solids) to a viewer.
/// Add all prop3ds (world box + solids) to a viewer.
void AddToViewer(class Viewport &viewer);
/// Remove all puppets from viewport.
/// Remove all prop3ds from viewport.
void RemoveFromViewer(class Viewport &viewer);
/// Get the world box puppet
ContainerBox* GetWorldPuppet() const { return m_WorldPuppet; }
/// Get the world box prop3d
ContainerBox* GetWorldProp3D() const { return m_WorldProp3D; }
/// Get the solid puppets
const std::vector<GeantSolid*>& GetSolidPuppets() const { return m_SolidPuppets; }
/// Get the solid prop3ds
const std::vector<GeantSolid*>& GetSolidProp3Ds() const { return m_SolidProp3Ds; }
private:
Geant::Scene *m_Scene;
ContainerBox *m_WorldPuppet;
std::vector<GeantSolid*> m_SolidPuppets;
ContainerBox *m_WorldProp3D;
std::vector<GeantSolid*> m_SolidProp3Ds;
};
} // namespace Vtk

View File

@@ -36,13 +36,13 @@ namespace uLib {
namespace Vtk {
/**
* @brief VTK Puppet for visualizing a Geant::Solid.
* @brief VTK Prop3D for visualizing a Geant::Solid.
*
* Renders the G4VSolid geometry as a tessellated polydata surface.
* Works with BoxSolid, TessellatedSolid, or any Solid that provides
* a valid G4VSolid via GetG4Solid().
*/
class GeantSolid : public Puppet, public Polydata {
class GeantSolid : public Prop3D, public Polydata {
typedef Geant::Solid Content;
public:

View File

@@ -18,7 +18,7 @@ namespace uLib {
namespace Vtk {
/**
* @brief VTK Puppet for visualizing a Geant::TessellatedSolid.
* @brief VTK Prop3D for visualizing a Geant::TessellatedSolid.
*/
class TessellatedSolid : public GeantSolid {
public:

View File

@@ -110,12 +110,12 @@ BOOST_AUTO_TEST_CASE(vtkVoxRaytracerRepresentationTest) {
// renderer //
Vtk::Viewer viewer;
viewer.AddPuppet(v_grid);
viewer.AddPuppet(v_rt);
viewer.AddPuppet(v_muon);
viewer.AddProp3D(v_grid);
viewer.AddProp3D(v_rt);
viewer.AddProp3D(v_muon);
// Select grid to show handler widget
viewer.SelectPuppet(&v_grid);
viewer.SelectProp3D(&v_grid);
viewer.Start();
}

View File

@@ -58,7 +58,7 @@ class vtkActor;
namespace uLib {
namespace Vtk {
class VoxRaytracerRepresentation : public Puppet {
class VoxRaytracerRepresentation : public Prop3D {
typedef VoxRaytracer Content;
public:

View File

@@ -50,18 +50,18 @@ int main(int argc, char **argv) {
// ---- 3. Apply a group transform ----
assembly.SetPosition(Vector3f(1_m, 1_m, 0));
// ---- 5. Visualize (create puppets to set properties) ----
// ---- 5. Visualize (create prop3ds to set properties) ----
Vtk::Assembly vtkAsm(&assembly);
Vtk::Viewer viewer;
vtkAsm.AddToViewer(viewer); // This triggers puppet creation via ConnectRenderer which eventually calls Puppet::GetProp
vtkAsm.AddToViewer(viewer); // This triggers prop3d creation via ConnectRenderer which eventually calls Prop3D::GetProp
// Explicitly update to ensure puppets exist and are added to assemblies
// Explicitly update to ensure prop3ds exist and are added to assemblies
vtkAsm.Update();
// Use the child context to find child puppets and set colors
// Use the child context to find child prop3ds and set colors
if (auto* childCtx = vtkAsm.GetChildrenContext()) {
auto setProps = [](Vtk::Puppet* p, float r, float g, float b) {
auto setProps = [](Vtk::Prop3D* p, float r, float g, float b) {
if (!p) return;
vtkPropCollection* props = p->GetProps();
props->InitTraversal();
@@ -74,12 +74,12 @@ int main(int argc, char **argv) {
}
};
setProps(childCtx->GetPuppet(&box1), 1.0, 0.0, 0.0); // Red
setProps(childCtx->GetPuppet(&box2), 0.0, 1.0, 0.0); // Green
setProps(childCtx->GetPuppet(&cyl), 0.0, 0.0, 1.0); // Blue
setProps(childCtx->GetProp3D(&box1), 1.0, 0.0, 0.0); // Red
setProps(childCtx->GetProp3D(&box2), 0.0, 1.0, 0.0); // Green
setProps(childCtx->GetProp3D(&cyl), 0.0, 0.0, 1.0); // Blue
}
std::cout << "Puppets in viewport: " << viewer.getPuppets().size() << " (Expected 4: 1 assembly + 3 children)" << std::endl;
std::cout << "Prop3Ds in viewport: " << viewer.getProp3Ds().size() << " (Expected 4: 1 assembly + 3 children)" << std::endl;
// ---- 4. Query the bounding box for terminal output ----
Vector3f bbMin, bbMax;

View File

@@ -43,7 +43,7 @@ int main() {
Vtk::ContainerBox v_box(&box);
v_box.Update();
// v_box.SetRepresentation(Vtk::Puppet::Surface);
// v_box.SetRepresentation(Vtk::Prop3D::Surface);
// v_box.SetOpacity(0.5);
// v_box.SetSelectable(true);
@@ -53,7 +53,7 @@ int main() {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer v_viewer;
v_viewer.AddPuppet(v_box);
v_viewer.AddProp3D(v_box);
v_viewer.Start();
}

View File

@@ -20,7 +20,7 @@ int main() {
std::cout << "Creating VTK representation..." << std::endl;
Vtk::ContainerBox v_box(&box);
v_box.SetRepresentation(Vtk::Puppet::Wireframe);
v_box.SetRepresentation(Vtk::Prop3D::Wireframe);
v_box.SetColor(1.0, 0.0, 0.0); // Red
// // 1. Initial Visualization setup (handled by Viewer)
@@ -38,7 +38,7 @@ int main() {
std::cout << "Starting viewer (close window to exit)..." << std::endl;
Vtk::Viewer viewer;
viewer.AddPuppet(v_box);
viewer.AddProp3D(v_box);
viewer.Start();
return 0;

View File

@@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(vtkQuadMeshConstruction) {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.AddPuppet(v_mesh);
viewer.AddProp3D(v_mesh);
viewer.Start();
}

View File

@@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(vtkStructuredGridTest) {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.AddPuppet(grid_viewer);
viewer.AddProp3D(grid_viewer);
viewer.Start();
}

View File

@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(vtkTriangleMeshConstruction) {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.AddPuppet(v_mesh);
viewer.AddProp3D(v_mesh);
viewer.Start();
}
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(vtkTriangleMeshConstruction2) {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.AddPuppet(v_mesh);
viewer.AddProp3D(v_mesh);
viewer.Start();
}

View File

@@ -35,12 +35,12 @@ void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void
std::string key = interactor->GetKeySym();
if (key == "w") {
std::cout << "--> Switching all images to Wireframe Box" << std::endl;
for (auto* img : state->images) img->SetRepresentation(Vtk::Puppet::Wireframe);
for (auto* img : state->images) img->SetRepresentation(Vtk::Prop3D::Wireframe);
state->viewer->GetRenderWindow()->Render();
}
else if (key == "s") {
std::cout << "--> Switching all images to Surface (Volume Rendering)" << std::endl;
for (auto* img : state->images) img->SetRepresentation(Vtk::Puppet::Surface);
for (auto* img : state->images) img->SetRepresentation(Vtk::Prop3D::Surface);
state->viewer->GetRenderWindow()->Render();
}
else if (key >= "0" && key <= "5") {
@@ -104,8 +104,8 @@ int main(int argc, char** argv) {
Vtk::Viewer viewer;
viewer.GetRenderer()->SetBackground(0.05, 0.05, 0.1);
viewer.AddPuppet(vtk_img1);
viewer.AddPuppet(vtk_img2);
viewer.AddProp3D(vtk_img1);
viewer.AddProp3D(vtk_img2);
// Setup KeyPress Callback
AppState state;

View File

@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(vtkVoxImageConstruction) {
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer viewer;
viewer.AddPuppet(vtk_img);
viewer.AddProp3D(vtk_img);
viewer.Start();
}

View File

@@ -75,7 +75,7 @@ void Assembly::InstallPipe() {
m_VtkAsm->AddPart(m_BBoxActor);
// 3. Build a child-objects context (auto-creates puppets for each child)
// 3. Build a child-objects context (auto-creates prop3ds for each child)
if (m_Content) {
m_ChildContext = new ObjectsContext(m_Content);
// Link the children context's assembly into our group assembly
@@ -101,7 +101,7 @@ void Assembly::Update() {
m_VtkAsm->Modified();
}
this->Puppet::Update();
this->Prop3D::Update();
this->UpdateBoundingBox();
if (m_ChildContext)
m_ChildContext->Update();

View File

@@ -24,19 +24,19 @@ namespace Vtk {
class ObjectsContext; // forward
/**
* @brief VTK Puppet for visualizing uLib::Assembly.
* @brief VTK Prop3D for visualizing uLib::Assembly.
*
* Manages a VTK assembly (vtkAssembly from the VTK library) that groups
* all child puppets and applies the Assembly's AffineTransform. It also
* all child prop3ds and applies the Assembly's AffineTransform. It also
* renders an optional bounding box wireframe computed from the Assembly's AABB.
*
* @note This class is uLib::Vtk::Assembly. It internally uses
* the VTK library class vtkAssembly for grouping, but the two
* are distinct.
*/
class Assembly : public Puppet {
class Assembly : public Prop3D {
public:
uLibTypeMacro(Assembly, Puppet)
uLibTypeMacro(Assembly, Prop3D)
Assembly(uLib::Assembly *content);
virtual ~Assembly();
@@ -51,10 +51,10 @@ public:
virtual uLib::ObjectsContext* GetChildren() override { return (uLib::ObjectsContext*)m_Content; }
/**
* @brief Returns the puppet managing child objects.
* @brief Returns the prop3d managing child objects.
*/
/** @brief Returns the puppet managing child objects. */
/** @brief Returns the prop3d managing child objects. */
ObjectsContext *GetChildrenContext() const;
private:

View File

@@ -96,7 +96,7 @@ void ContainerBox::Update() {
// Delegate rest of update (appearance, render, etc)
ConnectionBlock blocker(d->m_UpdateSignal);
this->Puppet::Update();
this->Prop3D::Update();
}
@@ -166,7 +166,7 @@ void ContainerBox::InstallPipe() {
// vtkProp3D* root = d->m_VtkAsm;
// if (root) {
// this->ApplyPuppetTransform(root);
// this->ApplyProp3DTransform(root);
// }
this->Update();
}

View File

@@ -37,9 +37,9 @@ namespace Vtk {
struct ContainerBoxData;
class ContainerBox : public Puppet, public Polydata {
class ContainerBox : public Prop3D, public Polydata {
uLibTypeMacro(ContainerBox, Puppet, Polydata)
uLibTypeMacro(ContainerBox, Prop3D, Polydata)
typedef uLib::ContainerBox Content;
public:

View File

@@ -82,7 +82,7 @@ void Cylinder::Update() {
// Delegate rest of update (appearance, render, etc)
ConnectionBlock blocker(m_UpdateSignal);
this->Puppet::Update();
this->Prop3D::Update();
}
void Cylinder::SyncFromVtk() {

View File

@@ -41,7 +41,7 @@ namespace Vtk {
* mathematical state of a Cylinder object. It manages the alignment
* between VTK's Y-centered cylinder and uLib's Z-based coordinate system.
*/
class Cylinder : public Puppet {
class Cylinder : public Prop3D {
typedef uLib::Cylinder Content;
public:

View File

@@ -125,7 +125,7 @@ void QuadMesh::contentUpdate() {
m_Poly->Modified();
m_Actor->GetMapper()->Update();
Puppet::Update();
Prop3D::Update();
}
void QuadMesh::Update() {

View File

@@ -36,7 +36,7 @@ class vtkActor;
namespace uLib {
namespace Vtk {
class QuadMesh : public Puppet, public Polydata {
class QuadMesh : public Prop3D, public Polydata {
typedef uLib::QuadMesh Content;
public:

View File

@@ -47,7 +47,7 @@
namespace uLib {
namespace Vtk {
class StructuredGrid : public Puppet {
class StructuredGrid : public Prop3D {
typedef uLib::StructuredGrid Content;
public:

View File

@@ -120,7 +120,7 @@ void TriangleMesh::contentUpdate() {
m_Poly->Modified();
m_Actor->GetMapper()->Update();
Puppet::Update();
Prop3D::Update();
}
void TriangleMesh::Update() {

View File

@@ -36,7 +36,7 @@ class vtkActor;
namespace uLib {
namespace Vtk {
class TriangleMesh : public Puppet, public Polydata {
class TriangleMesh : public Prop3D, public Polydata {
typedef uLib::TriangleMesh Content;
public:

View File

@@ -281,7 +281,7 @@ void VoxImage::RescaleShaderRange() {
}
void VoxImage::SetRepresentation(Representation mode) {
Puppet::SetRepresentation(mode); // Ensure base class data state is updated
Prop3D::SetRepresentation(mode); // Ensure base class data state is updated
if (mode == Wireframe) {
m_Actor->SetVisibility(0);
@@ -292,14 +292,14 @@ void VoxImage::SetRepresentation(Representation mode) {
m_OutlineActor->SetVisibility(1);
m_OutlineActor->GetProperty()->SetRepresentationToWireframe();
} else {
// Other representations (Points, Surface, etc) are handled by basic Puppet
// Other representations (Points, Surface, etc) are handled by basic Prop3D
// behavior which affects the m_Asm parts.
}
}
void VoxImage::serialize_display(uLib::Archive::display_properties_archive & ar, const unsigned int version) {
// Call base class to show Transform and Appearance properties
// Puppet::serialize_display(ar, version);
// Prop3D::serialize_display(ar, version);
// Use the member variables for volume rendering parameters
ar & boost::serialization::make_hrp("Window", m_Window);
@@ -335,7 +335,7 @@ void VoxImage::Update() {
m_Outline->Update();
ConnectionBlock blocker(m_UpdateConnection);
this->Puppet::Update();
this->Prop3D::Update();
}

View File

@@ -45,7 +45,7 @@ class vtkPiecewiseFunction;
namespace uLib {
namespace Vtk {
class VoxImage : public Puppet {
class VoxImage : public Prop3D {
public:
typedef Abstract::VoxImage Content;

View File

@@ -2,8 +2,8 @@
set(TESTS
vtkViewerTest
vtkHandlerWidget
PuppetPropertyTest
PuppetParentingTest
Prop3DPropertyTest
Prop3DParentingTest
vtkQViewportTest
# vtkVoxImageTest
# vtkTriangleMeshTest

View File

@@ -26,13 +26,13 @@
using namespace uLib;
int main() {
BEGIN_TESTING(Puppet Parenting Test);
BEGIN_TESTING(Prop3D Parenting Test);
ObjectsContext globalContext;
Vtk::Viewer viewer;
// Create the display context, linked to the model context.
// It will automatically create visual puppets for each model object.
// It will automatically create visual prop3ds for each model object.
Vtk::ObjectsContext viewerContext(&globalContext);
viewerContext.ConnectRenderer(viewer.GetRenderer());
@@ -41,12 +41,12 @@ int main() {
assembly->SetInstanceName("ParentAssembly");
globalContext.AddObject(assembly);
// Verify assembly puppet exists in the viewer context
Vtk::Puppet* assemblyPuppet = viewerContext.GetPuppet(assembly);
ASSERT_NOT_NULL(assemblyPuppet);
// Verify assembly prop3d exists in the viewer context
Vtk::Prop3D* assemblyProp3D = viewerContext.GetProp3D(assembly);
ASSERT_NOT_NULL(assemblyProp3D);
// cast to Vtk::Assembly to access child context
auto* vtkAss = dynamic_cast<Vtk::Assembly*>(assemblyPuppet);
auto* vtkAss = dynamic_cast<Vtk::Assembly*>(assemblyProp3D);
ASSERT_NOT_NULL(vtkAss);
// 2. Create a child Box and add it to the Assembly
@@ -55,25 +55,25 @@ int main() {
box1->SetPosition(Vector3f(20, 0, 0));
assembly->AddObject(box1);
// Verify child puppet was created in the assembly's child context
// Verify child prop3d was created in the assembly's child context
Vtk::ObjectsContext* childVtkCtx = vtkAss->GetChildrenContext();
ASSERT_NOT_NULL(childVtkCtx);
Vtk::Puppet* box1Puppet = childVtkCtx->GetPuppet(box1);
ASSERT_NOT_NULL(box1Puppet);
Vtk::Prop3D* box1Prop3D = childVtkCtx->GetProp3D(box1);
ASSERT_NOT_NULL(box1Prop3D);
// 3. Move the parent and verify the child follows
assembly->SetPosition(Vector3f(100, 0, 0));
assembly->Updated();
// In VTK assemblies, the child's absolute matrix should reflect the parent's transform
vtkProp3D* box1Prop = vtkProp3D::SafeDownCast(box1Puppet->GetProp());
vtkProp3D* box1Prop = vtkProp3D::SafeDownCast(box1Prop3D->GetProp());
ASSERT_NOT_NULL(box1Prop);
vtkMatrix4x4* boxMatrix = box1Prop->GetMatrix();
// Origin (0,0,0) + local(20,0,0) + assembly(100,0,0) = world(120,0,0) ?
// Actually, box1->GetPosition() is (20,0,0).
// The puppet ApplyTransform sets the prop orientation and position.
// The prop3d ApplyTransform sets the prop orientation and position.
std::cout << "Checking transformation chain..." << std::endl;
// std::cout << *boxMatrix << std::endl;
@@ -93,8 +93,8 @@ int main() {
box2->SetPosition(Vector3f(-20, 0, 0));
assembly->AddObject(box2);
Vtk::Puppet* box2Puppet = childVtkCtx->GetPuppet(box2);
ASSERT_NOT_NULL(box2Puppet);
Vtk::Prop3D* box2Prop3D = childVtkCtx->GetProp3D(box2);
ASSERT_NOT_NULL(box2Prop3D);
// Render if not in batch environment
if (!std::getenv("CTEST_PROJECT_NAME")) {

View File

@@ -19,13 +19,13 @@ using namespace uLib;
using namespace Vtk;
int main() {
BEGIN_TESTING(Puppet Property Registration Test);
BEGIN_TESTING(Prop3D Property Registration Test);
std::cout << "Creating Puppet object..." << std::endl;
Puppet p;
std::cout << "Creating Prop3D object..." << std::endl;
Prop3D p;
// At this point, the Puppet constructor has called ULIB_ACTIVATE_PROPERTIES.
// This should have discovered the members used in Puppet::serialize()
// At this point, the Prop3D constructor has called ULIB_ACTIVATE_PROPERTIES.
// This should have discovered the members used in Prop3D::serialize()
// and registered them as uLib properties.
const auto& props = p.GetProperties();
@@ -62,7 +62,7 @@ int main() {
*colorRProp = 0.9;
assert(colorRProp->Get() == 0.9);
std::cout << "All Puppet Property Registration Tests PASSED!" << std::endl;
std::cout << "All Prop3D Property Registration Tests PASSED!" << std::endl;
END_TESTING;
}

View File

@@ -49,12 +49,12 @@ int main() {
// 3. Setup the Viewer
Vtk::Viewer viewer;
// 2. Wrap it in a Vtk::ContainerBox (Vtk Puppet)
// 2. Wrap it in a Vtk::ContainerBox (Vtk Prop3D)
Vtk::ContainerBox v_box(&box);
v_box.SetRepresentation(Vtk::Puppet::Surface);
v_box.SetRepresentation(Vtk::Prop3D::Surface);
v_box.SetOpacity(0.5);
viewer.AddPuppet(v_box);
viewer.AddProp3D(v_box);
// 4. Create and setup the HandlerWidget
vtkSmartPointer<Vtk::HandlerWidget> handler =
@@ -62,7 +62,7 @@ int main() {
handler->SetInteractor(viewer.GetInteractor());
// Get the prop from the puppet and cast it to vtkProp3D
// Get the prop from the prop3d and cast it to vtkProp3D
vtkProp *v_prop = v_box.GetProp();
vtkProp3D *prop = vtkProp3D::SafeDownCast(v_prop);
if (!prop) {

View File

@@ -80,15 +80,15 @@ namespace Vtk {
// PIMPL -------------------------------------------------------------------- //
class PuppetData {
class Prop3DData {
public:
PuppetData(Puppet* owner) :
m_Puppet(owner),
Prop3DData(Prop3D* owner) :
m_Prop3D(owner),
m_Renderers(vtkSmartPointer<vtkRendererCollection>::New()),
m_Prop(nullptr),
m_ShowBoundingBox(false),
m_ShowScaleMeasures(false),
m_Representation(Puppet::Surface),
m_Representation(Prop3D::Surface),
m_Opacity(1.0),
m_Selectable(true),
m_Selected(false),
@@ -98,12 +98,12 @@ public:
m_Color = Vector3d(-1, -1, -1);
}
~PuppetData() {
~Prop3DData() {
// No manual Delete needed for smart pointers
}
Puppet *m_Puppet;
Prop3D *m_Prop3D;
// members //
vtkSmartPointer<vtkRendererCollection> m_Renderers;
vtkSmartPointer<vtkProp3D> m_Prop;
@@ -136,11 +136,11 @@ public:
vtkActor *actor = vtkActor::SafeDownCast(p);
if (actor) {
if (m_Representation != -1 && m_Representation != Puppet::Volume) {
if (m_Representation == Puppet::SurfaceWithEdges) {
if (m_Representation != -1 && m_Representation != Prop3D::Volume) {
if (m_Representation == Prop3D::SurfaceWithEdges) {
actor->GetProperty()->SetRepresentation(VTK_SURFACE);
actor->GetProperty()->SetEdgeVisibility(1);
} else if (m_Representation != Puppet::Outline && m_Representation != Puppet::Slice) {
} else if (m_Representation != Prop3D::Outline && m_Representation != Prop3D::Slice) {
actor->GetProperty()->SetRepresentation(m_Representation);
actor->GetProperty()->SetEdgeVisibility(0);
}
@@ -248,8 +248,8 @@ public:
}
// Update highlight matrix from the model world matrix
if (m_Puppet) {
if (auto* content = m_Puppet->GetContent()) {
if (m_Prop3D) {
if (auto* content = m_Prop3D->GetContent()) {
if (auto* tr = dynamic_cast<uLib::TRS*>(content)) {
vtkNew<vtkMatrix4x4> vwm;
Matrix4fToVtk(tr->GetWorldMatrix(), vwm);
@@ -288,24 +288,24 @@ public:
Puppet::Puppet() : Object(), pd(new PuppetData(this)) {
Prop3D::Prop3D() : Object(), pd(new Prop3DData(this)) {
ULIB_ACTIVATE_DISPLAY_PROPERTIES;
for (auto* p : this->GetDisplayProperties()) {
uLib::Object::connect(p, &uLib::PropertyBase::Updated, this, &Puppet::Update);
uLib::Object::connect(p, &uLib::PropertyBase::Updated, this, &Prop3D::Update);
}
}
Puppet::~Puppet()
Prop3D::~Prop3D()
{
delete pd;
}
vtkProp *Puppet::GetProp()
vtkProp *Prop3D::GetProp()
{
return pd->m_Prop;
}
vtkProp3D *Puppet::GetProxyProp()
vtkProp3D *Prop3D::GetProxyProp()
{
// The handler should manipulate the highlight actor if it exists
if (pd->m_HighlightActor) {
@@ -314,7 +314,7 @@ vtkProp3D *Puppet::GetProxyProp()
return vtkProp3D::SafeDownCast(this->GetProp());
}
void Puppet::SetProp(vtkProp *prop)
void Prop3D::SetProp(vtkProp *prop)
{
if(prop) {
prop->SetPickable(pd->m_Selectable);
@@ -339,23 +339,23 @@ void Puppet::SetProp(vtkProp *prop)
}
}
void Puppet::RemoveProp(vtkProp *prop)
void Prop3D::RemoveProp(vtkProp *prop)
{
// TODO
}
void Puppet::ApplyAppearance(vtkProp* prop)
void Prop3D::ApplyAppearance(vtkProp* prop)
{
pd->ApplyAppearance(prop);
}
void Puppet::ApplyTransform(vtkProp3D* p3d)
void Prop3D::ApplyTransform(vtkProp3D* p3d)
{
pd->ApplyTransform(p3d);
}
vtkPropCollection *Puppet::GetParts()
vtkPropCollection *Prop3D::GetParts()
{
if (auto* asm_p = vtkAssembly::SafeDownCast(pd->m_Prop)) {
return asm_p->GetParts();
@@ -363,7 +363,7 @@ vtkPropCollection *Puppet::GetParts()
return nullptr;
}
vtkPropCollection *Puppet::GetProps()
vtkPropCollection *Prop3D::GetProps()
{
if (auto* asm_p = vtkAssembly::SafeDownCast(pd->m_Prop)) {
return asm_p->GetParts();
@@ -371,7 +371,7 @@ vtkPropCollection *Puppet::GetProps()
return nullptr;
}
void Puppet::ConnectRenderer(vtkRenderer *renderer)
void Prop3D::ConnectRenderer(vtkRenderer *renderer)
{
if(renderer) {
this->GetRenderers()->AddItem(renderer);
@@ -391,7 +391,7 @@ void Puppet::ConnectRenderer(vtkRenderer *renderer)
}
}
void Puppet::DisconnectRenderer(vtkRenderer *renderer)
void Prop3D::DisconnectRenderer(vtkRenderer *renderer)
{
if(renderer) {
if(vtkProp* prop = this->GetProp())
@@ -404,22 +404,22 @@ void Puppet::DisconnectRenderer(vtkRenderer *renderer)
}
}
void Puppet::AddToViewer(Viewport &viewer)
void Prop3D::AddToViewer(Viewport &viewer)
{
viewer.AddPuppet(*this);
viewer.AddProp3D(*this);
}
void Puppet::RemoveFromViewer(Viewport &viewer)
void Prop3D::RemoveFromViewer(Viewport &viewer)
{
viewer.RemovePuppet(*this);
viewer.RemoveProp3D(*this);
}
vtkRendererCollection *Puppet::GetRenderers() const
vtkRendererCollection *Prop3D::GetRenderers() const
{
return pd->m_Renderers;
}
void Puppet::PrintSelf(std::ostream &o) const
void Prop3D::PrintSelf(std::ostream &o) const
{
o << "Props Assembly: \n";
if (pd->m_Prop)
@@ -429,7 +429,7 @@ void Puppet::PrintSelf(std::ostream &o) const
pd->m_Renderers->PrintSelf(o,vtkIndent(1));
}
void Puppet::ShowBoundingBox(bool show)
void Prop3D::ShowBoundingBox(bool show)
{
if (pd->m_ShowBoundingBox == show) return;
pd->m_ShowBoundingBox = show;
@@ -465,7 +465,7 @@ void Puppet::ShowBoundingBox(bool show)
}
}
void Puppet::ShowScaleMeasures(bool show)
void Prop3D::ShowScaleMeasures(bool show)
{
if (pd->m_ShowScaleMeasures == show) return;
pd->m_ShowScaleMeasures = show;
@@ -499,13 +499,13 @@ void Puppet::ShowScaleMeasures(bool show)
}
}
void Puppet::SetRepresentation(Representation mode)
void Prop3D::SetRepresentation(Representation mode)
{
pd->m_Representation = static_cast<int>(mode);
pd->ApplyAppearance(pd->m_Prop);
}
void Puppet::SetRepresentation(const char *mode)
void Prop3D::SetRepresentation(const char *mode)
{
std::string s(mode);
if (s == "points") SetRepresentation(Points);
@@ -517,7 +517,7 @@ void Puppet::SetRepresentation(const char *mode)
else if (s == "slice") SetRepresentation(Slice);
}
void Puppet::SetColor(double r, double g, double b)
void Prop3D::SetColor(double r, double g, double b)
{
pd->m_Color[0] = r;
pd->m_Color[1] = g;
@@ -525,7 +525,7 @@ void Puppet::SetColor(double r, double g, double b)
pd->ApplyAppearance(pd->m_Prop);
}
void Puppet::SetOpacity(double alpha)
void Prop3D::SetOpacity(double alpha)
{
pd->m_Opacity = alpha;
pd->ApplyAppearance(pd->m_Prop);
@@ -537,18 +537,18 @@ void Puppet::SetOpacity(double alpha)
void Puppet::SetSelectable(bool selectable)
void Prop3D::SetSelectable(bool selectable)
{
pd->m_Selectable = selectable;
pd->ApplyAppearance(pd->m_Prop);
}
bool Puppet::IsSelectable() const
bool Prop3D::IsSelectable() const
{
return pd->m_Selectable;
}
void Puppet::SetSelected(bool selected)
void Prop3D::SetSelected(bool selected)
{
if (!pd->m_Selectable) return;
if (pd->m_Selected == selected) return;
@@ -556,12 +556,12 @@ void Puppet::SetSelected(bool selected)
pd->UpdateHighlight();
}
bool Puppet::IsSelected() const
bool Prop3D::IsSelected() const
{
return pd->m_Selected;
}
void Puppet::ApplyPuppetTransform(vtkProp3D* prop)
void Prop3D::ApplyProp3DTransform(vtkProp3D* prop)
{
if (!prop) return;
if (auto* content = this->GetContent()) {
@@ -574,7 +574,7 @@ void Puppet::ApplyPuppetTransform(vtkProp3D* prop)
}
}
void Puppet::SyncFromVtk()
void Prop3D::SyncFromVtk()
{
if (auto* content = this->GetContent()) {
if (auto* tr = dynamic_cast<uLib::TRS*>(content)) {
@@ -588,11 +588,11 @@ void Puppet::SyncFromVtk()
}
}
void Puppet::Update()
void Prop3D::Update()
{
// Apply content transform via virtual GetProp() / ApplyPuppetTransform(),
// Apply content transform via virtual GetProp() / ApplyProp3DTransform(),
// so all derived classes benefit without duplicating the matrix code.
this->ApplyPuppetTransform(vtkProp3D::SafeDownCast(this->GetProp()));
this->ApplyProp3DTransform(vtkProp3D::SafeDownCast(this->GetProp()));
// Use virtual GetProp() for appearance so overriders (e.g. VoxImage)
// that never call SetProp() are handled correctly.
@@ -626,8 +626,7 @@ void Puppet::Update()
}
void Puppet::ConnectInteractor(vtkRenderWindowInteractor *interactor)
void Prop3D::ConnectInteractor(vtkRenderWindowInteractor *interactor)
{
}
@@ -639,7 +638,7 @@ void Puppet::ConnectInteractor(vtkRenderWindowInteractor *interactor)
struct TransformProxy {
PuppetData* pd;
Prop3DData* pd;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("Transform", pd->m_Transform);
@@ -647,7 +646,7 @@ struct TransformProxy {
};
struct AppearanceProxy {
PuppetData* pd;
Prop3DData* pd;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & boost::serialization::make_hrp("Color", pd->m_Color, "color");
@@ -662,7 +661,7 @@ struct AppearanceProxy {
}
};
void Puppet::serialize_display(Archive::display_properties_archive & ar, const unsigned int version) {
void Prop3D::serialize_display(Archive::display_properties_archive & ar, const unsigned int version) {
AppearanceProxy appearance{pd};
ar & boost::serialization::make_nvp("Appearance", appearance);

View File

@@ -52,7 +52,7 @@ namespace Archive {
class display_properties_archive;
}
namespace Vtk {
class Puppet;
class Prop3D;
class Viewer;
} // namespace Vtk
} // namespace uLib
@@ -60,13 +60,13 @@ class Viewer;
namespace uLib {
namespace Vtk {
class Puppet : public uLib::Object {
class Prop3D : public uLib::Object {
uLibTypeMacro(Puppet, uLib::Object)
uLibTypeMacro(Prop3D, uLib::Object)
public:
Puppet();
virtual ~Puppet();
Prop3D();
virtual ~Prop3D();
virtual vtkProp *GetProp();
virtual vtkProp3D *GetProxyProp();
@@ -152,17 +152,17 @@ protected:
virtual void ApplyAppearance(vtkProp *prop);
virtual void ApplyTransform(vtkProp3D *p3d);
virtual void ApplyPuppetTransform(vtkProp3D *p3d);
virtual void ApplyProp3DTransform(vtkProp3D *p3d);
std::vector<uLib::PropertyBase *> m_DisplayProperties;
mutable uLib::RecursiveMutex m_UpdateMutex;
private:
Puppet(const Puppet &) = delete;
Puppet &operator=(const Puppet &) = delete;
Prop3D(const Prop3D &) = delete;
Prop3D &operator=(const Prop3D &) = delete;
friend class PuppetData;
class PuppetData *pd;
friend class Prop3DData;
class Prop3DData *pd;
};
} // namespace Vtk
@@ -181,7 +181,7 @@ namespace Archive {
/**
* @brief Specialized archive for registering display-only properties in
* Puppets.
* Prop3Ds.
*/
class display_properties_archive
: public boost::archive::detail::common_oarchive<
@@ -191,10 +191,10 @@ public:
friend class boost::archive::save_access;
using boost::archive::detail::common_oarchive<display_properties_archive>::save_override;
display_properties_archive(Vtk::Puppet *p)
display_properties_archive(Vtk::Prop3D *p)
: boost::archive::detail::common_oarchive<display_properties_archive>(
boost::archive::no_header),
m_Puppet(p) {
m_Prop3D(p) {
if (p)
m_Visited.insert(dynamic_cast<const void *>(p));
}
@@ -210,9 +210,9 @@ public:
}
template <class T> void save_override(const boost::serialization::hrp<T> &t) {
if (m_Puppet) {
if (m_Prop3D) {
uLib::Property<T> *p = new uLib::Property<T>(
m_Puppet, t.name(),
m_Prop3D, t.name(),
&const_cast<boost::serialization::hrp<T> &>(t).value(),
t.units() ? t.units() : "", GetCurrentGroup());
if (t.has_range())
@@ -220,24 +220,24 @@ public:
if (t.has_default())
p->SetDefault(t.default_val());
m_Puppet->RegisterDisplayProperty(p);
Vtk::Puppet *puppet = m_Puppet;
m_Prop3D->RegisterDisplayProperty(p);
Vtk::Prop3D *prop3d = m_Prop3D;
uLib::Object::connect(p, &uLib::PropertyBase::Updated,
[puppet]() { puppet->Update(); });
[prop3d]() { prop3d->Update(); });
}
}
template <class T>
void save_override(const boost::serialization::hrp_enum<T> &t) {
if (m_Puppet) {
if (m_Prop3D) {
uLib::EnumProperty *p = new uLib::EnumProperty(
m_Puppet, t.name(),
m_Prop3D, t.name(),
(int *)&const_cast<boost::serialization::hrp_enum<T> &>(t).value(),
t.labels(), t.units() ? t.units() : "", GetCurrentGroup());
m_Puppet->RegisterDisplayProperty(p);
Vtk::Puppet *puppet = m_Puppet;
m_Prop3D->RegisterDisplayProperty(p);
Vtk::Prop3D *prop3d = m_Prop3D;
uLib::Object::connect(p, &uLib::PropertyBase::Updated,
[puppet]() { puppet->Update(); });
[prop3d]() { prop3d->Update(); });
}
}
@@ -292,11 +292,11 @@ public:
// Called by Property<T>::serialize() and EnumProperty::serialize() to
// directly register an existing property object as a display property.
void register_property(uLib::PropertyBase &p) {
if (m_Puppet) {
m_Puppet->RegisterDisplayProperty(&p);
Vtk::Puppet *puppet = m_Puppet;
if (m_Prop3D) {
m_Prop3D->RegisterDisplayProperty(&p);
Vtk::Prop3D *prop3d = m_Prop3D;
uLib::Object::connect(&p, &uLib::PropertyBase::Updated,
[puppet]() { puppet->Update(); });
[prop3d]() { prop3d->Update(); });
}
}
@@ -305,14 +305,14 @@ public:
}
private:
Vtk::Puppet *m_Puppet;
Vtk::Prop3D *m_Prop3D;
std::vector<std::string> m_GroupStack;
std::set<const void *> m_Visited;
};
} // namespace Archive
// This macro MUST be defined after both Puppet and display_properties_archive
// This macro MUST be defined after both Prop3D and display_properties_archive
// are fully defined.
#define ULIB_ACTIVATE_DISPLAY_PROPERTIES \
{ \

View File

@@ -34,8 +34,8 @@ ObjectsContext::ObjectsContext(uLib::ObjectsContext *context)
}
ObjectsContext::~ObjectsContext() {
for (auto const& [obj, puppet] : m_Puppets) {
delete puppet;
for (auto const& [obj, prop3d] : m_Prop3Ds) {
delete prop3d;
}
m_Assembly->Delete();
}
@@ -48,31 +48,31 @@ void ObjectsContext::Synchronize() {
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(); ) {
// Remove Prop3Ds for objects no longer in context
for (auto it = m_Prop3Ds.begin(); it != m_Prop3Ds.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.
it->second->DisconnectRenderer(nullptr); // If we have a ref to a renderer we should disconnect but Prop3D doesn't store it easily
// Actually Prop3D::DisconnectRenderer(vtkRenderer*) needs the renderer.
// For now we just remove from assembly
if (auto* p3d = vtkProp3D::SafeDownCast(it->second->GetProp()))
m_Assembly->RemovePart(p3d);
this->PuppetRemoved(it->second);
this->Prop3DRemoved(it->second);
delete it->second;
it = m_Puppets.erase(it);
it = m_Prop3Ds.erase(it);
} else {
++it;
}
}
// Add puppets for new objects
// Add Prop3Ds 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;
if (auto* p3d = vtkProp3D::SafeDownCast(puppet->GetProp()))
if (m_Prop3Ds.find(obj) == m_Prop3Ds.end()) {
Prop3D* prop3d = this->CreateProp3D(obj);
if (prop3d) {
m_Prop3Ds[obj] = prop3d;
if (auto* p3d = vtkProp3D::SafeDownCast(prop3d->GetProp()))
m_Assembly->AddPart(p3d);
this->PuppetAdded(puppet);
this->Prop3DAdded(prop3d);
}
}
}
@@ -80,50 +80,50 @@ void ObjectsContext::Synchronize() {
void ObjectsContext::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;
if (auto* p3d = vtkProp3D::SafeDownCast(puppet->GetProp()))
if (m_Prop3Ds.find(obj) == m_Prop3Ds.end()) {
Prop3D* prop3d = this->CreateProp3D(obj);
if (prop3d) {
m_Prop3Ds[obj] = prop3d;
if (auto* p3d = vtkProp3D::SafeDownCast(prop3d->GetProp()))
m_Assembly->AddPart(p3d);
this->PuppetAdded(puppet);
this->Prop3DAdded(prop3d);
}
}
}
void ObjectsContext::OnObjectRemoved(uLib::Object* obj) {
if (!obj) return;
auto it = m_Puppets.find(obj);
if (it != m_Puppets.end()) {
auto it = m_Prop3Ds.find(obj);
if (it != m_Prop3Ds.end()) {
// For now we just remove from assembly.
// Puppet::DisconnectRenderer(vtkRenderer*) needs the renderer, but we don't have it here easily.
// Prop3D::DisconnectRenderer(vtkRenderer*) needs the renderer, but we don't have it here easily.
if (auto* p3d = vtkProp3D::SafeDownCast(it->second->GetProp()))
m_Assembly->RemovePart(p3d);
this->PuppetRemoved(it->second);
this->Prop3DRemoved(it->second);
delete it->second;
m_Puppets.erase(it);
m_Prop3Ds.erase(it);
}
}
Puppet* ObjectsContext::GetPuppet(uLib::Object* obj) {
auto it = m_Puppets.find(obj);
if (it != m_Puppets.end()) return it->second;
Prop3D* ObjectsContext::GetProp3D(uLib::Object* obj) {
auto it = m_Prop3Ds.find(obj);
if (it != m_Prop3Ds.end()) return it->second;
return nullptr;
}
void ObjectsContext::Update() {
for (auto const& [obj, puppet] : m_Puppets) {
puppet->Update();
for (auto const& [obj, prop3d] : m_Prop3Ds) {
prop3d->Update();
}
}
void ObjectsContext::SyncFromVtk() {
for (auto const& [obj, puppet] : m_Puppets) {
puppet->SyncFromVtk();
for (auto const& [obj, prop3d] : m_Prop3Ds) {
prop3d->SyncFromVtk();
}
}
Puppet* ObjectsContext::CreatePuppet(uLib::Object* obj) {
Prop3D* ObjectsContext::CreateProp3D(uLib::Object* obj) {
if (!obj) return nullptr;
if (auto* vox = dynamic_cast<uLib::Abstract::VoxImage*>(obj)) {
@@ -148,12 +148,12 @@ Puppet* ObjectsContext::CreatePuppet(uLib::Object* obj) {
return nullptr;
}
void ObjectsContext::PuppetAdded(Puppet* puppet) {
ULIB_SIGNAL_EMIT(ObjectsContext::PuppetAdded, puppet);
void ObjectsContext::Prop3DAdded(Prop3D* prop3d) {
ULIB_SIGNAL_EMIT(ObjectsContext::Prop3DAdded, prop3d);
}
void ObjectsContext::PuppetRemoved(Puppet* puppet) {
ULIB_SIGNAL_EMIT(ObjectsContext::PuppetRemoved, puppet);
void ObjectsContext::Prop3DRemoved(Prop3D* prop3d) {
ULIB_SIGNAL_EMIT(ObjectsContext::Prop3DRemoved, prop3d);
}
} // namespace Vtk

View File

@@ -11,31 +11,31 @@ namespace uLib {
namespace Vtk {
/**
* @brief ObjectsContext manages VTK representations (Puppets) for a collection of uLib::Objects.
* @brief ObjectsContext manages VTK representations (Prop3Ds) for a collection of uLib::Objects.
*/
class ObjectsContext : public Puppet {
class ObjectsContext : public Prop3D {
public:
uLibTypeMacro(ObjectsContext, Puppet)
uLibTypeMacro(ObjectsContext, Prop3D)
ObjectsContext(uLib::ObjectsContext *context);
virtual ~ObjectsContext();
/** @brief Synchronizes the VTK puppets with the core ObjectsContext. */
/** @brief Synchronizes the VTK prop3ds with the core ObjectsContext. */
void Synchronize();
/** @brief Returns the puppet associated with a specific core object. */
Puppet* GetPuppet(uLib::Object* obj);
/** @brief Returns the Prop3D associated with a specific core object. */
Prop3D* GetProp3D(uLib::Object* obj);
const std::map<uLib::Object*, Puppet*>& GetPuppets() const { return m_Puppets; }
const std::map<uLib::Object*, Prop3D*>& GetProp3Ds() const { return m_Prop3Ds; }
/** @brief Updates all managed puppets. */
/** @brief Updates all managed prop3ds. */
virtual void Update() override;
/** @brief Synchronizes all managed puppets back to their models. */
/** @brief Synchronizes all managed prop3ds back to their models. */
virtual void SyncFromVtk() override;
public:
virtual void PuppetAdded(Puppet* puppet);
virtual void PuppetRemoved(Puppet* puppet);
virtual void Prop3DAdded(Prop3D* prop3d);
virtual void Prop3DRemoved(Prop3D* prop3d);
public:
/** @brief Slot called when an object is added to the core context. */
@@ -44,12 +44,12 @@ public:
void OnObjectRemoved(uLib::Object* obj);
protected:
/** @brief Factory method to create a puppet for a core object. */
Puppet* CreatePuppet(uLib::Object* obj);
/** @brief Factory method to create a Prop3D for a core object. */
Prop3D* CreateProp3D(uLib::Object* obj);
private:
uLib::ObjectsContext *m_Context;
std::map<uLib::Object*, Puppet*> m_Puppets;
std::map<uLib::Object*, Prop3D*> m_Prop3Ds;
vtkAssembly *m_Assembly;
};

View File

@@ -136,9 +136,9 @@ void QViewport::onProjButtonClicked()
SetParallelProjection(m_ProjButton->isChecked());
}
void QViewport::OnSelectionChanged(Puppet* p)
void QViewport::OnSelectionChanged(Prop3D* p)
{
emit puppetSelected(p);
emit prop3dSelected(p);
}
void QViewport::resizeEvent(QResizeEvent* event)

View File

@@ -26,12 +26,12 @@ namespace Vtk {
/**
* QViewport is a self-contained Qt widget that embeds a VTK renderer
* directly into the Qt application (no separate VTK window).
* Puppets and actors are added to the embedded renderer.
* Prop3Ds and actors are added to the embedded renderer.
*/
class QViewport : public QWidget, public Viewport {
Q_OBJECT
signals:
void puppetSelected(uLib::Vtk::Puppet* p);
void prop3dSelected(uLib::Vtk::Prop3D* p);
public:
explicit QViewport(QWidget* parent = nullptr);
virtual ~QViewport();
@@ -44,7 +44,7 @@ public:
virtual vtkRenderWindowInteractor* GetInteractor() override;
QVTKOpenGLNativeWidget* GetWidget() { return m_VtkWidget; }
virtual void OnSelectionChanged(Puppet* p) override;
virtual void OnSelectionChanged(Prop3D* p) override;
protected:
virtual void resizeEvent(QResizeEvent* event) override;

View File

@@ -201,12 +201,12 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
pv->m_HandlerWidget->GetOverlayRenderer()->SetLayer(1);
}
// Observe InteractionEvent to update the selected puppet when the widget moves it
// Observe InteractionEvent to update the selected Prop3D when the widget moves it
vtkNew<vtkCallbackCommand> widgetInteractionCallback;
widgetInteractionCallback->SetClientData(this);
widgetInteractionCallback->SetCallback([](vtkObject*, unsigned long, void* clientdata, void*){
auto* self = static_cast<Viewport*>(clientdata);
for (auto* p : self->m_Puppets) {
for (auto* p : self->m_Prop3Ds) {
if (p->IsSelected()) {
p->SyncFromVtk();
}
@@ -246,29 +246,29 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
return false;
};
Puppet* target = nullptr;
Prop3D* target = nullptr;
if (picked) {
// 2. Find the leaf puppet: the one that contains 'picked' and is not a parent of another that also contains it.
// 2. Find the leaf Prop3D: the one that contains 'picked' and is not a parent of another that also contains it.
// Actually, we can just find all matches and pick the one with most 'nested' prop?
// A simpler way: we know 'picked' is the LEAF prop from VTK.
// Find a puppet that contains it.
Puppet* leafPuppet = nullptr;
for (auto* p : self->m_Puppets) {
// Find a Prop3D that contains it.
Prop3D* leafProp3D = nullptr;
for (auto* p : self->m_Prop3Ds) {
if (containsProp(p->GetProp(), picked)) {
// If we already have a candidate, check if this one is smaller (nested)
if (!leafPuppet || containsProp(leafPuppet->GetProp(), p->GetProp())) {
leafPuppet = p;
if (!leafProp3D || containsProp(leafProp3D->GetProp(), p->GetProp())) {
leafProp3D = p;
}
}
}
if (leafPuppet) {
target = leafPuppet;
if (leafProp3D) {
target = leafProp3D;
// 3. Model-driven hierarchy climb:
// If the leaf puppet has a uLib object, climb its parents.
// If any parent is an Assembly with GroupSelection=true, select the assembly puppet instead.
uLib::Object* currentObj = leafPuppet->GetContent();
// If the leaf Prop3D has a uLib object, climb its parents.
// If any parent is an Assembly with GroupSelection=true, select the assembly Prop3D instead.
uLib::Object* currentObj = leafProp3D->GetContent();
while (currentObj) {
// Object doesn't have parent, but AffineTransform does
@@ -279,9 +279,9 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
if (auto* parentAsm = dynamic_cast<::uLib::Assembly*>(parentObj)) {
if (parentAsm->GetGroupSelection()) {
// Find the puppet for this parent assembly
auto it = self->m_ObjectToPuppet.find(parentAsm);
if (it != self->m_ObjectToPuppet.end()) {
// Find the Prop3D for this parent assembly
auto it = self->m_ObjectToProp3D.find(parentAsm);
if (it != self->m_ObjectToProp3D.end()) {
target = it->second;
// Keep climbing to find even larger groups
}
@@ -291,7 +291,7 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
}
}
}
self->SelectPuppet(target);
self->SelectProp3D(target);
});
iren->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
@@ -388,8 +388,8 @@ void Viewport::ZoomSelected()
{
if (!pv->m_Renderer) return;
Puppet* selected = nullptr;
for (auto* p : m_Puppets) {
Prop3D* selected = nullptr;
for (auto* p : m_Prop3Ds) {
if (p->IsSelected()) {
selected = p;
break;
@@ -427,23 +427,23 @@ void Viewport::ZoomSelected()
this->Render();
}
void Viewport::AddPuppet(Puppet& prop)
void Viewport::AddProp3D(Prop3D& prop)
{
this->RegisterPuppet(&prop, false);
this->RegisterProp3D(&prop, false);
Render();
}
void Viewport::RemovePuppet(Puppet& prop)
void Viewport::RemoveProp3D(Prop3D& prop)
{
this->UnregisterPuppet(&prop);
this->UnregisterProp3D(&prop);
Render();
}
void Viewport::RegisterPuppet(Puppet* p, bool isPart) {
void Viewport::RegisterProp3D(Prop3D* p, bool isPart) {
if (!p) return;
if (std::find(m_Puppets.begin(), m_Puppets.end(), p) != m_Puppets.end()) return;
if (std::find(m_Prop3Ds.begin(), m_Prop3Ds.end(), p) != m_Prop3Ds.end()) return;
m_Puppets.push_back(p);
m_Prop3Ds.push_back(p);
p->ConnectRenderer(pv->m_Renderer);
// If it's a part of an assembly, we don't want to draw it twice.
@@ -461,19 +461,19 @@ void Viewport::RegisterPuppet(Puppet* p, bool isPart) {
this->ObserveContext(as->GetChildrenContext());
}
if (obj) m_ObjectToPuppet[obj] = p;
if (obj) m_ObjectToProp3D[obj] = p;
}
void Viewport::UnregisterPuppet(Puppet* p) {
void Viewport::UnregisterProp3D(Prop3D* p) {
if (!p) return;
if (p->IsSelected()) SelectPuppet(nullptr);
if (p->IsSelected()) SelectProp3D(nullptr);
auto it = std::find(m_Puppets.begin(), m_Puppets.end(), p);
if (it != m_Puppets.end()) m_Puppets.erase(it);
auto it = std::find(m_Prop3Ds.begin(), m_Prop3Ds.end(), p);
if (it != m_Prop3Ds.end()) m_Prop3Ds.erase(it);
// Remove from map
for (auto mapIt = m_ObjectToPuppet.begin(); mapIt != m_ObjectToPuppet.end(); ) {
if (mapIt->second == p) mapIt = m_ObjectToPuppet.erase(mapIt);
for (auto mapIt = m_ObjectToProp3D.begin(); mapIt != m_ObjectToProp3D.end(); ) {
if (mapIt->second == p) mapIt = m_ObjectToProp3D.erase(mapIt);
else ++mapIt;
}
@@ -483,23 +483,23 @@ void Viewport::UnregisterPuppet(Puppet* p) {
void Viewport::ObserveContext(ObjectsContext* ctx) {
if (!ctx) return;
// Process existing puppets
for (auto const& [obj, puppet] : ctx->GetPuppets()) {
this->RegisterPuppet(puppet, true);
// Process existing Prop3Ds
for (auto const& [obj, prop3d] : ctx->GetProp3Ds()) {
this->RegisterProp3D(prop3d, true);
}
// Listen for future puppets
uLib::Object::connect(ctx, &ObjectsContext::PuppetAdded, [this](Puppet* p){
this->RegisterPuppet(p, true);
// Listen for future Prop3Ds
uLib::Object::connect(ctx, &ObjectsContext::Prop3DAdded, [this](Prop3D* p){
this->RegisterProp3D(p, true);
});
uLib::Object::connect(ctx, &ObjectsContext::PuppetRemoved, [this](Puppet* p){
this->UnregisterPuppet(p);
uLib::Object::connect(ctx, &ObjectsContext::Prop3DRemoved, [this](Prop3D* p){
this->UnregisterProp3D(p);
});
}
void Viewport::SelectPuppet(Puppet* prop)
void Viewport::SelectProp3D(Prop3D* prop)
{
for (auto* p : m_Puppets) {
for (auto* p : m_Prop3Ds) {
p->SetSelected(p == prop);
}

View File

@@ -46,10 +46,10 @@ public:
void ZoomAuto();
void ZoomSelected();
// Puppet / prop management
void AddPuppet(Puppet &prop);
void RemovePuppet(Puppet &prop);
void SelectPuppet(Puppet *prop);
// Prop3D / prop management
void AddProp3D(Prop3D &prop);
void RemoveProp3D(Prop3D &prop);
void SelectProp3D(Prop3D *prop);
void addProp(vtkProp *prop);
void RemoveProp(vtkProp *prop);
@@ -63,8 +63,8 @@ public:
vtkCornerAnnotation* GetAnnotation();
vtkCameraOrientationWidget* GetCameraWidget();
void DisableHandler();
virtual void OnSelectionChanged(Puppet* p) {}
const std::vector<Puppet*>& getPuppets() const { return m_Puppets; }
virtual void OnSelectionChanged(Prop3D* p) {}
const std::vector<Prop3D*>& getProp3Ds() const { return m_Prop3Ds; }
// Grid control
void SetGridVisible(bool visible);
@@ -83,15 +83,15 @@ protected:
void UpdateGrid();
// Internal puppet registration
void RegisterPuppet(Puppet* p, bool isPart = false);
void UnregisterPuppet(Puppet* p);
// Internal Prop3D registration
void RegisterProp3D(Prop3D* p, bool isPart = false);
void UnregisterProp3D(Prop3D* p);
void ObserveContext(ObjectsContext* ctx);
struct ViewportData *pv;
Axis m_GridAxis;
std::vector<Puppet*> m_Puppets;
std::map<uLib::Object*, Puppet*> m_ObjectToPuppet;
std::vector<Prop3D*> m_Prop3Ds;
std::map<uLib::Object*, Prop3D*> m_ObjectToProp3D;
};
} // namespace Vtk