attach vtk context to gcompose
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <typeinfo>
|
||||
#include <cxxabi.h>
|
||||
#include <functional>
|
||||
#include "Core/Object.h"
|
||||
|
||||
ContextModel::ContextModel(QObject* parent)
|
||||
: QAbstractItemModel(parent), m_rootContext(nullptr) {}
|
||||
@@ -12,6 +13,12 @@ ContextModel::~ContextModel() {}
|
||||
void ContextModel::setContext(uLib::ObjectsContext* context) {
|
||||
beginResetModel();
|
||||
m_rootContext = context;
|
||||
if (m_rootContext) {
|
||||
uLib::Object::connect(m_rootContext, &uLib::Object::Updated, [this]() {
|
||||
this->beginResetModel();
|
||||
this->endResetModel();
|
||||
});
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@@ -118,7 +125,14 @@ QVariant ContextModel::data(const QModelIndex& index, int role) const {
|
||||
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return getDemangledName(typeid(*obj));
|
||||
QString typeName = getDemangledName(typeid(*obj));
|
||||
std::string instName = obj->GetInstanceName();
|
||||
if (instName.empty()) return typeName;
|
||||
return QString("%1 (%2)").arg(QString::fromStdString(instName)).arg(typeName);
|
||||
}
|
||||
|
||||
if (role == Qt::EditRole) {
|
||||
return QString::fromStdString(obj->GetInstanceName());
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@@ -130,3 +144,18 @@ QVariant ContextModel::headerData(int section, Qt::Orientation orientation, int
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ContextModel::flags(const QModelIndex& index) const {
|
||||
if (!index.isValid()) return Qt::NoItemFlags;
|
||||
return Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
bool ContextModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
if (index.isValid() && role == Qt::EditRole) {
|
||||
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
||||
obj->SetInstanceName(value.toString().toStdString());
|
||||
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ public:
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
|
||||
private:
|
||||
uLib::ObjectsContext* m_rootContext;
|
||||
|
||||
@@ -4,8 +4,16 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QTreeView>
|
||||
#include <QSplitter>
|
||||
#include <QList>
|
||||
#include <QShortcut>
|
||||
#include <QItemSelectionModel>
|
||||
#include <Vtk/vtkQViewport.h>
|
||||
#include <Vtk/vtkObjectsContext.h>
|
||||
|
||||
ContextPanel::ContextPanel(QWidget* parent) : QWidget(parent) {
|
||||
ContextPanel::ContextPanel(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_vtkContext(nullptr) {
|
||||
m_layout = new QVBoxLayout(this);
|
||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||
m_layout->setSpacing(0);
|
||||
@@ -32,12 +40,92 @@ ContextPanel::ContextPanel(QWidget* parent) : QWidget(parent) {
|
||||
m_model = new ContextModel(this);
|
||||
m_treeView->setModel(m_model);
|
||||
|
||||
m_layout->addWidget(m_treeView);
|
||||
m_splitter = new QSplitter(Qt::Vertical, this);
|
||||
m_splitter->addWidget(m_treeView);
|
||||
|
||||
m_vtkView = new uLib::Vtk::QViewport(m_splitter);
|
||||
m_splitter->addWidget(m_vtkView);
|
||||
|
||||
QList<int> sizes;
|
||||
sizes << 400 << 200;
|
||||
m_splitter->setSizes(sizes);
|
||||
|
||||
m_layout->addWidget(m_splitter);
|
||||
|
||||
connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &ContextPanel::onSelectionChanged);
|
||||
|
||||
auto* deleteShortcut = new QShortcut(QKeySequence::Delete, this);
|
||||
connect(deleteShortcut, &QShortcut::activated, [this]() {
|
||||
auto selectedIndexes = m_treeView->selectionModel()->selectedIndexes();
|
||||
if (selectedIndexes.isEmpty() || !m_context) return;
|
||||
|
||||
// Collect objects to remove to avoid iterator invalidation issues if context signal emits during removal
|
||||
std::vector<uLib::Object*> toRemove;
|
||||
for (const auto& idx : selectedIndexes) {
|
||||
if (idx.column() == 0) {
|
||||
toRemove.push_back(static_cast<uLib::Object*>(idx.internalPointer()));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* obj : toRemove) {
|
||||
m_context->RemoveObject(obj);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ContextPanel::~ContextPanel() {}
|
||||
|
||||
void ContextPanel::setContext(uLib::ObjectsContext* context) {
|
||||
m_context = context;
|
||||
m_model->setContext(context);
|
||||
m_treeView->expandAll();
|
||||
|
||||
if (m_vtkContext) {
|
||||
m_vtkView->RemovePuppet(*m_vtkContext);
|
||||
delete m_vtkContext;
|
||||
}
|
||||
m_vtkContext = new uLib::Vtk::vtkObjectsContext(context);
|
||||
m_vtkView->AddPuppet(*m_vtkContext);
|
||||
|
||||
// Render viewport and add child puppets when context is updated
|
||||
if (context) {
|
||||
uLib::Object::connect(m_vtkContext, &uLib::Vtk::vtkObjectsContext::PuppetAdded, [this](uLib::Vtk::Puppet* p) {
|
||||
if (this->m_vtkView && p) {
|
||||
this->m_vtkView->AddPuppet(*p);
|
||||
this->m_vtkView->ZoomAuto();
|
||||
this->m_vtkView->Render();
|
||||
}
|
||||
});
|
||||
|
||||
// Add any puppets that were created during m_vtkContext's construction
|
||||
for (auto* obj : context->GetObjects()) {
|
||||
if (auto* p = m_vtkContext->GetPuppet(obj)) {
|
||||
this->m_vtkView->AddPuppet(*p);
|
||||
}
|
||||
}
|
||||
|
||||
uLib::Object::connect(context, &uLib::Object::Updated, [this]() {
|
||||
if (this->m_vtkView) {
|
||||
this->m_vtkView->ZoomAuto();
|
||||
this->m_vtkView->Render();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
m_vtkView->Render();
|
||||
}
|
||||
|
||||
void ContextPanel::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
|
||||
uLib::Object* target = nullptr;
|
||||
if (!selected.indexes().isEmpty()) {
|
||||
target = static_cast<uLib::Object*>(selected.indexes().first().internalPointer());
|
||||
}
|
||||
|
||||
emit objectSelected(target);
|
||||
|
||||
if (m_vtkContext) {
|
||||
auto* puppet = m_vtkContext->GetPuppet(target);
|
||||
m_vtkView->SelectPuppet(puppet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define CONTEXT_PANEL_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QItemSelection>
|
||||
|
||||
class QTreeView;
|
||||
class QVBoxLayout;
|
||||
@@ -9,9 +10,16 @@ class QLabel;
|
||||
class ContextModel;
|
||||
|
||||
namespace uLib {
|
||||
class Object;
|
||||
class ObjectsContext;
|
||||
namespace Vtk {
|
||||
class QViewport;
|
||||
class vtkObjectsContext;
|
||||
}
|
||||
}
|
||||
|
||||
class QSplitter;
|
||||
|
||||
class ContextPanel : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -20,12 +28,22 @@ public:
|
||||
|
||||
void setContext(uLib::ObjectsContext* context);
|
||||
|
||||
Q_SIGNALS:
|
||||
void objectSelected(uLib::Object* obj);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
|
||||
private:
|
||||
QVBoxLayout* m_layout;
|
||||
QWidget* m_titleBar;
|
||||
QLabel* m_titleLabel;
|
||||
QTreeView* m_treeView;
|
||||
ContextModel* m_model;
|
||||
QSplitter* m_splitter;
|
||||
uLib::Vtk::QViewport* m_vtkView;
|
||||
uLib::Vtk::vtkObjectsContext* m_vtkContext;
|
||||
uLib::ObjectsContext* m_context;
|
||||
};
|
||||
|
||||
#endif // CONTEXT_PANEL_H
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "MainPanel.h"
|
||||
#include "ViewportPane.h"
|
||||
#include "ContextPanel.h"
|
||||
#include "Core/ObjectFactory.h"
|
||||
#include "Core/ObjectsContext.h"
|
||||
#include "Vtk/vtkObjectsContext.h"
|
||||
#include "Vtk/vtkQViewport.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QSplitter>
|
||||
@@ -11,7 +15,7 @@
|
||||
#include <QApplication>
|
||||
#include "StyleManager.h"
|
||||
|
||||
MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
||||
MainPanel::MainPanel(QWidget* parent) : QWidget(parent), m_context(nullptr), m_mainVtkContext(nullptr) {
|
||||
auto* mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setSpacing(0);
|
||||
@@ -44,8 +48,23 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
||||
themeMenu->addAction("Bright", this, &MainPanel::onBrightTheme);
|
||||
btnTheme->setMenu(themeMenu);
|
||||
|
||||
// New Menu Button
|
||||
auto* btnNew = new QPushButton("New", menuPanel);
|
||||
btnNew->setObjectName("MenuButton");
|
||||
auto* newMenu = new QMenu(btnNew);
|
||||
|
||||
auto classes = uLib::ObjectFactory::Instance().GetRegisteredClasses();
|
||||
for (const auto& className : classes) {
|
||||
auto* action = newMenu->addAction(QString::fromStdString(className));
|
||||
connect(action, &QAction::triggered, [this, className]() {
|
||||
this->onCreateObject(className);
|
||||
});
|
||||
}
|
||||
btnNew->setMenu(newMenu);
|
||||
|
||||
menuLayout->addWidget(logo);
|
||||
menuLayout->addWidget(btnFile);
|
||||
menuLayout->addWidget(btnNew);
|
||||
menuLayout->addWidget(btnTheme);
|
||||
menuLayout->addStretch();
|
||||
|
||||
@@ -58,6 +77,16 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
||||
m_firstPane = new ViewportPane(m_rootSplitter);
|
||||
m_rootSplitter->addWidget(m_firstPane);
|
||||
|
||||
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;
|
||||
if (m_mainVtkContext) {
|
||||
puppet = m_mainVtkContext->GetPuppet(obj);
|
||||
}
|
||||
viewport->SelectPuppet(puppet);
|
||||
}
|
||||
});
|
||||
|
||||
// Set initial sizes
|
||||
QList<int> sizes;
|
||||
sizes << 200 << 1000;
|
||||
@@ -67,7 +96,52 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
||||
}
|
||||
|
||||
void MainPanel::setContext(uLib::ObjectsContext* context) {
|
||||
m_context = context;
|
||||
m_contextPanel->setContext(context);
|
||||
|
||||
if (m_mainVtkContext) {
|
||||
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
|
||||
viewport->RemovePuppet(*m_mainVtkContext);
|
||||
}
|
||||
delete m_mainVtkContext;
|
||||
m_mainVtkContext = nullptr;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
|
||||
m_mainVtkContext = new uLib::Vtk::vtkObjectsContext(context);
|
||||
viewport->AddPuppet(*m_mainVtkContext);
|
||||
uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::vtkObjectsContext::PuppetAdded, [viewport](uLib::Vtk::Puppet* p) {
|
||||
if (viewport && p) {
|
||||
viewport->AddPuppet(*p);
|
||||
viewport->ZoomAuto();
|
||||
viewport->Render();
|
||||
}
|
||||
});
|
||||
|
||||
// Add any puppets that were created during m_mainVtkContext's construction
|
||||
for (auto* obj : context->GetObjects()) {
|
||||
if (auto* p = m_mainVtkContext->GetPuppet(obj)) {
|
||||
viewport->AddPuppet(*p);
|
||||
}
|
||||
}
|
||||
|
||||
uLib::Object::connect(context, &uLib::Object::Updated, [viewport]() {
|
||||
viewport->ZoomAuto();
|
||||
viewport->Render();
|
||||
});
|
||||
viewport->ZoomAuto();
|
||||
viewport->Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainPanel::onCreateObject(const std::string& className) {
|
||||
if (!m_context) return;
|
||||
auto* obj = uLib::ObjectFactory::Instance().Create(className);
|
||||
if (obj) {
|
||||
m_context->AddObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void MainPanel::onOpen() {
|
||||
|
||||
@@ -9,6 +9,9 @@ class ContextPanel;
|
||||
|
||||
namespace uLib {
|
||||
class ObjectsContext;
|
||||
namespace Vtk {
|
||||
class vtkObjectsContext;
|
||||
}
|
||||
}
|
||||
|
||||
class MainPanel : public QWidget {
|
||||
@@ -25,11 +28,15 @@ private slots:
|
||||
void onSave();
|
||||
void onDarkTheme();
|
||||
void onBrightTheme();
|
||||
|
||||
void onCreateObject(const std::string& className);
|
||||
|
||||
private:
|
||||
QSplitter* m_rootSplitter;
|
||||
ViewportPane* m_firstPane;
|
||||
ContextPanel* m_contextPanel;
|
||||
uLib::ObjectsContext* m_context;
|
||||
uLib::Vtk::vtkObjectsContext* m_mainVtkContext;
|
||||
};
|
||||
|
||||
#endif // MAINPANEL_H
|
||||
|
||||
@@ -33,7 +33,8 @@ int main(int argc, char** argv) {
|
||||
std::cout << "Starting gcompose Qt application..." << std::endl;
|
||||
|
||||
ContainerBox world_box(Vector3f(1, 1, 1));
|
||||
world_box.Scale(Vector3f(20_mm, 20_mm, 20_mm));
|
||||
world_box.Scale(Vector3f(2_mm, 2_mm, 2_mm));
|
||||
world_box.SetPosition(Vector3f(-1_mm, -1_mm, -1_mm));
|
||||
|
||||
Geant::Scene scene;
|
||||
scene.ConstructWorldBox(world_box.GetSize(), "G4_AIR");
|
||||
@@ -46,14 +47,7 @@ int main(int argc, char** argv) {
|
||||
// 2. Initialize MainWindow (contains embedded VTK QViewport)
|
||||
MainWindow window;
|
||||
window.setContext(&globalContext);
|
||||
MainPanel* panel = window.getPanel();
|
||||
ViewportPane* pane = panel->getFirstPane();
|
||||
Vtk::QViewport* viewport = qobject_cast<Vtk::QViewport*>(pane->currentViewport());
|
||||
|
||||
Vtk::vtkContainerBox vtk_box(&world_box);
|
||||
viewport->AddPuppet(vtk_box);
|
||||
viewport->ZoomAuto();
|
||||
|
||||
|
||||
std::cout << "Geant4 and VTK scenes are ready." << std::endl;
|
||||
|
||||
window.show();
|
||||
|
||||
@@ -10,6 +10,7 @@ set(HEADERS
|
||||
Macros.h
|
||||
Mpl.h
|
||||
Object.h
|
||||
ObjectFactory.h
|
||||
ObjectsContext.h
|
||||
Options.h
|
||||
Serializable.h
|
||||
@@ -27,6 +28,7 @@ set(SOURCES
|
||||
Archives.cpp
|
||||
Debug.cpp
|
||||
Object.cpp
|
||||
ObjectFactory.cpp
|
||||
ObjectsContext.cpp
|
||||
Options.cpp
|
||||
Serializable.cpp
|
||||
|
||||
@@ -56,7 +56,8 @@ public:
|
||||
GenericMFPtr sloptr;
|
||||
std::string slostr;
|
||||
};
|
||||
|
||||
|
||||
std::string m_InstanceName;
|
||||
Vector<Signal> sigv;
|
||||
Vector<Slot> slov;
|
||||
};
|
||||
@@ -147,6 +148,15 @@ GenericMFPtr *Object::findSlotImpl(const char *name) const {
|
||||
|
||||
void Object::Updated() { ULIB_SIGNAL_EMIT(Object::Updated); }
|
||||
|
||||
const std::string& Object::GetInstanceName() const {
|
||||
return d->m_InstanceName;
|
||||
}
|
||||
|
||||
void Object::SetInstanceName(const std::string& name) {
|
||||
d->m_InstanceName = name;
|
||||
this->Updated();
|
||||
}
|
||||
|
||||
// std::ostream &
|
||||
// operator << (std::ostream &os, uLib::Object &ob)
|
||||
// {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define U_CORE_OBJECT_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
// WARNING: COPILE ERROR if this goes after mpl/vector //
|
||||
// #include "Core/Vector.h"
|
||||
@@ -74,6 +75,10 @@ public:
|
||||
Object(const Object ©);
|
||||
~Object();
|
||||
|
||||
virtual const char * GetClassName() const { return "Object"; }
|
||||
|
||||
const std::string& GetInstanceName() const;
|
||||
void SetInstanceName(const std::string& name);
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// PARAMETERS //
|
||||
|
||||
|
||||
32
src/Core/ObjectFactory.cpp
Normal file
32
src/Core/ObjectFactory.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "ObjectFactory.h"
|
||||
|
||||
namespace uLib {
|
||||
|
||||
ObjectFactory& ObjectFactory::Instance() {
|
||||
static ObjectFactory instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ObjectFactory::Register(const std::string& className, FactoryFunction func) {
|
||||
if (m_factoryMap.find(className) == m_factoryMap.end()) {
|
||||
m_factoryMap[className] = func;
|
||||
}
|
||||
}
|
||||
|
||||
Object* ObjectFactory::Create(const std::string& className) {
|
||||
auto it = m_factoryMap.find(className);
|
||||
if (it != m_factoryMap.end()) {
|
||||
return (it->second)();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> ObjectFactory::GetRegisteredClasses() const {
|
||||
std::vector<std::string> classes;
|
||||
for (auto const& [name, func] : m_factoryMap) {
|
||||
classes.push_back(name);
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
} // namespace uLib
|
||||
68
src/Core/ObjectFactory.h
Normal file
68
src/Core/ObjectFactory.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef U_CORE_OBJECTFACTORY_H
|
||||
#define U_CORE_OBJECTFACTORY_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include "Core/Object.h"
|
||||
|
||||
namespace uLib {
|
||||
|
||||
/**
|
||||
* @brief Singleton factory for dynamic Object instantiation based on class name.
|
||||
*/
|
||||
class ObjectFactory {
|
||||
public:
|
||||
typedef std::function<Object*()> FactoryFunction;
|
||||
|
||||
/** @brief Get the singleton instance. */
|
||||
static ObjectFactory& Instance();
|
||||
|
||||
/** @brief Register a factory function for a given class name. */
|
||||
void Register(const std::string& className, FactoryFunction func);
|
||||
|
||||
/** @brief Create a new instance of the specified class. */
|
||||
Object* Create(const std::string& className);
|
||||
|
||||
/** @brief Get the names of all registered classes. */
|
||||
std::vector<std::string> GetRegisteredClasses() const;
|
||||
|
||||
private:
|
||||
ObjectFactory() = default;
|
||||
~ObjectFactory() = default;
|
||||
|
||||
// Prevent copy and assignment
|
||||
ObjectFactory(const ObjectFactory&) = delete;
|
||||
ObjectFactory& operator=(const ObjectFactory&) = delete;
|
||||
|
||||
std::map<std::string, FactoryFunction> m_factoryMap;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper class to statically register a factory function.
|
||||
*/
|
||||
template <typename T>
|
||||
class ObjectRegistrar {
|
||||
public:
|
||||
ObjectRegistrar(const std::string& className) {
|
||||
ObjectFactory::Instance().Register(className, []() -> Object* { return new T(); });
|
||||
}
|
||||
};
|
||||
|
||||
#define ULIB_REG_CONCAT_IMPL(a, b) a##b
|
||||
#define ULIB_REG_CONCAT(a, b) ULIB_REG_CONCAT_IMPL(a, b)
|
||||
|
||||
/**
|
||||
* @brief Macro to register a class to the factory.
|
||||
* Put this in the .cpp file of the class.
|
||||
*/
|
||||
#define ULIB_REGISTER_OBJECT(className) \
|
||||
static uLib::ObjectRegistrar<className> ULIB_REG_CONCAT(g_ObjectRegistrar_, __LINE__)(#className);
|
||||
|
||||
#define ULIB_REGISTER_OBJECT_NAME(className, registeredName) \
|
||||
static uLib::ObjectRegistrar<className> ULIB_REG_CONCAT(g_ObjectRegistrar_, __LINE__)(registeredName);
|
||||
|
||||
} // namespace uLib
|
||||
|
||||
#endif // U_CORE_OBJECTFACTORY_H
|
||||
@@ -10,6 +10,7 @@ ObjectsContext::~ObjectsContext() {}
|
||||
void ObjectsContext::AddObject(Object* obj) {
|
||||
if (obj && std::find(m_objects.begin(), m_objects.end(), obj) == m_objects.end()) {
|
||||
m_objects.push_back(obj);
|
||||
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectAdded, obj);
|
||||
this->Updated(); // Signal that the context has been updated
|
||||
}
|
||||
}
|
||||
@@ -17,13 +18,18 @@ void ObjectsContext::AddObject(Object* obj) {
|
||||
void ObjectsContext::RemoveObject(Object* obj) {
|
||||
auto it = std::find(m_objects.begin(), m_objects.end(), obj);
|
||||
if (it != m_objects.end()) {
|
||||
Object* removedObj = *it;
|
||||
m_objects.erase(it);
|
||||
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectRemoved, removedObj);
|
||||
this->Updated(); // Signal that the context has been updated
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectsContext::Clear() {
|
||||
if (!m_objects.empty()) {
|
||||
for (auto obj : m_objects) {
|
||||
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectRemoved, obj);
|
||||
}
|
||||
m_objects.clear();
|
||||
this->Updated();
|
||||
}
|
||||
@@ -44,4 +50,12 @@ Object* ObjectsContext::GetObject(size_t index) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ObjectsContext::ObjectAdded(Object* obj) {
|
||||
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectAdded, obj);
|
||||
}
|
||||
|
||||
void ObjectsContext::ObjectRemoved(Object* obj) {
|
||||
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectRemoved, obj);
|
||||
}
|
||||
|
||||
} // namespace uLib
|
||||
|
||||
@@ -14,6 +14,8 @@ public:
|
||||
ObjectsContext();
|
||||
virtual ~ObjectsContext();
|
||||
|
||||
virtual const char * GetClassName() const { return "ObjectsContext"; }
|
||||
|
||||
/**
|
||||
* @brief Adds an object to the context.
|
||||
* @param obj Pointer to the object to add.
|
||||
@@ -36,6 +38,12 @@ public:
|
||||
* @return Const reference to the vector of object pointers.
|
||||
*/
|
||||
const std::vector<Object*>& GetObjects() const;
|
||||
|
||||
signals:
|
||||
/** @brief Signal emitted when an object is added. */
|
||||
virtual void ObjectAdded(Object* obj);
|
||||
/** @brief Signal emitted when an object is removed. */
|
||||
virtual void ObjectRemoved(Object* obj);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of objects in the context.
|
||||
|
||||
@@ -43,11 +43,23 @@ using namespace boost::placeholders;
|
||||
// Signals macro //
|
||||
|
||||
#define default(vlaue)
|
||||
#define slots
|
||||
#ifndef Q_MOC_RUN
|
||||
#ifndef signals
|
||||
#define signals /*virtual void init_signals();*/ public
|
||||
#endif
|
||||
#ifndef slots
|
||||
#define slots
|
||||
#endif
|
||||
#ifndef emit
|
||||
#define emit
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SLOT
|
||||
#define SLOT(a) BOOST_STRINGIZE(a)
|
||||
#endif
|
||||
#ifndef SIGNAL
|
||||
#define SIGNAL(a) BOOST_STRINGIZE(a)
|
||||
#endif
|
||||
|
||||
#define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \
|
||||
do { \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "HEP/Detectors/DetectorChamber.h"
|
||||
#include "Core/ObjectFactory.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace uLib {
|
||||
@@ -43,4 +44,6 @@ MuonEvent DetectorChamber::ProjectMuonEvent(const MuonEvent &muon) const {
|
||||
return projectedMuon;
|
||||
}
|
||||
|
||||
ULIB_REGISTER_OBJECT(DetectorChamber)
|
||||
|
||||
} // namespace uLib
|
||||
@@ -45,6 +45,8 @@ class DetectorChamber : public ContainerBox {
|
||||
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "DetectorChamber"; }
|
||||
|
||||
DetectorChamber() : BaseClass() {
|
||||
m_ProjectionPlane.origin = HPoint3f(0, 0, 0);
|
||||
m_ProjectionPlane.direction = HVector3f(0, 0, 1);
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Geant {
|
||||
class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, public AffineTransform
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.EmitterPrimary"; }
|
||||
|
||||
EmitterPrimary();
|
||||
virtual ~EmitterPrimary();
|
||||
|
||||
@@ -44,6 +47,9 @@ class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, publ
|
||||
class SkyPlaneEmitterPrimary : public EmitterPrimary
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.SkyPlaneEmitterPrimary"; }
|
||||
|
||||
SkyPlaneEmitterPrimary();
|
||||
virtual ~SkyPlaneEmitterPrimary();
|
||||
|
||||
@@ -63,6 +69,9 @@ class SkyPlaneEmitterPrimary : public EmitterPrimary
|
||||
class CylinderEmitterPrimary : public EmitterPrimary
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.CylinderEmitterPrimary"; }
|
||||
|
||||
CylinderEmitterPrimary();
|
||||
virtual ~CylinderEmitterPrimary();
|
||||
|
||||
@@ -89,6 +98,9 @@ class CylinderEmitterPrimary : public EmitterPrimary
|
||||
class QuadMeshEmitterPrimary : public EmitterPrimary
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.QuadMeshEmitterPrimary"; }
|
||||
|
||||
QuadMeshEmitterPrimary();
|
||||
virtual ~QuadMeshEmitterPrimary();
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef U_GEANTEVENT_H
|
||||
#define U_GEANTEVENT_H
|
||||
|
||||
#include "Core/Object.h"
|
||||
#include "Core/Types.h"
|
||||
#include "Core/Vector.h"
|
||||
#include "Math/Dense.h"
|
||||
@@ -46,10 +47,12 @@ class SteppingAction;
|
||||
/// recording the change of momentum and direction at each step boundary.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GeantEvent {
|
||||
class GeantEvent : public Object {
|
||||
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.GeantEvent"; }
|
||||
|
||||
/// A single interaction step along the muon path.
|
||||
struct Delta {
|
||||
Scalarf m_Length; ///< step length through the solid
|
||||
|
||||
@@ -59,6 +59,8 @@ private:
|
||||
class Material : public Object {
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.Material"; }
|
||||
|
||||
uLibRefMacro(G4Data,G4Material *)
|
||||
private:
|
||||
G4Material *m_G4Data;
|
||||
|
||||
@@ -43,6 +43,9 @@ class EmitterPrimary;
|
||||
|
||||
class Scene : public Object {
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.Scene"; }
|
||||
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ namespace Geant {
|
||||
|
||||
class Solid : public Object {
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.Solid"; }
|
||||
|
||||
Solid();
|
||||
Solid(const char *name);
|
||||
virtual ~Solid();
|
||||
@@ -83,6 +86,9 @@ protected:
|
||||
class TessellatedSolid : public Solid {
|
||||
typedef Solid BaseClass;
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.TessellatedSolid"; }
|
||||
|
||||
TessellatedSolid(const char *name);
|
||||
void SetMesh(TriangleMesh &mesh);
|
||||
uLibGetMacro(Solid, G4TessellatedSolid *)
|
||||
@@ -104,6 +110,9 @@ class BoxSolid : public Solid {
|
||||
typedef Solid BaseClass;
|
||||
|
||||
public:
|
||||
|
||||
virtual const char* GetClassName() const override { return "Geant.BoxSolid"; }
|
||||
|
||||
BoxSolid(const char *name, ContainerBox *box);
|
||||
virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; }
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ set(SOURCES VoxRaytracer.cpp
|
||||
QuadMesh.cpp
|
||||
Dense.cpp
|
||||
Structured2DGrid.cpp
|
||||
Structured4DGrid.cpp)
|
||||
Structured4DGrid.cpp
|
||||
MathRegistrations.cpp)
|
||||
|
||||
set(LIBRARIES ${PACKAGE_LIBPREFIX}Core
|
||||
Eigen3::Eigen
|
||||
|
||||
@@ -48,6 +48,9 @@ class ContainerBox : public AffineTransform, public Object {
|
||||
typedef AffineTransform BaseClass;
|
||||
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "ContainerBox"; }
|
||||
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
* Initializes the local transformation with this instance as its parent.
|
||||
|
||||
@@ -45,6 +45,9 @@ class Cylinder : public AffineTransform, public Object {
|
||||
typedef AffineTransform BaseClass;
|
||||
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "Cylinder"; }
|
||||
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
* Initializes with radius 1 and height 1.
|
||||
|
||||
@@ -28,15 +28,18 @@
|
||||
#ifndef U_GEOMETRY_H
|
||||
#define U_GEOMETRY_H
|
||||
|
||||
#include "Core/Object.h"
|
||||
#include "Math/Dense.h"
|
||||
#include "Math/Transform.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace uLib {
|
||||
|
||||
class Geometry : public AffineTransform {
|
||||
class Geometry : public AffineTransform, public Object {
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "Geometry"; }
|
||||
|
||||
virtual Vector3f ToLinear(const Vector3f& curved_space) const {
|
||||
return curved_space;
|
||||
}
|
||||
@@ -87,6 +90,8 @@ class SphericalGeometry : public Geometry {
|
||||
public:
|
||||
SphericalGeometry() {}
|
||||
|
||||
virtual const char * GetClassName() const { return "SphericalGeometry"; }
|
||||
|
||||
Vector3f ToLinear(const Vector3f& spherical) const {
|
||||
float r = spherical.x();
|
||||
float theta = spherical.y();
|
||||
@@ -109,6 +114,8 @@ class ToroidalGeometry : public Geometry {
|
||||
public:
|
||||
ToroidalGeometry(float Rtor) : m_Rtor(Rtor) {}
|
||||
|
||||
virtual const char * GetClassName() const { return "ToroidalGeometry"; }
|
||||
|
||||
Vector3f ToLinear(const Vector3f& toroidal) const {
|
||||
float r = toroidal.x();
|
||||
float theta = toroidal.y();
|
||||
|
||||
20
src/Math/MathRegistrations.cpp
Normal file
20
src/Math/MathRegistrations.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "Core/ObjectFactory.h"
|
||||
#include "Math/ContainerBox.h"
|
||||
#include "Math/Cylinder.h"
|
||||
#include "Math/Geometry.h"
|
||||
#include "Math/TriangleMesh.h"
|
||||
#include "Math/QuadMesh.h"
|
||||
#include "Math/VoxImage.h"
|
||||
#include "Math/StructuredData.h"
|
||||
|
||||
namespace uLib {
|
||||
|
||||
ULIB_REGISTER_OBJECT(ContainerBox)
|
||||
ULIB_REGISTER_OBJECT(Cylinder)
|
||||
ULIB_REGISTER_OBJECT(CylindricalGeometry)
|
||||
ULIB_REGISTER_OBJECT(SphericalGeometry)
|
||||
ULIB_REGISTER_OBJECT(TriangleMesh)
|
||||
ULIB_REGISTER_OBJECT(QuadMesh)
|
||||
ULIB_REGISTER_OBJECT_NAME(VoxImage<Voxel>, "VoxImage")
|
||||
|
||||
} // namespace uLib
|
||||
@@ -36,6 +36,8 @@ class Polydata : public Object {
|
||||
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "Polydata"; }
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace uLib {
|
||||
class QuadMesh : public AffineTransform, public Object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "QuadMesh"; }
|
||||
|
||||
void PrintSelf(std::ostream &o);
|
||||
|
||||
/** @brief Adds a point in global coordinates. Stored in local coordinates. */
|
||||
|
||||
@@ -40,6 +40,9 @@ namespace uLib {
|
||||
class TriangleMesh : public AffineTransform, public Object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "TriangleMesh"; }
|
||||
|
||||
void PrintSelf(std::ostream &o);
|
||||
|
||||
/** @brief Adds a point in global coordinates. Stored in local coordinates. */
|
||||
|
||||
@@ -46,6 +46,9 @@ namespace Abstract {
|
||||
|
||||
class VoxImage : public uLib::StructuredGrid {
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "VoxImage"; }
|
||||
|
||||
typedef uLib::StructuredGrid BaseClass;
|
||||
|
||||
virtual float GetValue(const Vector3i &id) const = 0;
|
||||
|
||||
@@ -57,9 +57,12 @@ protected:
|
||||
} // namespace Abstract
|
||||
|
||||
template <typename VoxelT, typename AlgorithmT>
|
||||
class VoxImageFilter : public Abstract::VoxImageFilter {
|
||||
class VoxImageFilter : public Abstract::VoxImageFilter, public Object {
|
||||
|
||||
public:
|
||||
|
||||
virtual const char * GetClassName() const { return "VoxImageFilter"; }
|
||||
|
||||
VoxImageFilter(const Vector3i &size);
|
||||
|
||||
void Run();
|
||||
|
||||
@@ -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