From 8ddb7c4d7e5cbc81124887e9ea81680d59b8e2f3 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Mon, 24 Feb 2025 16:17:57 -0800 Subject: [PATCH 01/60] refactor, use new CameraDataObject for ui --- agave_app/CameraDockWidget.cpp | 4 +- agave_app/CameraDockWidget.h | 5 +- agave_app/CameraWidget.cpp | 366 ++++++++++++++++++++++++++++++++- agave_app/CameraWidget.h | 5 +- agave_app/GLView3D.h | 1 + agave_app/agaveGui.cpp | 18 +- agave_app/agaveGui.h | 5 +- renderlib/CMakeLists.txt | 2 - renderlib/CameraDataObject.cpp | 34 ++- renderlib/CameraDataObject.hpp | 3 +- renderlib/ViewerWindow.cpp | 4 + 11 files changed, 414 insertions(+), 33 deletions(-) diff --git a/agave_app/CameraDockWidget.cpp b/agave_app/CameraDockWidget.cpp index 4d6fa45d..5e213175 100644 --- a/agave_app/CameraDockWidget.cpp +++ b/agave_app/CameraDockWidget.cpp @@ -1,8 +1,8 @@ #include "CameraDockWidget.h" -QCameraDockWidget::QCameraDockWidget(QWidget* pParent, RenderSettings* rs, CameraDataObject* cdo) +QCameraDockWidget::QCameraDockWidget(QWidget* pParent, QCamera* cam, RenderSettings* rs, CameraDataObject* cdo) : QDockWidget(pParent) - , m_CameraWidget(nullptr, rs, cdo) + , m_CameraWidget(nullptr, cam, rs, cdo) { setWindowTitle("Camera"); diff --git a/agave_app/CameraDockWidget.h b/agave_app/CameraDockWidget.h index 5962c295..e2ac83fe 100644 --- a/agave_app/CameraDockWidget.h +++ b/agave_app/CameraDockWidget.h @@ -9,7 +9,10 @@ class QCameraDockWidget : public QDockWidget Q_OBJECT public: - QCameraDockWidget(QWidget* pParent = NULL, RenderSettings* rs = NULL, CameraDataObject* cdo = NULL); + QCameraDockWidget(QWidget* pParent = NULL, + QCamera* cam = NULL, + RenderSettings* rs = NULL, + CameraDataObject* cdo = NULL); private: QCameraWidget m_CameraWidget; diff --git a/agave_app/CameraWidget.cpp b/agave_app/CameraWidget.cpp index 332afa50..c133fbaf 100644 --- a/agave_app/CameraWidget.cpp +++ b/agave_app/CameraWidget.cpp @@ -8,7 +8,214 @@ #include -QCameraWidget::QCameraWidget(QWidget* pParent, RenderSettings* rs, CameraDataObject* cdo) +struct GenericUIInfo +{ + std::string type; + std::string formLabel; + std::string statusTip; + std::string toolTip; + + GenericUIInfo() = default; + GenericUIInfo(std::string type, std::string formLabel, std::string statusTip, std::string toolTip) + : type(type) + , formLabel(formLabel) + , statusTip(statusTip) + , toolTip(toolTip) + { + } +}; +struct CheckBoxUiInfo : public GenericUIInfo +{ + static constexpr const char* TYPE = "CheckBox"; + + CheckBoxUiInfo() { type = CheckBoxUiInfo::TYPE; } + CheckBoxUiInfo(std::string formLabel, std::string statusTip, std::string toolTip) + : GenericUIInfo(CheckBoxUiInfo::TYPE, formLabel, statusTip, toolTip) + { + } +}; +struct ComboBoxUiInfo : public GenericUIInfo +{ + static constexpr const char* TYPE = "ComboBox"; + std::vector items; + + ComboBoxUiInfo() { type = ComboBoxUiInfo::TYPE; } + ComboBoxUiInfo(std::string formLabel, std::string statusTip, std::string toolTip, std::vector items) + : GenericUIInfo(ComboBoxUiInfo::TYPE, formLabel, statusTip, toolTip) + , items(items) + { + } +}; +struct FloatSliderSpinnerUiInfo : public GenericUIInfo +{ + static constexpr const char* TYPE = "FloatSliderSpinner"; + float min = 0.0f; + float max = 0.0f; + int decimals = 0; + float singleStep = 0.0f; + int numTickMarks = 0; + std::string suffix; + + FloatSliderSpinnerUiInfo() { type = FloatSliderSpinnerUiInfo::TYPE; } + FloatSliderSpinnerUiInfo(std::string formLabel, + std::string statusTip, + std::string toolTip, + float min, + float max, + int decimals, + float singleStep, + int numTickMarks = 0, + std::string suffix = "") + : GenericUIInfo(FloatSliderSpinnerUiInfo::TYPE, formLabel, statusTip, toolTip) + , min(min) + , max(max) + , decimals(decimals) + , singleStep(singleStep) + , numTickMarks(numTickMarks) + , suffix(suffix) + { + } +}; +struct IntSliderSpinnerUiInfo : public GenericUIInfo +{ + static constexpr const char* TYPE = "IntSliderSpinner"; + int min; + int max; + int singleStep; + int numTickMarks; + std::string suffix; + + IntSliderSpinnerUiInfo() { type = IntSliderSpinnerUiInfo::TYPE; } +}; + +QNumericSlider* +create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr> prop) +{ + QNumericSlider* slider = new QNumericSlider(); + slider->setStatusTip(QString::fromStdString(info->statusTip)); + slider->setToolTip(QString::fromStdString(info->toolTip)); + slider->setRange(info->min, info->max); + slider->setDecimals(info->decimals); + slider->setSingleStep(info->singleStep); + slider->setNumTickMarks(info->numTickMarks); + slider->setSuffix(QString::fromStdString(info->suffix)); + + slider->setValue(prop->get(), true); + QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + // TODO how would this capture the "previous" value, for undo? + QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + + return slider; +} +QNumericSlider* +create(const IntSliderSpinnerUiInfo* info, std::shared_ptr> prop) +{ + QNumericSlider* slider = new QNumericSlider(); + slider->setStatusTip(QString::fromStdString(info->statusTip)); + slider->setToolTip(QString::fromStdString(info->toolTip)); + slider->setRange(info->min, info->max); + slider->setSingleStep(info->singleStep); + slider->setNumTickMarks(info->numTickMarks); + slider->setSuffix(QString::fromStdString(info->suffix)); + + slider->setValue(prop->get(), true); + QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + // TODO how would this capture the "previous" value, for undo? + QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + + return slider; +} +QCheckBox* +create(const CheckBoxUiInfo* info, std::shared_ptr> prop) +{ + QCheckBox* checkBox = new QCheckBox(); + checkBox->setStatusTip(QString::fromStdString(info->statusTip)); + checkBox->setToolTip(QString::fromStdString(info->toolTip)); + // checkBox->setText(QString::fromStdString(info->formLabel)); + checkBox->setCheckState(prop->get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { + prop->set(state == Qt::CheckState::Checked, true); + }); + return checkBox; +} +QComboBox* +create(const ComboBoxUiInfo* info, std::shared_ptr> prop) +{ + QComboBox* comboBox = new QComboBox(); + comboBox->setStatusTip(QString::fromStdString(info->statusTip)); + comboBox->setToolTip(QString::fromStdString(info->toolTip)); + for (const auto& item : info->items) { + comboBox->addItem(QString::fromStdString(item)); + } + comboBox->setCurrentIndex(prop->get()); + QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); + return comboBox; +} + +void +createSection(QFormLayout* layout, std::vector controlDescs) +{ + // for (const auto& desc : controlDescs) { + // QLabel* label = new QLabel(QString::fromStdString(desc->formLabel)); + // if (desc->type == CheckBoxUiInfo::TYPE) { + // layout->addRow(label, create(static_cast(desc), )); + // } else if (desc->type == ComboBoxUiInfo::TYPE) { + // layout->addRow(label, create(static_cast(desc))); + // } else if (desc->type == FloatSliderSpinnerUiInfo::TYPE) { + // layout->addRow(label, create(static_cast(desc))); + // } else if (desc->type == IntSliderSpinnerUiInfo::TYPE) { + // layout->addRow(label, create(static_cast(desc))); + // } + // } +} + +QNumericSlider* +addRow(const FloatSliderSpinnerUiInfo& info, prtyProperty* prop) +{ + QNumericSlider* slider = new QNumericSlider(); + slider->setStatusTip(QString::fromStdString(info.statusTip)); + slider->setToolTip(QString::fromStdString(info.toolTip)); + slider->setRange(info.min, info.max); + slider->setDecimals(info.decimals); + slider->setSingleStep(info.singleStep); + slider->setNumTickMarks(info.numTickMarks); + slider->setSuffix(QString::fromStdString(info.suffix)); + + slider->setValue(prop->get(), true); + QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + // TODO how would this capture the "previous" value, for undo? + QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + + return slider; +} +QComboBox* +addRow(const ComboBoxUiInfo& info, prtyProperty* prop) +{ + QComboBox* comboBox = new QComboBox(); + comboBox->setStatusTip(QString::fromStdString(info.statusTip)); + comboBox->setToolTip(QString::fromStdString(info.toolTip)); + for (const auto& item : info.items) { + comboBox->addItem(QString::fromStdString(item)); + } + comboBox->setCurrentIndex(prop->get()); + QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); + return comboBox; +} +QCheckBox* +addRow(const CheckBoxUiInfo& info, prtyProperty* prop) +{ + QCheckBox* checkBox = new QCheckBox(); + checkBox->setStatusTip(QString::fromStdString(info.statusTip)); + checkBox->setToolTip(QString::fromStdString(info.toolTip)); + // checkBox->setText(QString::fromStdString(info.formLabel)); + checkBox->setCheckState(prop->get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { + prop->set(state == Qt::CheckState::Checked, true); + }); + return checkBox; +} + +QCameraWidget::QCameraWidget(QWidget* pParent, QCamera* cam, RenderSettings* rs, CameraDataObject* cdo) : QWidget(pParent) , m_MainLayout() , m_renderSettings(rs) @@ -17,18 +224,163 @@ QCameraWidget::QCameraWidget(QWidget* pParent, RenderSettings* rs, CameraDataObj Controls::initFormLayout(m_MainLayout); setLayout(&m_MainLayout); - QNumericSlider* slider = addRow(CameraUiDescription::m_exposure, &m_cameraDataObject->Exposure); + QNumericSlider* slider = addRow(FloatSliderSpinnerUiInfo("Exposure", + "Set Exposure", + "Set camera exposure", + 0.0f, + 1.0f, + 2, // decimals + 0.01, // singleStep + 0 // numTickMarks + ), + &m_cameraDataObject->Exposure); m_MainLayout.addRow("Exposure", slider); - QComboBox* comboBox = addRow(CameraUiDescription::m_exposureIterations, &m_cameraDataObject->ExposureIterations); + QComboBox* comboBox = addRow(ComboBoxUiInfo("Exposure Time", + "Set Exposure Time", + "Set number of samples to accumulate per viewport update", + { "1", "2", "4", "8" }), + &m_cameraDataObject->ExposureIterations); m_MainLayout.addRow("Exposure Time", comboBox); - QCheckBox* checkBox = addRow(CameraUiDescription::m_noiseReduction, &m_cameraDataObject->NoiseReduction); + QCheckBox* checkBox = addRow(CheckBoxUiInfo("Noise Reduction", "Enable denoising pass", "Enable denoising pass"), + &m_cameraDataObject->NoiseReduction); m_MainLayout.addRow("Noise Reduction", checkBox); - QNumericSlider* slider2 = addRow(CameraUiDescription::m_apertureSize, &m_cameraDataObject->ApertureSize); + QNumericSlider* slider2 = addRow(FloatSliderSpinnerUiInfo("Aperture Size", + "Set camera aperture size", + "Set camera aperture size", + 0.0f, + 0.1f, + 2, // decimals + 0.01, // singleStep + 0, // numTickMarks + " mm"), + &m_cameraDataObject->ApertureSize); m_MainLayout.addRow("Aperture Size", slider2); - QNumericSlider* slider3 = addRow(CameraUiDescription::m_fieldOfView, &m_cameraDataObject->FieldOfView); + QNumericSlider* slider3 = addRow(FloatSliderSpinnerUiInfo("Field of view", + "Set camera field of view angle", + "Set camera field of view angle", + 10.0f, + 150.0f, + 2, // decimals + 0.01, // singleStep + 0, // numTickMarks + " deg."), + &m_cameraDataObject->FieldOfView); m_MainLayout.addRow("Field of view", slider3); - QNumericSlider* slider4 = addRow(CameraUiDescription::m_focalDistance, &m_cameraDataObject->FocalDistance); + QNumericSlider* slider4 = addRow(FloatSliderSpinnerUiInfo("Focal distance", + "Set focal distance", + "Set focal distance", + 0.0f, + 15.0f, + 2, // decimals + 0.01, // singleStep + 0, // numTickMarks + " m"), + &m_cameraDataObject->FocalDistance); m_MainLayout.addRow("Focal distance", slider4); + +#if 0 + // Exposure, controls how bright or dim overall scene is + m_ExposureSlider.setStatusTip(tr("Set Exposure")); + m_ExposureSlider.setToolTip(tr("Set camera exposure")); + m_ExposureSlider.setRange(0.0f, 1.0f); + m_ExposureSlider.setValue(cam->GetFilm().GetExposure()); + m_ExposureSlider.setDecimals(2); + m_ExposureSlider.setSingleStep(0.01); + + m_MainLayout.addRow("Exposure", &m_ExposureSlider); + + connect(&m_ExposureSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetExposure); + + // Number of render iterations per viewport update + m_ExposureIterationsSpinner.setStatusTip(tr("Set Exposure Time")); + m_ExposureIterationsSpinner.setToolTip(tr("Set number of samples to accumulate per viewport update")); + m_ExposureIterationsSpinner.addItem("1", 1); + m_ExposureIterationsSpinner.addItem("2", 2); + m_ExposureIterationsSpinner.addItem("4", 4); + m_ExposureIterationsSpinner.addItem("8", 8); + m_ExposureIterationsSpinner.setCurrentIndex( + m_ExposureIterationsSpinner.findData(cam->GetFilm().GetExposureIterations())); + m_MainLayout.addRow("Exposure Time", &m_ExposureIterationsSpinner); + connect(&m_ExposureIterationsSpinner, &QComboBox::currentIndexChanged, this, &QCameraWidget::SetExposureIterations); + + m_NoiseReduction.setStatusTip(tr("Enable denoising pass")); + m_NoiseReduction.setToolTip(tr("Enable denoising pass")); + m_NoiseReduction.setCheckState(rs->m_DenoiseParams.m_Enabled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + m_MainLayout.addRow("Noise Reduction", &m_NoiseReduction); + + connect(&m_NoiseReduction, &QCheckBox::stateChanged, this, &QCameraWidget::OnNoiseReduction); + + m_ApertureSizeSlider.setStatusTip(tr("Set camera aperture size")); + m_ApertureSizeSlider.setToolTip(tr("Set camera aperture size")); + m_ApertureSizeSlider.setRange(0.0, 0.1); + m_ApertureSizeSlider.setSuffix(" mm"); + m_ApertureSizeSlider.setDecimals(2); + m_ApertureSizeSlider.setValue(0.0); + m_ApertureSizeSlider.setSingleStep(0.01); + m_MainLayout.addRow("Aperture Size", &m_ApertureSizeSlider); + + connect(&m_ApertureSizeSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetAperture); + + m_FieldOfViewSlider.setStatusTip(tr("Set camera field of view angle")); + m_FieldOfViewSlider.setToolTip(tr("Set camera field of view angle")); + m_FieldOfViewSlider.setRange(10.0, 150.0); + m_FieldOfViewSlider.setDecimals(2); + m_FieldOfViewSlider.setValue(cam->GetProjection().GetFieldOfView()); + m_FieldOfViewSlider.setSuffix(" deg."); + m_MainLayout.addRow("Field of view", &m_FieldOfViewSlider); + + connect(&m_FieldOfViewSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetFieldOfView); + + // Focal distance + m_FocalDistanceSlider.setStatusTip(tr("Set focal distance")); + m_FocalDistanceSlider.setToolTip(tr("Set focal distance")); + m_FocalDistanceSlider.setRange(0.0, 15.0); + m_FocalDistanceSlider.setDecimals(2); + m_FocalDistanceSlider.setValue(0.0); + m_FocalDistanceSlider.setSuffix(" m"); + + m_MainLayout.addRow("Focal distance", &m_FocalDistanceSlider); + + connect(&m_FocalDistanceSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetFocalDistance); + + QObject::connect(&cam->GetFilm(), SIGNAL(Changed(const QFilm&)), this, SLOT(OnFilmChanged())); + QObject::connect(&cam->GetAperture(), SIGNAL(Changed(const QAperture&)), this, SLOT(OnApertureChanged())); + QObject::connect(&cam->GetProjection(), SIGNAL(Changed(const QProjection&)), this, SLOT(OnProjectionChanged())); + QObject::connect(&cam->GetFocus(), SIGNAL(Changed(const QFocus&)), this, SLOT(OnFocusChanged())); +#endif +} + +void +QCameraWidget::OnFilmChanged() +{ + m_ExposureSlider.setValue(m_qcamera->GetFilm().GetExposure(), true); + m_ExposureIterationsSpinner.blockSignals(true); + m_ExposureIterationsSpinner.setCurrentIndex( + m_ExposureIterationsSpinner.findData(m_qcamera->GetFilm().GetExposureIterations())); + m_ExposureIterationsSpinner.blockSignals(false); + m_NoiseReduction.blockSignals(true); + m_NoiseReduction.setCheckState(m_renderSettings->m_DenoiseParams.m_Enabled ? Qt::CheckState::Checked + : Qt::CheckState::Unchecked); + m_NoiseReduction.blockSignals(false); + emit m_qcamera->Changed(); +} +void +QCameraWidget::OnApertureChanged() +{ + m_ApertureSizeSlider.setValue(m_qcamera->GetAperture().GetSize(), true); + emit m_qcamera->Changed(); +} +void +QCameraWidget::OnProjectionChanged() +{ + m_FieldOfViewSlider.setValue(m_qcamera->GetProjection().GetFieldOfView(), true); + emit m_qcamera->Changed(); +} +void +QCameraWidget::OnFocusChanged() +{ + m_FocalDistanceSlider.setValue(m_qcamera->GetFocus().GetFocalDistance(), true); + emit m_qcamera->Changed(); } QSize diff --git a/agave_app/CameraWidget.h b/agave_app/CameraWidget.h index d7a82379..13731c01 100644 --- a/agave_app/CameraWidget.h +++ b/agave_app/CameraWidget.h @@ -18,7 +18,10 @@ class QCameraWidget : public QWidget Q_OBJECT public: - QCameraWidget(QWidget* pParent = NULL, RenderSettings* rs = nullptr, CameraDataObject* cdo = nullptr); + QCameraWidget(QWidget* pParent = NULL, + QCamera* cam = nullptr, + RenderSettings* rs = nullptr, + CameraDataObject* cdo = nullptr); virtual QSize sizeHint() const; diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index f75fa7a4..f48837d1 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -111,6 +111,7 @@ public slots: private: CameraDataObject* m_cameraDataObject; + QCamera* m_qcamera; QRenderSettings* m_qrendersettings; /// Rendering timer. diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 8a847a5c..38c2775f 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -117,6 +117,8 @@ agaveGui::agaveGui(QWidget* parent) // We need a minimum size or else the size defaults to zero. m_glView->setMinimumSize(256, 512); m_glView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + // create camera ui window now that there is an actual camera. + setupCameraDock(m_glView->getCameraDataObject()); // create camera ui window now that there is an actual camera. setupCameraDock(m_glView->getCameraDataObject()); @@ -351,14 +353,24 @@ void agaveGui::setupCameraDock(CameraDataObject* cdo) { // TODO enable changing/resetting the camera data object shown in this dock? - m_cameradock = new QCameraDockWidget(this, &m_renderSettings, cdo); + m_cameradock = new QCameraDockWidget(this, &m_qcamera, &m_renderSettings, cdo); m_cameradock->setAllowedAreas(Qt::AllDockWidgetAreas); addDockWidget(Qt::RightDockWidgetArea, m_cameradock); } + m_viewMenu->addSeparator(); + m_viewMenu->addAction(m_cameradock->toggleViewAction()); +} + void -agaveGui::setupAppearanceDock() +agaveGui::createDockWindows() { + + m_timelinedock = new QTimelineDockWidget(this, &m_qrendersettings); + m_timelinedock->setAllowedAreas(Qt::AllDockWidgetAreas); + addDockWidget(Qt::RightDockWidgetArea, m_timelinedock); + m_timelinedock->setVisible(false); // hide by default + m_appearanceDockWidget = new QAppearanceDockWidget( this, &m_qrendersettings, &m_renderSettings, m_toggleRotateControlsAction, m_toggleTranslateControlsAction); m_appearanceDockWidget->setAllowedAreas(Qt::AllDockWidgetAreas); @@ -387,8 +399,6 @@ agaveGui::setupStatisticsDock() void agaveGui::addDockItemsToViewMenu() { - m_viewMenu->addSeparator(); - m_viewMenu->addAction(m_cameradock->toggleViewAction()); m_viewMenu->addSeparator(); m_viewMenu->addAction(m_timelinedock->toggleViewAction()); m_viewMenu->addSeparator(); diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h index 2537e700..705b656d 100644 --- a/agave_app/agaveGui.h +++ b/agave_app/agaveGui.h @@ -93,11 +93,8 @@ private slots: void createActions(); void createMenus(); void createToolbars(); - void addDockItemsToViewMenu(); + void createDockWindows(); void setupCameraDock(CameraDataObject* cdo); - void setupTimelineDock(); - void setupAppearanceDock(); - void setupStatisticsDock(); void showOpenFailedMessageBox(QString path); diff --git a/renderlib/CMakeLists.txt b/renderlib/CMakeLists.txt index 86268939..d38bff12 100644 --- a/renderlib/CMakeLists.txt +++ b/renderlib/CMakeLists.txt @@ -28,8 +28,6 @@ target_sources(renderlib PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/CCamera.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/CameraDataObject.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/CameraDataObject.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/CameraUiDescription.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/CameraUiDescription.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/ClipPlaneTool.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ClipPlaneTool.h" "${CMAKE_CURRENT_SOURCE_DIR}/Colormap.cpp" diff --git a/renderlib/CameraDataObject.cpp b/renderlib/CameraDataObject.cpp index 038ba632..269db43b 100644 --- a/renderlib/CameraDataObject.cpp +++ b/renderlib/CameraDataObject.cpp @@ -7,12 +7,30 @@ CameraDataObject::CameraDataObject(CCamera* camera) { updatePropsFromCamera(); // hook up properties to update the underlying camera - Exposure.addCallback([this](prtyProperty* p, bool) { update(); }); - ExposureIterations.addCallback([this](prtyProperty* p, bool) { update(); }); - NoiseReduction.addCallback([this](prtyProperty* p, bool) { update(); }); - ApertureSize.addCallback([this](prtyProperty* p, bool) { update(); }); - FieldOfView.addCallback([this](prtyProperty* p, bool) { update(); }); - FocalDistance.addCallback([this](prtyProperty* p, bool) { update(); }); + Exposure.addCallback([this](prtyProperty* p, bool) { + // LOG_DEBUG << "Setting exposure to " << p->get(); + update(); + }); + ExposureIterations.addCallback([this](prtyProperty* p, bool) { + // LOG_DEBUG << "Setting exposure iterations to " << p->get(); + update(); + }); + NoiseReduction.addCallback([this](prtyProperty* p, bool) { + // LOG_DEBUG << "Setting noise reduction to " << p->get(); + update(); + }); + ApertureSize.addCallback([this](prtyProperty* p, bool) { + // LOG_DEBUG << "Setting aperture size to " << p->get(); + update(); + }); + FieldOfView.addCallback([this](prtyProperty* p, bool) { + // LOG_DEBUG << "Setting field of view to " << p->get(); + update(); + }); + FocalDistance.addCallback([this](prtyProperty* p, bool) { + // LOG_DEBUG << "Setting focal distance to " << p->get(); + update(); + }); } void @@ -21,7 +39,6 @@ CameraDataObject::updatePropsFromCamera() if (m_camera) { Exposure.set(1.0f - m_camera->m_Film.m_Exposure); ExposureIterations.set(m_camera->m_Film.m_ExposureIterations); - // TODO this is not hooked up to the camera properly // NoiseReduction.set(m_camera->m_Film.m_NoiseReduction); ApertureSize.set(m_camera->m_Aperture.m_Size); FieldOfView.set(m_camera->m_FovV); @@ -47,9 +64,6 @@ CameraDataObject::update() m_camera->Update(); - // TODO noise reduction!!! - - // TODO how can I hook this up automatically to the RenderSettings dirty flags? // renderer should pick this up and do the right thing (TM) m_camera->m_Dirty = true; } diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index d5f8080a..6456956b 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -17,8 +17,7 @@ class CameraDataObject CCamera* m_camera; - void updatePropsFromCamera(); - private: void update(); + void updatePropsFromCamera(); }; diff --git a/renderlib/ViewerWindow.cpp b/renderlib/ViewerWindow.cpp index cd747fe5..cda488ea 100644 --- a/renderlib/ViewerWindow.cpp +++ b/renderlib/ViewerWindow.cpp @@ -137,6 +137,10 @@ ViewerWindow::updateCamera() // let renderer know camera is dirty m_renderSettings->m_DirtyFlags.SetFlag(CameraDirty); } + if (m_CCamera.m_Dirty) { + m_renderSettings->m_DirtyFlags.SetFlag(CameraDirty); + m_CCamera.m_Dirty = false; + } sceneView.camera = renderCamera; sceneView.camera.Update(); From 782072a37d4a2814f8ab9b07c172b874d7d427ed Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Mon, 24 Feb 2025 17:13:45 -0800 Subject: [PATCH 02/60] move controls into subdir --- agave_app/CMakeLists.txt | 4 ++ agave_app/CameraWidget.cpp | 100 ---------------------------- agave_app/CameraWidget.h | 1 + agave_app/qtControls/CMakeLists.txt | 2 - agave_app/tfeditor/gradients.cpp | 8 +-- 5 files changed, 8 insertions(+), 107 deletions(-) diff --git a/agave_app/CMakeLists.txt b/agave_app/CMakeLists.txt index 017b0529..cc74ce12 100644 --- a/agave_app/CMakeLists.txt +++ b/agave_app/CMakeLists.txt @@ -29,6 +29,10 @@ target_sources(agaveapp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/cgiparser.h" "${CMAKE_CURRENT_SOURCE_DIR}/commandBuffer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/commandBuffer.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Film.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Film.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Focus.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Focus.h" "${CMAKE_CURRENT_SOURCE_DIR}/GLView3D.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/GLView3D.h" "${CMAKE_CURRENT_SOURCE_DIR}/loadDialog.cpp" diff --git a/agave_app/CameraWidget.cpp b/agave_app/CameraWidget.cpp index c133fbaf..cb382834 100644 --- a/agave_app/CameraWidget.cpp +++ b/agave_app/CameraWidget.cpp @@ -1,93 +1,10 @@ #include "CameraWidget.h" #include "RenderSettings.h" -#include "qtControls/controlFactory.h" - #include "renderlib/uiInfo.hpp" -#include "renderlib/CameraUiDescription.hpp" #include -struct GenericUIInfo -{ - std::string type; - std::string formLabel; - std::string statusTip; - std::string toolTip; - - GenericUIInfo() = default; - GenericUIInfo(std::string type, std::string formLabel, std::string statusTip, std::string toolTip) - : type(type) - , formLabel(formLabel) - , statusTip(statusTip) - , toolTip(toolTip) - { - } -}; -struct CheckBoxUiInfo : public GenericUIInfo -{ - static constexpr const char* TYPE = "CheckBox"; - - CheckBoxUiInfo() { type = CheckBoxUiInfo::TYPE; } - CheckBoxUiInfo(std::string formLabel, std::string statusTip, std::string toolTip) - : GenericUIInfo(CheckBoxUiInfo::TYPE, formLabel, statusTip, toolTip) - { - } -}; -struct ComboBoxUiInfo : public GenericUIInfo -{ - static constexpr const char* TYPE = "ComboBox"; - std::vector items; - - ComboBoxUiInfo() { type = ComboBoxUiInfo::TYPE; } - ComboBoxUiInfo(std::string formLabel, std::string statusTip, std::string toolTip, std::vector items) - : GenericUIInfo(ComboBoxUiInfo::TYPE, formLabel, statusTip, toolTip) - , items(items) - { - } -}; -struct FloatSliderSpinnerUiInfo : public GenericUIInfo -{ - static constexpr const char* TYPE = "FloatSliderSpinner"; - float min = 0.0f; - float max = 0.0f; - int decimals = 0; - float singleStep = 0.0f; - int numTickMarks = 0; - std::string suffix; - - FloatSliderSpinnerUiInfo() { type = FloatSliderSpinnerUiInfo::TYPE; } - FloatSliderSpinnerUiInfo(std::string formLabel, - std::string statusTip, - std::string toolTip, - float min, - float max, - int decimals, - float singleStep, - int numTickMarks = 0, - std::string suffix = "") - : GenericUIInfo(FloatSliderSpinnerUiInfo::TYPE, formLabel, statusTip, toolTip) - , min(min) - , max(max) - , decimals(decimals) - , singleStep(singleStep) - , numTickMarks(numTickMarks) - , suffix(suffix) - { - } -}; -struct IntSliderSpinnerUiInfo : public GenericUIInfo -{ - static constexpr const char* TYPE = "IntSliderSpinner"; - int min; - int max; - int singleStep; - int numTickMarks; - std::string suffix; - - IntSliderSpinnerUiInfo() { type = IntSliderSpinnerUiInfo::TYPE; } -}; - QNumericSlider* create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr> prop) { @@ -152,23 +69,6 @@ create(const ComboBoxUiInfo* info, std::shared_ptr> prop) return comboBox; } -void -createSection(QFormLayout* layout, std::vector controlDescs) -{ - // for (const auto& desc : controlDescs) { - // QLabel* label = new QLabel(QString::fromStdString(desc->formLabel)); - // if (desc->type == CheckBoxUiInfo::TYPE) { - // layout->addRow(label, create(static_cast(desc), )); - // } else if (desc->type == ComboBoxUiInfo::TYPE) { - // layout->addRow(label, create(static_cast(desc))); - // } else if (desc->type == FloatSliderSpinnerUiInfo::TYPE) { - // layout->addRow(label, create(static_cast(desc))); - // } else if (desc->type == IntSliderSpinnerUiInfo::TYPE) { - // layout->addRow(label, create(static_cast(desc))); - // } - // } -} - QNumericSlider* addRow(const FloatSliderSpinnerUiInfo& info, prtyProperty* prop) { diff --git a/agave_app/CameraWidget.h b/agave_app/CameraWidget.h index 13731c01..085a1247 100644 --- a/agave_app/CameraWidget.h +++ b/agave_app/CameraWidget.h @@ -1,5 +1,6 @@ #pragma once +#include "Camera.h" #include "qtControls/Controls.h" #include "renderlib/core/prty/prtyProperty.h" diff --git a/agave_app/qtControls/CMakeLists.txt b/agave_app/qtControls/CMakeLists.txt index 8e8f55a0..506089fd 100644 --- a/agave_app/qtControls/CMakeLists.txt +++ b/agave_app/qtControls/CMakeLists.txt @@ -3,8 +3,6 @@ target_include_directories(agaveapp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ) target_sources(agaveapp PRIVATE -"${CMAKE_CURRENT_SOURCE_DIR}/controlFactory.cpp" -"${CMAKE_CURRENT_SOURCE_DIR}/controlFactory.h" "${CMAKE_CURRENT_SOURCE_DIR}/Controls.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Controls.h" "${CMAKE_CURRENT_SOURCE_DIR}/RangeWidget.cpp" diff --git a/agave_app/tfeditor/gradients.cpp b/agave_app/tfeditor/gradients.cpp index a48f2d0c..4c7b0405 100644 --- a/agave_app/tfeditor/gradients.cpp +++ b/agave_app/tfeditor/gradients.cpp @@ -1,10 +1,8 @@ #include "gradients.h" -#include "Controls.h" -#include "qcustomplot.h" -#include "renderlib/Defines.h" -#include "renderlib/Logging.h" -#include "renderlib/MathUtil.h" +#include "qtControls/Controls.h" +#include "Defines.h" +#include "Logging.h" #include From fe35bc908b480793d484fbffafbf4e8b78907c67 Mon Sep 17 00:00:00 2001 From: DMT Date: Mon, 19 May 2025 18:34:55 -0700 Subject: [PATCH 03/60] add properties for appearance settings --- renderlib/AppearanceDataObject.cpp | 70 +++++++++++++++++++++++++++ renderlib/AppearanceDataObject.hpp | 30 ++++++++++++ renderlib/AppearanceUiDescription.cpp | 56 +++++++++++++++++++++ renderlib/AppearanceUiDescription.hpp | 18 +++++++ renderlib/CMakeLists.txt | 4 ++ renderlib/glm.h | 2 +- renderlib/uiInfo.hpp | 11 +++++ 7 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 renderlib/AppearanceDataObject.cpp create mode 100644 renderlib/AppearanceDataObject.hpp create mode 100644 renderlib/AppearanceUiDescription.cpp create mode 100644 renderlib/AppearanceUiDescription.hpp diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp new file mode 100644 index 00000000..3ef9bf6b --- /dev/null +++ b/renderlib/AppearanceDataObject.cpp @@ -0,0 +1,70 @@ +#include "AppearanceDataObject.hpp" + +#include "Enumerations.h" +#include "Logging.h" + +AppearanceDataOject::AppearanceDataOject(RenderSettings* renderSettings) + : m_renderSettings(renderSettings) +{ + updatePropsFromRenderSettings(); + // hook up properties to update the underlying camera + RendererType.addCallback([this](prtyProperty* p, bool) { update(); }); + ShadingType.addCallback([this](prtyProperty* p, bool) { update(); }); + DensityScale.addCallback([this](prtyProperty* p, bool) { update(); }); + GradientFactor.addCallback([this](prtyProperty* p, bool) { update(); }); + StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool) { update(); }); + StepSizeSecondaryRay.addCallback([this](prtyProperty* p, bool) { update(); }); + Interpolate.addCallback([this](prtyProperty* p, bool) { update(); }); + BackgroundColor.addCallback([this](prtyProperty* p, bool) { update(); }); + ShowBoundingBox.addCallback([this](prtyProperty* p, bool) { update(); }); + BoundingBoxColor.addCallback([this](prtyProperty* p, bool) { update(); }); + ShowScaleBar.addCallback([this](prtyProperty* p, bool) { update(); }); +} + +void +AppearanceDataOject::updatePropsFromRenderSettings() +{ + if (m_renderSettings) { + ShadingType.set(m_renderSettings->m_RenderSettings.m_ShadingType); + // RendererType.set(m_renderSettings->m_RenderSettings.m_RendererType); + DensityScale.set(m_renderSettings->m_RenderSettings.m_DensityScale); + GradientFactor.set(m_renderSettings->m_RenderSettings.m_GradientFactor); + StepSizePrimaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactor); + StepSizeSecondaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); + Interpolate.set(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); + // BackgroundColor.set(glm::vec3(m_renderSettings->m_RenderSettings.m_BackgroundColor[0], + // m_renderSettings->m_RenderSettings.m_BackgroundColor[1], + // m_renderSettings->m_RenderSettings.m_BackgroundColor[2])); + // ShowBoundingBox.set(m_renderSettings->m_RenderSettings.m_ShowBoundingBox); + // BoundingBoxColor.set(glm::vec3(m_renderSettings->m_RenderSettings.m_BoundingBoxColor[0], + // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[1], + // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[2])); + // ShowScaleBar.set(m_renderSettings->m_RenderSettings.m_ShowScaleBar); + } +} +void +AppearanceDataOject::update() +{ + // update low-level object from properties + if (m_renderSettings) { + m_renderSettings->m_RenderSettings.m_ShadingType = ShadingType.get(); + // m_renderSettings->m_RenderSettings.m_RendererType = RendererType.get(); + m_renderSettings->m_RenderSettings.m_DensityScale = DensityScale.get(); + m_renderSettings->m_RenderSettings.m_GradientFactor = GradientFactor.get(); + m_renderSettings->m_RenderSettings.m_StepSizeFactor = StepSizePrimaryRay.get(); + m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = StepSizeSecondaryRay.get(); + m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = Interpolate.get(); + // m_renderSettings->m_RenderSettings.m_BackgroundColor[0] = BackgroundColor.get().x; + // m_renderSettings->m_RenderSettings.m_BackgroundColor[1] = BackgroundColor.get().y; + // m_renderSettings->m_RenderSettings.m_BackgroundColor[2] = BackgroundColor.get().z; + // m_renderSettings->m_RenderSettings.m_ShowBoundingBox = ShowBoundingBox.get(); + // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[0] = BoundingBoxColor.get().x; + // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[1] = BoundingBoxColor.get().y; + // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[2] = BoundingBoxColor.get().z; + // m_renderSettings->m_RenderSettings.m_ShowScaleBar = ShowScaleBar.get(); + + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); + m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); + m_renderSettings->m_DirtyFlags.SetFlag(LightsDirty); + } +} \ No newline at end of file diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp new file mode 100644 index 00000000..a5804064 --- /dev/null +++ b/renderlib/AppearanceDataObject.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "core/prty/prtyProperty.h" +#include "RenderSettings.h" +#include "glm.h" + +class AppearanceDataOject +{ +public: + AppearanceDataOject(RenderSettings* camera); + + prtyProperty RendererType{ "RendererType", 0 }; + prtyProperty ShadingType{ "ShadingType", 0 }; + prtyProperty DensityScale{ "DensityScale", 1.0f }; + prtyProperty GradientFactor{ "GradientFactor", 0.5f }; + prtyProperty StepSizePrimaryRay{ "StepSizePrimaryRay", 1.0f }; + prtyProperty StepSizeSecondaryRay{ "StepSizeSecondaryRay", 1.0f }; + prtyProperty Interpolate{ "Interpolate", false }; + prtyProperty BackgroundColor{ "BackgroundColor", glm::vec3(0.0f, 0.0f, 0.0f) }; + prtyProperty ShowBoundingBox{ "ShowBoundingBox", false }; + prtyProperty BoundingBoxColor{ "BoundingBoxColor", glm::vec3(1.0f, 1.0f, 1.0f) }; + prtyProperty ShowScaleBar{ "ShowScaleBar", false }; + + RenderSettings* m_renderSettings; + + void updatePropsFromRenderSettings(); + +private: + void update(); +}; diff --git a/renderlib/AppearanceUiDescription.cpp b/renderlib/AppearanceUiDescription.cpp new file mode 100644 index 00000000..c8925306 --- /dev/null +++ b/renderlib/AppearanceUiDescription.cpp @@ -0,0 +1,56 @@ +#include "AppearanceUiDescription.hpp" + +ComboBoxUiInfo AppearanceUiDescription::m_rendererType("Renderer Type", + "Select volume rendering type", + "Select volume rendering type", + { "Ray march blending", "Path Traced" }); +ComboBoxUiInfo AppearanceUiDescription::m_shadingType("Shading Type", + "Select volume shading style", + "Select volume shading style", + { "BRDF Only", "Phase Function Only", "Mixed" }); +FloatSliderSpinnerUiInfo AppearanceUiDescription::m_densityScale("Scattering Density", + "Set scattering density for volume", + "Set scattering density for volume", + 0.001f, + 100.0f, + 3, + 0.01f, + 10); +FloatSliderSpinnerUiInfo AppearanceUiDescription::m_gradientFactor("Shading Type Mixture", + "Mix between BRDF and Phase shading", + "Mix between BRDF and Phase shading", + 0.0f, + 1.0f, + 3, + 0.01f, + 10); +FloatSliderSpinnerUiInfo AppearanceUiDescription::m_stepSizePrimaryRay("Primary Ray Step Size", + "Set volume ray march step size for camera rays", + "Set volume ray march step size for camera rays", + 1.0f, + 100.0f, + 3, + 0.01f, + 10); +FloatSliderSpinnerUiInfo AppearanceUiDescription::m_stepSizeSecondaryRay( + "Secondary Ray Step Size", + "Set volume ray march step size for scattered rays", + "Set volume ray march step size for scattered rays", + 1.0f, + 100.0f, + 3, + 0.01f, + 10); +CheckBoxUiInfo AppearanceUiDescription::m_interpolate("Interpolate", + "Interpolated volume sampling", + "Interpolated volume sampling"); +ColorPickerUiInfo AppearanceUiDescription::m_backgroundColor("Background Color", + "Set background color", + "Set background color"); +CheckBoxUiInfo AppearanceUiDescription::m_showBoundingBox("Show Bounding Box", + "Show/hide bounding box", + "Show/hide bounding box"); +ColorPickerUiInfo AppearanceUiDescription::m_boundingBoxColor("Bounding Box Color", + "Set bounding box color", + "Set bounding box color"); +CheckBoxUiInfo AppearanceUiDescription::m_showScaleBar("Show Scale Bar", "Show/hide scale bar", "Show/hide scale bar"); diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceUiDescription.hpp new file mode 100644 index 00000000..6441c56a --- /dev/null +++ b/renderlib/AppearanceUiDescription.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "uiInfo.hpp" + +struct AppearanceUiDescription +{ + static ComboBoxUiInfo m_rendererType; + static ComboBoxUiInfo m_shadingType; + static FloatSliderSpinnerUiInfo m_densityScale; + static FloatSliderSpinnerUiInfo m_gradientFactor; + static FloatSliderSpinnerUiInfo m_stepSizePrimaryRay; + static FloatSliderSpinnerUiInfo m_stepSizeSecondaryRay; + static CheckBoxUiInfo m_interpolate; + static ColorPickerUiInfo m_backgroundColor; + static CheckBoxUiInfo m_showBoundingBox; + static ColorPickerUiInfo m_boundingBoxColor; + static CheckBoxUiInfo m_showScaleBar; +}; diff --git a/renderlib/CMakeLists.txt b/renderlib/CMakeLists.txt index d38bff12..d005e867 100644 --- a/renderlib/CMakeLists.txt +++ b/renderlib/CMakeLists.txt @@ -14,6 +14,10 @@ target_include_directories(renderlib PUBLIC ${GLAD_DIR} ) target_sources(renderlib PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDataObject.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDataObject.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceUiDescription.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceUiDescription.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppScene.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppScene.h" "${CMAKE_CURRENT_SOURCE_DIR}/AreaLightTool.cpp" diff --git a/renderlib/glm.h b/renderlib/glm.h index cfd6acde..93b02f09 100644 --- a/renderlib/glm.h +++ b/renderlib/glm.h @@ -13,4 +13,4 @@ #include #include #include -#include +#include diff --git a/renderlib/uiInfo.hpp b/renderlib/uiInfo.hpp index fcdb86da..21acacd5 100644 --- a/renderlib/uiInfo.hpp +++ b/renderlib/uiInfo.hpp @@ -82,3 +82,14 @@ struct IntSliderSpinnerUiInfo : public GenericUIInfo IntSliderSpinnerUiInfo() { type = IntSliderSpinnerUiInfo::TYPE; } }; + +struct ColorPickerUiInfo : public GenericUIInfo +{ + static constexpr const char* TYPE = "ColorPicker"; + + ColorPickerUiInfo() { type = ColorPickerUiInfo::TYPE; } + ColorPickerUiInfo(std::string formLabel, std::string statusTip, std::string toolTip) + : GenericUIInfo(ColorPickerUiInfo::TYPE, formLabel, statusTip, toolTip) + { + } +}; From a900ea00ba2fd0632a866b57a53bbc798865a0e6 Mon Sep 17 00:00:00 2001 From: dmt Date: Tue, 27 May 2025 22:07:54 -0700 Subject: [PATCH 04/60] compile new widget --- agave_app/AppearanceWidget.cpp | 58 +++++++++++++++++++++++++ agave_app/AppearanceWidget.h | 32 ++++++++++++++ agave_app/CMakeLists.txt | 2 + agave_app/qtControls/controlFactory.cpp | 17 ++++++++ agave_app/qtControls/controlFactory.h | 7 ++- renderlib/AppearanceDataObject.cpp | 10 ++--- renderlib/AppearanceDataObject.hpp | 8 ++-- 7 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 agave_app/AppearanceWidget.cpp create mode 100644 agave_app/AppearanceWidget.h diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp new file mode 100644 index 00000000..b040c519 --- /dev/null +++ b/agave_app/AppearanceWidget.cpp @@ -0,0 +1,58 @@ +#include "AppearanceWidget.h" +#include "RenderSettings.h" + +#include "qtControls/controlFactory.h" + +#include "renderlib/uiInfo.hpp" +#include "renderlib/AppearanceUiDescription.hpp" + +#include + +QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, RenderSettings* rs, AppearanceDataObject* cdo) + : QWidget(pParent) + , m_MainLayout() + , m_renderSettings(rs) + , m_appearanceDataObject(cdo) +{ + Controls::initFormLayout(m_MainLayout); + setLayout(&m_MainLayout); + + QComboBox* rendererType = addRow(AppearanceUiDescription::m_rendererType, &m_appearanceDataObject->RendererType); + m_MainLayout.addRow("Renderer", rendererType); + QComboBox* shadingType = addRow(AppearanceUiDescription::m_shadingType, &m_appearanceDataObject->ShadingType); + m_MainLayout.addRow("Shading Type", shadingType); + QNumericSlider* densityScale = addRow(AppearanceUiDescription::m_densityScale, &m_appearanceDataObject->DensityScale); + m_MainLayout.addRow("Scattering Density", densityScale); + QNumericSlider* gradientFactor = + addRow(AppearanceUiDescription::m_gradientFactor, &m_appearanceDataObject->GradientFactor); + m_MainLayout.addRow("Shading Type Mixture", gradientFactor); + QNumericSlider* stepSizePrimaryRay = + addRow(AppearanceUiDescription::m_stepSizePrimaryRay, &m_appearanceDataObject->StepSizePrimaryRay); + m_MainLayout.addRow("Step Size Primary Ray", stepSizePrimaryRay); + QNumericSlider* stepSizeSecondaryRay = + addRow(AppearanceUiDescription::m_stepSizeSecondaryRay, &m_appearanceDataObject->StepSizeSecondaryRay); + m_MainLayout.addRow("Step Size Secondary Ray", stepSizeSecondaryRay); + QCheckBox* interpolateCheckBox = addRow(AppearanceUiDescription::m_interpolate, &m_appearanceDataObject->Interpolate); + m_MainLayout.addRow("Interpolate", interpolateCheckBox); + QColorPushButton* backgroundColorButton = + addRow(AppearanceUiDescription::m_backgroundColor, &m_appearanceDataObject->BackgroundColor); + m_MainLayout.addRow("Background Color", backgroundColorButton); + QCheckBox* showBoundingBoxCheckBox = + addRow(AppearanceUiDescription::m_showBoundingBox, &m_appearanceDataObject->ShowBoundingBox); + m_MainLayout.addRow("Show Bounding Box", showBoundingBoxCheckBox); + QColorPushButton* boundingBoxColorButton = + addRow(AppearanceUiDescription::m_boundingBoxColor, &m_appearanceDataObject->BoundingBoxColor); + m_MainLayout.addRow("Bounding Box Color", boundingBoxColorButton); + QCheckBox* showScaleBarCheckBox = + addRow(AppearanceUiDescription::m_showScaleBar, &m_appearanceDataObject->ShowScaleBar); + m_MainLayout.addRow("Show Scale Bar", showScaleBarCheckBox); + // QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this](int index) { + // this->m_appearanceDataObject->RendererType.setValue(index); + // }); +} + +QSize +QAppearanceWidget2::sizeHint() const +{ + return QSize(20, 20); +} diff --git a/agave_app/AppearanceWidget.h b/agave_app/AppearanceWidget.h new file mode 100644 index 00000000..7826e4d3 --- /dev/null +++ b/agave_app/AppearanceWidget.h @@ -0,0 +1,32 @@ +#pragma once + +#include "qtControls/Controls.h" + +#include "renderlib/core/prty/prtyProperty.h" +#include "renderlib/AppearanceDataObject.hpp" +#include "renderlib/Logging.h" + +#include +#include +#include +#include + +class RenderSettings; + +class QAppearanceWidget2 : public QWidget +{ + Q_OBJECT + +public: + QAppearanceWidget2(QWidget* pParent = NULL, RenderSettings* rs = nullptr, AppearanceDataObject* cdo = nullptr); + + virtual QSize sizeHint() const; + +private: + QFormLayout m_MainLayout; + + RenderSettings* m_renderSettings; + +private: + AppearanceDataObject* m_appearanceDataObject; +}; diff --git a/agave_app/CMakeLists.txt b/agave_app/CMakeLists.txt index cc74ce12..c4dabb05 100644 --- a/agave_app/CMakeLists.txt +++ b/agave_app/CMakeLists.txt @@ -17,6 +17,8 @@ target_sources(agaveapp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/agaveGui.ui" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDockWidget.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDockWidget.h" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceWidget.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceWidget.h" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceSettingsWidget.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceSettingsWidget.h" "${CMAKE_CURRENT_SOURCE_DIR}/CameraDockWidget.cpp" diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index 9626448d..567af507 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -117,6 +117,7 @@ addRow(const ComboBoxUiInfo& info, prtyProperty* prop) QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); return comboBox; } + QCheckBox* addRow(const CheckBoxUiInfo& info, prtyProperty* prop) { @@ -130,3 +131,19 @@ addRow(const CheckBoxUiInfo& info, prtyProperty* prop) }); return checkBox; } + +QColorPushButton* +addRow(const ColorPickerUiInfo& info, prtyProperty* prop) +{ + QColorPushButton* colorButton = new QColorPushButton(); + colorButton->setStatusTip(QString::fromStdString(info.statusTip)); + colorButton->setToolTip(QString::fromStdString(info.toolTip)); + QColor c = QColor::fromRgbF(prop->get().r, prop->get().g, prop->get().b); + colorButton->SetColor(c, true); + QObject::connect(colorButton, &QColorPushButton::currentColorChanged, [colorButton, prop](const QColor& c) { + // Convert QColor to glm::vec3 + glm::vec3 color(c.redF(), c.greenF(), c.blueF()); + prop->set(color, true); + }); + return colorButton; +} \ No newline at end of file diff --git a/agave_app/qtControls/controlFactory.h b/agave_app/qtControls/controlFactory.h index f127fce7..ab1cceb2 100644 --- a/agave_app/qtControls/controlFactory.h +++ b/agave_app/qtControls/controlFactory.h @@ -2,12 +2,14 @@ #include "renderlib/uiInfo.hpp" #include "renderlib/core/prty/prtyProperty.h" +#include "renderlib/glm.h" #include class QNumericSlider; class QCheckBox; class QComboBox; +class QColorPushButton; QNumericSlider* create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr> prop); @@ -31,4 +33,7 @@ QComboBox* addRow(const ComboBoxUiInfo& info, prtyProperty* prop); QCheckBox* -addRow(const CheckBoxUiInfo& info, prtyProperty* prop); \ No newline at end of file +addRow(const CheckBoxUiInfo& info, prtyProperty* prop); + +QColorPushButton* +addRow(const ColorPickerUiInfo& info, prtyProperty* prop); diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 3ef9bf6b..230d85f8 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -3,13 +3,13 @@ #include "Enumerations.h" #include "Logging.h" -AppearanceDataOject::AppearanceDataOject(RenderSettings* renderSettings) +AppearanceDataObject::AppearanceDataObject(RenderSettings* renderSettings) : m_renderSettings(renderSettings) { updatePropsFromRenderSettings(); // hook up properties to update the underlying camera - RendererType.addCallback([this](prtyProperty* p, bool) { update(); }); - ShadingType.addCallback([this](prtyProperty* p, bool) { update(); }); + RendererType.addCallback([this](prtyProperty* p, bool) { update(); }); + ShadingType.addCallback([this](prtyProperty* p, bool) { update(); }); DensityScale.addCallback([this](prtyProperty* p, bool) { update(); }); GradientFactor.addCallback([this](prtyProperty* p, bool) { update(); }); StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool) { update(); }); @@ -22,7 +22,7 @@ AppearanceDataOject::AppearanceDataOject(RenderSettings* renderSettings) } void -AppearanceDataOject::updatePropsFromRenderSettings() +AppearanceDataObject::updatePropsFromRenderSettings() { if (m_renderSettings) { ShadingType.set(m_renderSettings->m_RenderSettings.m_ShadingType); @@ -43,7 +43,7 @@ AppearanceDataOject::updatePropsFromRenderSettings() } } void -AppearanceDataOject::update() +AppearanceDataObject::update() { // update low-level object from properties if (m_renderSettings) { diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index a5804064..de691ba5 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -4,13 +4,13 @@ #include "RenderSettings.h" #include "glm.h" -class AppearanceDataOject +class AppearanceDataObject { public: - AppearanceDataOject(RenderSettings* camera); + AppearanceDataObject(RenderSettings* camera); - prtyProperty RendererType{ "RendererType", 0 }; - prtyProperty ShadingType{ "ShadingType", 0 }; + prtyProperty RendererType{ "RendererType", 0 }; + prtyProperty ShadingType{ "ShadingType", 0 }; prtyProperty DensityScale{ "DensityScale", 1.0f }; prtyProperty GradientFactor{ "GradientFactor", 0.5f }; prtyProperty StepSizePrimaryRay{ "StepSizePrimaryRay", 1.0f }; From f7c3d30f1ec1ad7303e3ebc03e5382c7c7cd552a Mon Sep 17 00:00:00 2001 From: DMT Date: Sun, 1 Jun 2025 08:42:33 -0700 Subject: [PATCH 05/60] adding the dockwidget --- agave_app/AppearanceDockWidget2.cpp | 16 ++++++++++++++++ agave_app/AppearanceDockWidget2.h | 16 ++++++++++++++++ agave_app/CMakeLists.txt | 2 ++ agave_app/GLView3D.cpp | 5 +++++ agave_app/GLView3D.h | 4 +++- agave_app/agaveGui.cpp | 13 +++++++------ agave_app/agaveGui.h | 5 +++++ renderlib/AppearanceDataObject.hpp | 2 +- 8 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 agave_app/AppearanceDockWidget2.cpp create mode 100644 agave_app/AppearanceDockWidget2.h diff --git a/agave_app/AppearanceDockWidget2.cpp b/agave_app/AppearanceDockWidget2.cpp new file mode 100644 index 00000000..fa40c546 --- /dev/null +++ b/agave_app/AppearanceDockWidget2.cpp @@ -0,0 +1,16 @@ +#include "AppearanceDockWidget2.h" + +QAppearanceDockWidget2::QAppearanceDockWidget2(QWidget* pParent, RenderSettings* rs, AppearanceDataObject* ado) + : QDockWidget(pParent) + , m_AppearanceWidget(nullptr, rs, ado) +{ + setWindowTitle("Appearance"); + + setWidget(&m_AppearanceWidget); + + QSizePolicy SizePolicy; + + SizePolicy.setVerticalPolicy(QSizePolicy::Maximum); + + setSizePolicy(SizePolicy); +} diff --git a/agave_app/AppearanceDockWidget2.h b/agave_app/AppearanceDockWidget2.h new file mode 100644 index 00000000..32c12f09 --- /dev/null +++ b/agave_app/AppearanceDockWidget2.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "AppearanceWidget.h" + +class QAppearanceDockWidget2 : public QDockWidget +{ + Q_OBJECT + +public: + QAppearanceDockWidget2(QWidget* pParent = NULL, RenderSettings* rs = NULL, AppearanceDataObject* cdo = NULL); + +private: + QAppearanceWidget2 m_AppearanceWidget; +}; diff --git a/agave_app/CMakeLists.txt b/agave_app/CMakeLists.txt index c4dabb05..13281672 100644 --- a/agave_app/CMakeLists.txt +++ b/agave_app/CMakeLists.txt @@ -17,6 +17,8 @@ target_sources(agaveapp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/agaveGui.ui" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDockWidget.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDockWidget.h" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDockWidget2.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDockWidget2.h" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceWidget.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceWidget.h" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceSettingsWidget.cpp" diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 6253ec42..f7492272 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -3,6 +3,7 @@ #include "QRenderSettings.h" #include "ViewerState.h" +#include "renderlib/AppearanceDataObject.hpp" #include "renderlib/CameraDataObject.hpp" #include "renderlib/ImageXYZC.h" #include "renderlib/Logging.h" @@ -43,6 +44,7 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, QWidget* parent) // camera is created deep down inside m_viewerWindow. m_cameraDataObject = new CameraDataObject(&m_viewerWindow->m_CCamera); + m_appearanceDataObject = new AppearanceDataObject(rs); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); @@ -128,6 +130,7 @@ GLView3D::onNewImage(Scene* scene) GLView3D::~GLView3D() { delete m_cameraDataObject; + delete m_appearanceDataObject; makeCurrent(); check_gl("view dtor makecurrent"); @@ -479,6 +482,8 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! m_cameraDataObject->updatePropsFromCamera(); + + m_appearanceDataObject->updatePropsFromRenderSettings(); } QPixmap diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index f48837d1..de2c6e0f 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -12,6 +12,7 @@ #include #include +class AppearanceDataObject; class CameraDataObject; class CStatus; class ImageXYZC; @@ -68,6 +69,7 @@ class GLView3D : public QOpenGLWidget const CCamera& getCamera() { return m_viewerWindow->m_CCamera; } // tied to the above camera. CCamera must outlive this: CameraDataObject* getCameraDataObject() { return m_cameraDataObject; } + AppearanceDataObject* getAppearanceDataObject() { return m_appearanceDataObject; } void fromViewerState(const Serialize::ViewerState& s); @@ -111,7 +113,7 @@ public slots: private: CameraDataObject* m_cameraDataObject; - QCamera* m_qcamera; + AppearanceDataObject* m_appearanceDataObject; QRenderSettings* m_qrendersettings; /// Rendering timer. diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 38c2775f..2d774b1c 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -14,6 +14,7 @@ #include "renderlib/version.hpp" #include "AppearanceDockWidget.h" +#include "AppearanceDockWidget2.h" #include "CameraDockWidget.h" #include "Serialize.h" #include "StatisticsDockWidget.h" @@ -124,7 +125,7 @@ agaveGui::agaveGui(QWidget* parent) setupCameraDock(m_glView->getCameraDataObject()); setupTimelineDock(); setupStatisticsDock(); - setupAppearanceDock(); + setupAppearanceDock(m_glView->getAppearanceDataObject()); addDockItemsToViewMenu(); @@ -363,13 +364,13 @@ agaveGui::setupCameraDock(CameraDataObject* cdo) } void -agaveGui::createDockWindows() +agaveGui::setupAppearanceDock(AppearanceDataObject* ado) { + m_appearanceDockWidget2 = new QAppearanceDockWidget2(this, &m_renderSettings, ado); + m_appearanceDockWidget2->setAllowedAreas(Qt::AllDockWidgetAreas); + addDockWidget(Qt::LeftDockWidgetArea, m_appearanceDockWidget2); - m_timelinedock = new QTimelineDockWidget(this, &m_qrendersettings); - m_timelinedock->setAllowedAreas(Qt::AllDockWidgetAreas); - addDockWidget(Qt::RightDockWidgetArea, m_timelinedock); - m_timelinedock->setVisible(false); // hide by default + // original appearance dock widget m_appearanceDockWidget = new QAppearanceDockWidget( this, &m_qrendersettings, &m_renderSettings, m_toggleRotateControlsAction, m_toggleTranslateControlsAction); diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h index 705b656d..a32d9516 100644 --- a/agave_app/agaveGui.h +++ b/agave_app/agaveGui.h @@ -14,6 +14,7 @@ #include class QAppearanceDockWidget; +class QAppearanceDockWidget2; class QCameraDockWidget; class QStatisticsDockWidget; class QTimelineDockWidget; @@ -95,6 +96,9 @@ private slots: void createToolbars(); void createDockWindows(); void setupCameraDock(CameraDataObject* cdo); + void setupTimelineDock(); + void setupAppearanceDock(AppearanceDataObject* ado); + void setupStatisticsDock(); void showOpenFailedMessageBox(QString path); @@ -144,6 +148,7 @@ private slots: QRenderSettings m_qrendersettings; QAppearanceDockWidget* m_appearanceDockWidget; + QAppearanceDockWidget2* m_appearanceDockWidget2; QStatisticsDockWidget* m_statisticsDockWidget; diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index de691ba5..7dfc39cf 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -7,7 +7,7 @@ class AppearanceDataObject { public: - AppearanceDataObject(RenderSettings* camera); + AppearanceDataObject(RenderSettings* rs); prtyProperty RendererType{ "RendererType", 0 }; prtyProperty ShadingType{ "ShadingType", 0 }; From 589f924c9fce2723d7011e94cde95941b8d9adb1 Mon Sep 17 00:00:00 2001 From: dmt Date: Sun, 1 Jun 2025 21:20:46 -0700 Subject: [PATCH 06/60] update tensorstore --- .github/workflows/build_and_test.yml | 10 ++++++++-- .github/workflows/tagged_master_release.yml | 7 ++++++- renderlib/io/CMakeLists.txt | 6 ++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 3b62eada..3aad0000 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -101,6 +101,11 @@ jobs: - uses: actions/checkout@v4 with: submodules: "recursive" + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + architecture: "x64" - name: Install Qt uses: jurplel/install-qt-action@v4 with: @@ -228,10 +233,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up Python + - name: Install Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" + architecture: "x64" - name: Install Dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/tagged_master_release.yml b/.github/workflows/tagged_master_release.yml index afac9d9a..c68a49cb 100644 --- a/.github/workflows/tagged_master_release.yml +++ b/.github/workflows/tagged_master_release.yml @@ -25,6 +25,11 @@ jobs: - uses: actions/checkout@v4 with: submodules: "recursive" + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + architecture: "x64" - name: Install Qt uses: jurplel/install-qt-action@v4 with: @@ -162,7 +167,7 @@ jobs: - name: Install Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.12" architecture: "x64" - name: Install Dependencies run: | diff --git a/renderlib/io/CMakeLists.txt b/renderlib/io/CMakeLists.txt index d9e7bfcf..ef2e6d15 100644 --- a/renderlib/io/CMakeLists.txt +++ b/renderlib/io/CMakeLists.txt @@ -36,10 +36,8 @@ if(APPLE) endif(APPLE) FetchContent_Declare( tensorstore - URL "https://github.com/google/tensorstore/archive/refs/tags/v0.1.78.tar.gz" - URL_HASH SHA256=f59667a32357b8cc0c752429927ad97654f6a67c7d3d62b9efea902c6798d473 - # URL "https://github.com/google/tensorstore/tarball/1461a5247186a84f5be7b632309ca0f5bf05a55e" - # URL_HASH SHA256=1ac9ac2c3a24d0c25f049d289968b4e3944a798a9466b84d80a964b74a2d018a + URL "https://github.com/google/tensorstore/archive/refs/tags/v0.1.75.tar.gz" + URL_HASH SHA256=82f8a170bd6635147315036dcad4e5f32c4d5374a3faa7cdd4e958a15b9cba2e ) FetchContent_MakeAvailable(tensorstore) From bc37293b3484066ca2c6af2fdb213894a8f420d3 Mon Sep 17 00:00:00 2001 From: dmt Date: Mon, 2 Jun 2025 19:25:01 -0700 Subject: [PATCH 07/60] fix python lint --- agave_pyclient/agave_pyclient/agave.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agave_pyclient/agave_pyclient/agave.py b/agave_pyclient/agave_pyclient/agave.py index a35584d9..9f774c8f 100644 --- a/agave_pyclient/agave_pyclient/agave.py +++ b/agave_pyclient/agave_pyclient/agave.py @@ -1028,7 +1028,7 @@ def batch_render_turntable( # then orbit the camera parametrically for i in range(0, number_of_frames): - self.session(f"{output_name}_{i+first_frame}.png") + self.session(f"{output_name}_{i + first_frame}.png") self.redraw() # first frame gets zero orbit, then onward: self.trackball_camera(0.0, direction * (360.0 / float(number_of_frames))) @@ -1069,7 +1069,7 @@ def batch_render_rocker( for i in range(0, number_of_frames): quadrant = (i * 4) // number_of_frames quadrantdirection = 1 if quadrant == 0 or quadrant == 3 else -1 - self.session(f"{output_name}_{i+first_frame}.png") + self.session(f"{output_name}_{i + first_frame}.png") self.redraw() # first frame gets zero orbit, then onward: self.trackball_camera(0.0, angledelta * direction * quadrantdirection) From ec1962983059ca53096ea39b1023a77f12e1133a Mon Sep 17 00:00:00 2001 From: dmt Date: Mon, 2 Jun 2025 19:51:26 -0700 Subject: [PATCH 08/60] appearancedataobject has to affect the Scene also --- agave_app/GLView3D.cpp | 2 +- renderlib/AppearanceDataObject.cpp | 35 +++++++++++++++--------------- renderlib/AppearanceDataObject.hpp | 4 +++- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index f7492272..10bf2909 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -44,7 +44,7 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, QWidget* parent) // camera is created deep down inside m_viewerWindow. m_cameraDataObject = new CameraDataObject(&m_viewerWindow->m_CCamera); - m_appearanceDataObject = new AppearanceDataObject(rs); + m_appearanceDataObject = new AppearanceDataObject(rs, m_viewerWindow->sceneView.m_scene); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 230d85f8..067f1f17 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -3,8 +3,9 @@ #include "Enumerations.h" #include "Logging.h" -AppearanceDataObject::AppearanceDataObject(RenderSettings* renderSettings) +AppearanceDataObject::AppearanceDataObject(RenderSettings* renderSettings, Scene* scene) : m_renderSettings(renderSettings) + , m_scene(scene) { updatePropsFromRenderSettings(); // hook up properties to update the underlying camera @@ -32,14 +33,14 @@ AppearanceDataObject::updatePropsFromRenderSettings() StepSizePrimaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactor); StepSizeSecondaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); Interpolate.set(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); - // BackgroundColor.set(glm::vec3(m_renderSettings->m_RenderSettings.m_BackgroundColor[0], - // m_renderSettings->m_RenderSettings.m_BackgroundColor[1], - // m_renderSettings->m_RenderSettings.m_BackgroundColor[2])); - // ShowBoundingBox.set(m_renderSettings->m_RenderSettings.m_ShowBoundingBox); - // BoundingBoxColor.set(glm::vec3(m_renderSettings->m_RenderSettings.m_BoundingBoxColor[0], - // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[1], - // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[2])); - // ShowScaleBar.set(m_renderSettings->m_RenderSettings.m_ShowScaleBar); + BackgroundColor.set(glm::vec3(m_scene->m_material.m_backgroundColor[0], + m_scene->m_material.m_backgroundColor[1], + m_scene->m_material.m_backgroundColor[2])); + ShowBoundingBox.set(m_scene->m_material.m_showBoundingBox); + BoundingBoxColor.set(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], + m_scene->m_material.m_boundingBoxColor[1], + m_scene->m_material.m_boundingBoxColor[2])); + ShowScaleBar.set(m_scene->m_showScaleBar); } } void @@ -54,14 +55,14 @@ AppearanceDataObject::update() m_renderSettings->m_RenderSettings.m_StepSizeFactor = StepSizePrimaryRay.get(); m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = StepSizeSecondaryRay.get(); m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = Interpolate.get(); - // m_renderSettings->m_RenderSettings.m_BackgroundColor[0] = BackgroundColor.get().x; - // m_renderSettings->m_RenderSettings.m_BackgroundColor[1] = BackgroundColor.get().y; - // m_renderSettings->m_RenderSettings.m_BackgroundColor[2] = BackgroundColor.get().z; - // m_renderSettings->m_RenderSettings.m_ShowBoundingBox = ShowBoundingBox.get(); - // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[0] = BoundingBoxColor.get().x; - // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[1] = BoundingBoxColor.get().y; - // m_renderSettings->m_RenderSettings.m_BoundingBoxColor[2] = BoundingBoxColor.get().z; - // m_renderSettings->m_RenderSettings.m_ShowScaleBar = ShowScaleBar.get(); + m_scene->m_material.m_backgroundColor[0] = BackgroundColor.get().x; + m_scene->m_material.m_backgroundColor[1] = BackgroundColor.get().y; + m_scene->m_material.m_backgroundColor[2] = BackgroundColor.get().z; + m_scene->m_material.m_showBoundingBox = ShowBoundingBox.get(); + m_scene->m_material.m_boundingBoxColor[0] = BoundingBoxColor.get().x; + m_scene->m_material.m_boundingBoxColor[1] = BoundingBoxColor.get().y; + m_scene->m_material.m_boundingBoxColor[2] = BoundingBoxColor.get().z; + m_scene->m_showScaleBar = ShowScaleBar.get(); m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index 7dfc39cf..13a627e8 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -1,13 +1,14 @@ #pragma once #include "core/prty/prtyProperty.h" +#include "AppScene.h" #include "RenderSettings.h" #include "glm.h" class AppearanceDataObject { public: - AppearanceDataObject(RenderSettings* rs); + AppearanceDataObject(RenderSettings* rs, Scene* scene); prtyProperty RendererType{ "RendererType", 0 }; prtyProperty ShadingType{ "ShadingType", 0 }; @@ -22,6 +23,7 @@ class AppearanceDataObject prtyProperty ShowScaleBar{ "ShowScaleBar", false }; RenderSettings* m_renderSettings; + Scene* m_scene; void updatePropsFromRenderSettings(); From bb3ca1c40fb5155d5063a5af9aae6b2e94325cb1 Mon Sep 17 00:00:00 2001 From: DMT Date: Thu, 5 Jun 2025 12:00:53 -0700 Subject: [PATCH 09/60] compile fix --- agave_app/GLView3D.cpp | 2 +- renderlib/AppearanceDataObject.cpp | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 10bf2909..ac615a82 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -44,7 +44,7 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, QWidget* parent) // camera is created deep down inside m_viewerWindow. m_cameraDataObject = new CameraDataObject(&m_viewerWindow->m_CCamera); - m_appearanceDataObject = new AppearanceDataObject(rs, m_viewerWindow->sceneView.m_scene); + m_appearanceDataObject = new AppearanceDataObject(rs, m_viewerWindow->sceneView.scene); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 067f1f17..836c75cf 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -33,14 +33,16 @@ AppearanceDataObject::updatePropsFromRenderSettings() StepSizePrimaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactor); StepSizeSecondaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); Interpolate.set(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); - BackgroundColor.set(glm::vec3(m_scene->m_material.m_backgroundColor[0], - m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2])); - ShowBoundingBox.set(m_scene->m_material.m_showBoundingBox); - BoundingBoxColor.set(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], - m_scene->m_material.m_boundingBoxColor[1], - m_scene->m_material.m_boundingBoxColor[2])); - ShowScaleBar.set(m_scene->m_showScaleBar); + if (m_scene) { + BackgroundColor.set(glm::vec3(m_scene->m_material.m_backgroundColor[0], + m_scene->m_material.m_backgroundColor[1], + m_scene->m_material.m_backgroundColor[2])); + ShowBoundingBox.set(m_scene->m_material.m_showBoundingBox); + BoundingBoxColor.set(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], + m_scene->m_material.m_boundingBoxColor[1], + m_scene->m_material.m_boundingBoxColor[2])); + ShowScaleBar.set(m_scene->m_showScaleBar); + } } } void From ac22497caa5216e6bf1572e9ee030101607e060f Mon Sep 17 00:00:00 2001 From: DMT Date: Fri, 6 Jun 2025 07:33:59 -0700 Subject: [PATCH 10/60] install the scene earlier --- agave_app/GLView3D.cpp | 17 ++++++++--------- agave_app/GLView3D.h | 2 +- agave_app/agaveGui.cpp | 2 +- renderlib/AppearanceDataObject.cpp | 20 ++++++++++---------- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index ac615a82..e8eeeded 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -33,7 +33,7 @@ #pragma warning(disable : 4351) #endif -GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, QWidget* parent) +GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidget* parent) : QOpenGLWidget(parent) , m_etimer() , m_viewerWindow(nullptr) @@ -44,7 +44,7 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, QWidget* parent) // camera is created deep down inside m_viewerWindow. m_cameraDataObject = new CameraDataObject(&m_viewerWindow->m_CCamera); - m_appearanceDataObject = new AppearanceDataObject(rs, m_viewerWindow->sceneView.scene); + m_appearanceDataObject = new AppearanceDataObject(rs, scene); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); @@ -118,13 +118,12 @@ void GLView3D::onNewImage(Scene* scene) { m_viewerWindow->m_renderer->setScene(scene); - // set volume dirty - RenderSettings* rs = m_viewerWindow->m_renderSettings; - rs->m_DirtyFlags.SetFlag(CameraDirty); - rs->m_DirtyFlags.SetFlag(VolumeDirty); - rs->m_DirtyFlags.SetFlag(RenderParamsDirty); - rs->m_DirtyFlags.SetFlag(TransferFunctionDirty); - rs->m_DirtyFlags.SetFlag(LightsDirty); + // costly teardown and rebuild. + this->OnUpdateRenderer(m_viewerWindow->m_rendererType); + // would be better to preserve renderer and just change the scene data to include the new image. + // how tightly coupled is renderer and scene???? + + m_appearanceDataObject->updatePropsFromRenderSettings(); } GLView3D::~GLView3D() diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index de2c6e0f..fd665452 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -40,7 +40,7 @@ class GLView3D : public QOpenGLWidget * @param series the image series. * @param parent the parent of this object. */ - GLView3D(QRenderSettings* qrs, RenderSettings* rs, QWidget* parent = 0); + GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidget* parent = 0); /// Destructor. ~GLView3D(); diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 2d774b1c..3f2196ba 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -112,7 +112,7 @@ agaveGui::agaveGui(QWidget* parent) connect(m_tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); // add the single gl view as a tab - m_glView = new GLView3D(&m_qrendersettings, &m_renderSettings, this); + m_glView = new GLView3D(&m_qrendersettings, &m_renderSettings, &m_appScene, this); QObject::connect(m_glView, SIGNAL(ChangedRenderer()), this, SLOT(OnUpdateRenderer())); m_glView->setObjectName("glcontainer"); // We need a minimum size or else the size defaults to zero. diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 836c75cf..a493c895 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -33,16 +33,16 @@ AppearanceDataObject::updatePropsFromRenderSettings() StepSizePrimaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactor); StepSizeSecondaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); Interpolate.set(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); - if (m_scene) { - BackgroundColor.set(glm::vec3(m_scene->m_material.m_backgroundColor[0], - m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2])); - ShowBoundingBox.set(m_scene->m_material.m_showBoundingBox); - BoundingBoxColor.set(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], - m_scene->m_material.m_boundingBoxColor[1], - m_scene->m_material.m_boundingBoxColor[2])); - ShowScaleBar.set(m_scene->m_showScaleBar); - } + } + if (m_scene) { + BackgroundColor.set(glm::vec3(m_scene->m_material.m_backgroundColor[0], + m_scene->m_material.m_backgroundColor[1], + m_scene->m_material.m_backgroundColor[2])); + ShowBoundingBox.set(m_scene->m_material.m_showBoundingBox); + BoundingBoxColor.set(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], + m_scene->m_material.m_boundingBoxColor[1], + m_scene->m_material.m_boundingBoxColor[2])); + ShowScaleBar.set(m_scene->m_showScaleBar); } } void From 0ac2355b8cfd564f9416bfec0cf4a66a33740d69 Mon Sep 17 00:00:00 2001 From: dmt Date: Mon, 9 Jun 2025 07:32:05 -0700 Subject: [PATCH 11/60] try to hook up changes that need to happen on the ViewerWindow --- agave_app/AppearanceDockWidget2.cpp | 7 +++++-- agave_app/AppearanceDockWidget2.h | 5 ++++- agave_app/AppearanceWidget.cpp | 17 +++++++++++++---- agave_app/AppearanceWidget.h | 6 +++++- agave_app/agaveGui.cpp | 3 ++- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/agave_app/AppearanceDockWidget2.cpp b/agave_app/AppearanceDockWidget2.cpp index fa40c546..1b5403f3 100644 --- a/agave_app/AppearanceDockWidget2.cpp +++ b/agave_app/AppearanceDockWidget2.cpp @@ -1,8 +1,11 @@ #include "AppearanceDockWidget2.h" -QAppearanceDockWidget2::QAppearanceDockWidget2(QWidget* pParent, RenderSettings* rs, AppearanceDataObject* ado) +QAppearanceDockWidget2::QAppearanceDockWidget2(QWidget* pParent, + RenderSettings* rs, + ViewerWindow* vw, + AppearanceDataObject* ado) : QDockWidget(pParent) - , m_AppearanceWidget(nullptr, rs, ado) + , m_AppearanceWidget(nullptr, rs, vw, ado) { setWindowTitle("Appearance"); diff --git a/agave_app/AppearanceDockWidget2.h b/agave_app/AppearanceDockWidget2.h index 32c12f09..1ca4653f 100644 --- a/agave_app/AppearanceDockWidget2.h +++ b/agave_app/AppearanceDockWidget2.h @@ -9,7 +9,10 @@ class QAppearanceDockWidget2 : public QDockWidget Q_OBJECT public: - QAppearanceDockWidget2(QWidget* pParent = NULL, RenderSettings* rs = NULL, AppearanceDataObject* cdo = NULL); + QAppearanceDockWidget2(QWidget* pParent = NULL, + RenderSettings* rs = NULL, + ViewerWindow* vw = NULL, + AppearanceDataObject* cdo = NULL); private: QAppearanceWidget2 m_AppearanceWidget; diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index b040c519..cbb282d3 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -5,10 +5,14 @@ #include "renderlib/uiInfo.hpp" #include "renderlib/AppearanceUiDescription.hpp" +#include "renderlib/ViewerWindow.h" #include -QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, RenderSettings* rs, AppearanceDataObject* cdo) +QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, + RenderSettings* rs, + ViewerWindow* vw, + AppearanceDataObject* cdo) : QWidget(pParent) , m_MainLayout() , m_renderSettings(rs) @@ -46,9 +50,14 @@ QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, RenderSettings* rs, App QCheckBox* showScaleBarCheckBox = addRow(AppearanceUiDescription::m_showScaleBar, &m_appearanceDataObject->ShowScaleBar); m_MainLayout.addRow("Show Scale Bar", showScaleBarCheckBox); - // QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this](int index) { - // this->m_appearanceDataObject->RendererType.setValue(index); - // }); + + // QObject::connect(&m_RendererType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetRendererType(int))); + // QObject::connect(&m_ShadingType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetShadingType(int))); + + QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, &vw](int index) { vw->setRenderer(index); }); + QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, &gradientFactor](int index) { + gradientFactor->setEnabled(index == 2); + }); } QSize diff --git a/agave_app/AppearanceWidget.h b/agave_app/AppearanceWidget.h index 7826e4d3..e9e43361 100644 --- a/agave_app/AppearanceWidget.h +++ b/agave_app/AppearanceWidget.h @@ -12,13 +12,17 @@ #include class RenderSettings; +class ViewerWindow; class QAppearanceWidget2 : public QWidget { Q_OBJECT public: - QAppearanceWidget2(QWidget* pParent = NULL, RenderSettings* rs = nullptr, AppearanceDataObject* cdo = nullptr); + QAppearanceWidget2(QWidget* pParent = NULL, + RenderSettings* rs = nullptr, + ViewerWindow* vw = nullptr, + AppearanceDataObject* cdo = nullptr); virtual QSize sizeHint() const; diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 3f2196ba..c3994e84 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -366,7 +366,8 @@ agaveGui::setupCameraDock(CameraDataObject* cdo) void agaveGui::setupAppearanceDock(AppearanceDataObject* ado) { - m_appearanceDockWidget2 = new QAppearanceDockWidget2(this, &m_renderSettings, ado); + // DANGER see borrowRenderer call + m_appearanceDockWidget2 = new QAppearanceDockWidget2(this, &m_renderSettings, m_glView->borrowRenderer(), ado); m_appearanceDockWidget2->setAllowedAreas(Qt::AllDockWidgetAreas); addDockWidget(Qt::LeftDockWidgetArea, m_appearanceDockWidget2); From 6e52ce99318b00ad9b77bd230810700e43007131 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 11 Jun 2025 16:43:59 -0700 Subject: [PATCH 12/60] don't capture by ref for local variables --- agave_app/AppearanceWidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index cbb282d3..071b54bf 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -54,8 +54,8 @@ QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, // QObject::connect(&m_RendererType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetRendererType(int))); // QObject::connect(&m_ShadingType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetShadingType(int))); - QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, &vw](int index) { vw->setRenderer(index); }); - QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, &gradientFactor](int index) { + QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, vw](int index) { vw->setRenderer(index); }); + QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, gradientFactor](int index) { gradientFactor->setEnabled(index == 2); }); } From 39909becd49e09eaf97c0cb471aad18ac71c468f Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 11 Jun 2025 19:26:57 -0700 Subject: [PATCH 13/60] store renderer type inside of RenderSettings --- agave_app/GLView3D.cpp | 2 +- agave_app/QRenderSettings.cpp | 10 +++++----- agave_app/QRenderSettings.h | 1 - renderlib/AppearanceDataObject.cpp | 4 ++-- renderlib/RenderSettings.cpp | 5 ++++- renderlib/RenderSettings.h | 1 + renderlib/ViewerWindow.cpp | 3 +-- renderlib/ViewerWindow.h | 1 - 8 files changed, 14 insertions(+), 13 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index e8eeeded..ff296918 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -119,7 +119,7 @@ GLView3D::onNewImage(Scene* scene) { m_viewerWindow->m_renderer->setScene(scene); // costly teardown and rebuild. - this->OnUpdateRenderer(m_viewerWindow->m_rendererType); + this->OnUpdateRenderer(m_viewerWindow->m_renderSettings->m_rendererType); // would be better to preserve renderer and just change the scene data to include the new image. // how tightly coupled is renderer and scene???? diff --git a/agave_app/QRenderSettings.cpp b/agave_app/QRenderSettings.cpp index e40e0912..2cc96a5c 100644 --- a/agave_app/QRenderSettings.cpp +++ b/agave_app/QRenderSettings.cpp @@ -4,9 +4,9 @@ QRenderSettings::QRenderSettings(QObject* pParent) : QObject(pParent) - , m_RendererType(1) , m_renderSettings(nullptr) -{} +{ +} QRenderSettings::QRenderSettings(const QRenderSettings& Other) { @@ -73,16 +73,16 @@ QRenderSettings::SetShadingType(const int& ShadingType) int QRenderSettings::GetRendererType(void) const { - return m_RendererType; + return m_renderSettings->m_rendererType; } void QRenderSettings::SetRendererType(const int& RendererType) { - if (RendererType == m_RendererType) + if (RendererType == m_renderSettings->m_rendererType) return; - m_RendererType = RendererType; + m_renderSettings->m_rendererType = RendererType; emit ChangedRenderer(RendererType); } diff --git a/agave_app/QRenderSettings.h b/agave_app/QRenderSettings.h index 71572eda..11a17564 100644 --- a/agave_app/QRenderSettings.h +++ b/agave_app/QRenderSettings.h @@ -32,6 +32,5 @@ class QRenderSettings : public QObject void Selected(SceneObject*); private: - int m_RendererType; RenderSettings* m_renderSettings; }; diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index a493c895..56a816d8 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -27,7 +27,7 @@ AppearanceDataObject::updatePropsFromRenderSettings() { if (m_renderSettings) { ShadingType.set(m_renderSettings->m_RenderSettings.m_ShadingType); - // RendererType.set(m_renderSettings->m_RenderSettings.m_RendererType); + RendererType.set(m_renderSettings->m_rendererType); DensityScale.set(m_renderSettings->m_RenderSettings.m_DensityScale); GradientFactor.set(m_renderSettings->m_RenderSettings.m_GradientFactor); StepSizePrimaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactor); @@ -51,7 +51,7 @@ AppearanceDataObject::update() // update low-level object from properties if (m_renderSettings) { m_renderSettings->m_RenderSettings.m_ShadingType = ShadingType.get(); - // m_renderSettings->m_RenderSettings.m_RendererType = RendererType.get(); + m_renderSettings->m_rendererType = RendererType.get(); m_renderSettings->m_RenderSettings.m_DensityScale = DensityScale.get(); m_renderSettings->m_RenderSettings.m_GradientFactor = GradientFactor.get(); m_renderSettings->m_RenderSettings.m_StepSizeFactor = StepSizePrimaryRay.get(); diff --git a/renderlib/RenderSettings.cpp b/renderlib/RenderSettings.cpp index cce08ce0..a760b300 100644 --- a/renderlib/RenderSettings.cpp +++ b/renderlib/RenderSettings.cpp @@ -5,7 +5,9 @@ RenderSettings::RenderSettings(void) : m_DirtyFlags() , m_DenoiseParams() , m_NoIterations(0) -{} + , m_rendererType(1) +{ +} RenderSettings::RenderSettings(const RenderSettings& Other) { @@ -19,6 +21,7 @@ RenderSettings::operator=(const RenderSettings& Other) m_DenoiseParams = Other.m_DenoiseParams; m_NoIterations = Other.m_NoIterations; m_RenderSettings = Other.m_RenderSettings; + m_rendererType = Other.m_rendererType; return *this; } diff --git a/renderlib/RenderSettings.h b/renderlib/RenderSettings.h index 2ea47aeb..b24f5ba3 100644 --- a/renderlib/RenderSettings.h +++ b/renderlib/RenderSettings.h @@ -10,6 +10,7 @@ class RenderSettings RenderSettings(const RenderSettings& Other); RenderSettings& operator=(const RenderSettings& Other); + int m_rendererType; Flags m_DirtyFlags; PathTraceRenderSettings m_RenderSettings; DenoiseParams m_DenoiseParams; diff --git a/renderlib/ViewerWindow.cpp b/renderlib/ViewerWindow.cpp index cda488ea..044c986a 100644 --- a/renderlib/ViewerWindow.cpp +++ b/renderlib/ViewerWindow.cpp @@ -17,7 +17,6 @@ ViewerWindow::ViewerWindow(RenderSettings* rs) : m_renderSettings(rs) , m_renderer(new RenderGLPT(rs)) , m_gestureRenderer(new GestureRendererGL()) - , m_rendererType(1) { gesture.input.reset(); @@ -327,7 +326,7 @@ ViewerWindow::setRenderer(int rendererType) LOG_DEBUG << "Set OpenGL single pass Renderer"; m_renderer.reset(new RenderGL(m_renderSettings)); }; - m_rendererType = rendererType; + m_renderSettings->m_rendererType = rendererType; // need to update the scene in QAppearanceSettingsWidget. m_renderer->setScene(sc); diff --git a/renderlib/ViewerWindow.h b/renderlib/ViewerWindow.h index 9e2a6335..1aa23f97 100644 --- a/renderlib/ViewerWindow.h +++ b/renderlib/ViewerWindow.h @@ -79,5 +79,4 @@ class ViewerWindow RenderSettings* m_renderSettings; std::unique_ptr m_renderer; - int m_rendererType; }; From 885c175d83632a15e8dd56dc334d92ebb71c2787 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 11 Jun 2025 19:36:44 -0700 Subject: [PATCH 14/60] remove controls that are in the object model --- agave_app/AppearanceSettingsWidget.cpp | 100 ------------------------- renderlib/AppearanceDataObject.cpp | 1 + 2 files changed, 1 insertion(+), 100 deletions(-) diff --git a/agave_app/AppearanceSettingsWidget.cpp b/agave_app/AppearanceSettingsWidget.cpp index f5070e2a..7d082b2f 100644 --- a/agave_app/AppearanceSettingsWidget.cpp +++ b/agave_app/AppearanceSettingsWidget.cpp @@ -111,106 +111,6 @@ QAppearanceSettingsWidget::QAppearanceSettingsWidget(QWidget* pParent, Controls::initFormLayout(m_MainLayout); setLayout(&m_MainLayout); - m_RendererType.setStatusTip(tr("Select volume rendering type")); - m_RendererType.setToolTip(tr("Select volume rendering type")); - - m_RendererType.addItem("Ray march blending", 0); - m_RendererType.addItem("Path Traced", 1); - - m_RendererType.setCurrentIndex(1); - m_MainLayout.addRow("Renderer", &m_RendererType); - - m_DensityScaleSlider.setStatusTip(tr("Set scattering density for volume")); - m_DensityScaleSlider.setToolTip(tr("Set scattering density for volume")); - m_DensityScaleSlider.setRange(0.001, 100.0); - m_DensityScaleSlider.setDecimals(3); - m_DensityScaleSlider.setValue(rs->m_RenderSettings.m_DensityScale); - m_MainLayout.addRow("Scattering Density", &m_DensityScaleSlider); - - m_ShadingType.setStatusTip(tr("Select volume shading style")); - m_ShadingType.setToolTip(tr("Select volume shading style")); - m_ShadingType.addItem("BRDF Only", 0); - m_ShadingType.addItem("Phase Function Only", 1); - m_ShadingType.addItem("Mixed", 2); - m_ShadingType.setCurrentIndex(rs->m_RenderSettings.m_ShadingType); - m_MainLayout.addRow("Shading Type", &m_ShadingType); - - m_GradientFactorSlider.setStatusTip(tr("Mix between BRDF and Phase shading")); - m_GradientFactorSlider.setToolTip(tr("Mix between BRDF and Phase shading")); - m_GradientFactorSlider.setRange(0.0, 1.0); - m_GradientFactorSlider.setDecimals(3); - m_GradientFactorSlider.setValue(rs->m_RenderSettings.m_GradientFactor); - m_MainLayout.addRow("Shading Type Mixture", &m_GradientFactorSlider); - - QObject::connect(&m_DensityScaleSlider, SIGNAL(valueChanged(double)), this, SLOT(OnSetDensityScale(double))); - QObject::connect(&m_GradientFactorSlider, SIGNAL(valueChanged(double)), this, SLOT(OnSetGradientFactor(double))); - - m_StepSizePrimaryRaySlider.setStatusTip(tr("Set volume ray march step size for camera rays")); - m_StepSizePrimaryRaySlider.setToolTip(tr("Set volume ray march step size for camera rays")); - // step size is in voxels and step sizes of less than 1 voxel are not very useful, while slowing down performance - m_StepSizePrimaryRaySlider.setRange(1.0, 100.0); - m_StepSizePrimaryRaySlider.setValue(rs->m_RenderSettings.m_StepSizeFactor); - m_StepSizePrimaryRaySlider.setDecimals(3); - m_MainLayout.addRow("Primary Ray Step Size", &m_StepSizePrimaryRaySlider); - - QObject::connect( - &m_StepSizePrimaryRaySlider, SIGNAL(valueChanged(double)), this, SLOT(OnSetStepSizePrimaryRay(double))); - - m_StepSizeSecondaryRaySlider.setStatusTip(tr("Set volume ray march step size for scattered rays")); - m_StepSizeSecondaryRaySlider.setToolTip(tr("Set volume ray march step size for scattered rays")); - m_StepSizeSecondaryRaySlider.setRange(1.0, 100.0); - m_StepSizeSecondaryRaySlider.setValue(rs->m_RenderSettings.m_StepSizeFactorShadow); - m_StepSizeSecondaryRaySlider.setDecimals(3); - m_MainLayout.addRow("Secondary Ray Step Size", &m_StepSizeSecondaryRaySlider); - - QObject::connect( - &m_StepSizeSecondaryRaySlider, SIGNAL(valueChanged(double)), this, SLOT(OnSetStepSizeSecondaryRay(double))); - - m_interpolateCheckBox.setChecked(true); - m_interpolateCheckBox.setStatusTip(tr("Interpolated volume sampling")); - m_interpolateCheckBox.setToolTip(tr("Interpolated volume sampling")); - m_MainLayout.addRow("Interpolate", &m_interpolateCheckBox); - QObject::connect(&m_interpolateCheckBox, &QCheckBox::clicked, [this](const bool is_checked) { - this->OnInterpolateChecked(is_checked); - }); - - m_backgroundColorButton.setStatusTip(tr("Set background color")); - m_backgroundColorButton.setToolTip(tr("Set background color")); - m_backgroundColorButton.SetColor(QColor(0, 0, 0), true); - m_MainLayout.addRow("Background Color", &m_backgroundColorButton); - - QObject::connect(&m_backgroundColorButton, &QColorPushButton::currentColorChanged, [this](const QColor& c) { - this->OnBackgroundColorChanged(c); - }); - - auto* bboxLayout = new QHBoxLayout(); - m_showBoundingBoxCheckBox.setChecked(false); - m_showBoundingBoxCheckBox.setStatusTip(tr("Show/hide bounding box")); - m_showBoundingBoxCheckBox.setToolTip(tr("Show/hide bounding box")); - bboxLayout->addWidget(&m_showBoundingBoxCheckBox, 0); - - m_boundingBoxColorButton.setStatusTip(tr("Set bounding box color")); - m_boundingBoxColorButton.setToolTip(tr("Set bounding box color")); - m_boundingBoxColorButton.SetColor(QColor(255, 255, 255), true); - bboxLayout->addWidget(&m_boundingBoxColorButton, 1); - - m_MainLayout.addRow("Bounding Box", bboxLayout); - - QObject::connect(&m_showBoundingBoxCheckBox, &QCheckBox::clicked, [this](const bool is_checked) { - this->OnShowBoundsChecked(is_checked); - }); - QObject::connect(&m_boundingBoxColorButton, &QColorPushButton::currentColorChanged, [this](const QColor& c) { - this->OnBoundingBoxColorChanged(c); - }); - - m_showScaleBarCheckBox.setChecked(false); - m_showScaleBarCheckBox.setStatusTip(tr("Show/hide scale bar")); - m_showScaleBarCheckBox.setToolTip(tr("Show/hide scale bar")); - m_MainLayout.addRow("Scale Bar", &m_showScaleBarCheckBox); - QObject::connect(&m_showScaleBarCheckBox, &QCheckBox::clicked, [this](const bool is_checked) { - this->OnShowScaleBarChecked(is_checked); - }); - m_scaleSection = new Section("Volume Scale", 0); auto* scaleSectionLayout = new QGridLayout(); scaleSectionLayout->addWidget(new QLabel("X"), 0, 0); diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 56a816d8..39b386f4 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -45,6 +45,7 @@ AppearanceDataObject::updatePropsFromRenderSettings() ShowScaleBar.set(m_scene->m_showScaleBar); } } + void AppearanceDataObject::update() { From 809bb11c4443df26044e6a92f1b62a2b96379cfb Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 11 Jun 2025 20:58:11 -0700 Subject: [PATCH 15/60] loading from json is broken: the ui does not update to the correct values --- agave_app/AppearanceSettingsWidget.cpp | 53 ------------------------- agave_app/AppearanceSettingsWidget.h | 11 ------ agave_app/AppearanceWidget.cpp | 3 -- renderlib/AppearanceDataObject.cpp | 55 ++++++++++++++++++++------ renderlib/CameraDataObject.cpp | 36 ++++++++--------- 5 files changed, 62 insertions(+), 96 deletions(-) diff --git a/agave_app/AppearanceSettingsWidget.cpp b/agave_app/AppearanceSettingsWidget.cpp index 7d082b2f..78ae4a9d 100644 --- a/agave_app/AppearanceSettingsWidget.cpp +++ b/agave_app/AppearanceSettingsWidget.cpp @@ -99,12 +99,6 @@ QAppearanceSettingsWidget::QAppearanceSettingsWidget(QWidget* pParent, QAction* pToggleTranslateAction) : QGroupBox(pParent) , m_MainLayout() - , m_DensityScaleSlider() - , m_RendererType() - , m_ShadingType() - , m_GradientFactorSlider() - , m_StepSizePrimaryRaySlider() - , m_StepSizeSecondaryRaySlider() , m_qrendersettings(qrs) , m_scene(nullptr) { @@ -221,12 +215,6 @@ QAppearanceSettingsWidget::QAppearanceSettingsWidget(QWidget* pParent, lineA->setFrameShape(QFrame::HLine); lineA->setFrameShadow(QFrame::Sunken); m_MainLayout.addRow(lineA); - - QObject::connect(&m_RendererType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetRendererType(int))); - QObject::connect(&m_ShadingType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetShadingType(int))); - // QObject::connect(&gStatus, SIGNAL(RenderBegin()), this, SLOT(OnRenderBegin())); - - QObject::connect(m_qrendersettings, SIGNAL(Changed()), this, SLOT(OnTransferFunctionChanged())); } void @@ -682,32 +670,12 @@ QAppearanceSettingsWidget::OnSetSkyLightBotColor(double intensity, const QColor& m_qrendersettings->renderSettings()->m_DirtyFlags.SetFlag(LightsDirty); } -void -QAppearanceSettingsWidget::OnRenderBegin(void) -{ - m_DensityScaleSlider.setValue(m_qrendersettings->GetDensityScale()); - m_ShadingType.setCurrentIndex(m_qrendersettings->GetShadingType()); - m_GradientFactorSlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_GradientFactor); - - m_StepSizePrimaryRaySlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_StepSizeFactor, true); - m_StepSizeSecondaryRaySlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_StepSizeFactorShadow, - true); - m_interpolateCheckBox.setChecked(m_qrendersettings->renderSettings()->m_RenderSettings.m_InterpolatedVolumeSampling); -} - void QAppearanceSettingsWidget::OnSetDensityScale(double DensityScale) { m_qrendersettings->SetDensityScale(DensityScale); } -void -QAppearanceSettingsWidget::OnSetShadingType(int Index) -{ - m_qrendersettings->SetShadingType(Index); - m_GradientFactorSlider.setEnabled(Index == 2); -} - void QAppearanceSettingsWidget::OnSetRendererType(int Index) { @@ -734,14 +702,6 @@ QAppearanceSettingsWidget::OnSetStepSizeSecondaryRay(const double& StepSizeSecon m_qrendersettings->renderSettings()->m_DirtyFlags.SetFlag(RenderParamsDirty); } -void -QAppearanceSettingsWidget::OnTransferFunctionChanged(void) -{ - m_DensityScaleSlider.setValue(m_qrendersettings->GetDensityScale(), true); - m_ShadingType.setCurrentIndex(m_qrendersettings->GetShadingType()); - m_GradientFactorSlider.setValue(m_qrendersettings->GetGradientFactor(), true); -} - void QAppearanceSettingsWidget::OnBackgroundColorChanged(const QColor& color) { @@ -972,19 +932,6 @@ QAppearanceSettingsWidget::onNewImage(Scene* scene) return; } - m_DensityScaleSlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_DensityScale); - m_ShadingType.setCurrentIndex(m_qrendersettings->renderSettings()->m_RenderSettings.m_ShadingType); - m_GradientFactorSlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_GradientFactor); - - m_StepSizePrimaryRaySlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_StepSizeFactor); - m_StepSizeSecondaryRaySlider.setValue(m_qrendersettings->renderSettings()->m_RenderSettings.m_StepSizeFactorShadow); - m_interpolateCheckBox.setChecked(m_qrendersettings->renderSettings()->m_RenderSettings.m_InterpolatedVolumeSampling); - - QColor cbg = QColor::fromRgbF(m_scene->m_material.m_backgroundColor[0], - m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2]); - m_backgroundColorButton.SetColor(cbg); - size_t xmax = m_scene->m_volume->sizeX() - 1; size_t ymax = m_scene->m_volume->sizeY() - 1; size_t zmax = m_scene->m_volume->sizeZ() - 1; diff --git a/agave_app/AppearanceSettingsWidget.h b/agave_app/AppearanceSettingsWidget.h index 45899ec5..93d1079a 100644 --- a/agave_app/AppearanceSettingsWidget.h +++ b/agave_app/AppearanceSettingsWidget.h @@ -41,11 +41,8 @@ class QAppearanceSettingsWidget : public QGroupBox void onNewImage(Scene* scene); public slots: - void OnRenderBegin(void); void OnSetDensityScale(double DensityScale); - void OnTransferFunctionChanged(void); void OnSetRendererType(int Index); - void OnSetShadingType(int Index); void OnSetGradientFactor(double GradientFactor); void OnSetStepSizePrimaryRay(const double& StepSizePrimaryRay); void OnSetStepSizeSecondaryRay(const double& StepSizeSecondaryRay); @@ -90,14 +87,6 @@ public slots: Scene* m_scene; QFormLayout m_MainLayout; - QNumericSlider m_DensityScaleSlider; - QComboBox m_RendererType; - QComboBox m_ShadingType; - QNumericSlider m_GradientFactorSlider; - QNumericSlider m_StepSizePrimaryRaySlider; - QNumericSlider m_StepSizeSecondaryRaySlider; - QCheckBox m_interpolateCheckBox; - QColorPushButton m_backgroundColorButton; QRenderSettings* m_qrendersettings; diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index 071b54bf..59033ccf 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -51,9 +51,6 @@ QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, addRow(AppearanceUiDescription::m_showScaleBar, &m_appearanceDataObject->ShowScaleBar); m_MainLayout.addRow("Show Scale Bar", showScaleBarCheckBox); - // QObject::connect(&m_RendererType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetRendererType(int))); - // QObject::connect(&m_ShadingType, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetShadingType(int))); - QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, vw](int index) { vw->setRenderer(index); }); QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, gradientFactor](int index) { gradientFactor->setEnabled(index == 2); diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 39b386f4..1601b132 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -9,17 +9,50 @@ AppearanceDataObject::AppearanceDataObject(RenderSettings* renderSettings, Scene { updatePropsFromRenderSettings(); // hook up properties to update the underlying camera - RendererType.addCallback([this](prtyProperty* p, bool) { update(); }); - ShadingType.addCallback([this](prtyProperty* p, bool) { update(); }); - DensityScale.addCallback([this](prtyProperty* p, bool) { update(); }); - GradientFactor.addCallback([this](prtyProperty* p, bool) { update(); }); - StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool) { update(); }); - StepSizeSecondaryRay.addCallback([this](prtyProperty* p, bool) { update(); }); - Interpolate.addCallback([this](prtyProperty* p, bool) { update(); }); - BackgroundColor.addCallback([this](prtyProperty* p, bool) { update(); }); - ShowBoundingBox.addCallback([this](prtyProperty* p, bool) { update(); }); - BoundingBoxColor.addCallback([this](prtyProperty* p, bool) { update(); }); - ShowScaleBar.addCallback([this](prtyProperty* p, bool) { update(); }); + RendererType.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + ShadingType.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + DensityScale.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + GradientFactor.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + StepSizeSecondaryRay.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + Interpolate.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + BackgroundColor.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + ShowBoundingBox.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + BoundingBoxColor.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); + ShowScaleBar.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); + }); } void diff --git a/renderlib/CameraDataObject.cpp b/renderlib/CameraDataObject.cpp index 269db43b..55c206f6 100644 --- a/renderlib/CameraDataObject.cpp +++ b/renderlib/CameraDataObject.cpp @@ -7,29 +7,29 @@ CameraDataObject::CameraDataObject(CCamera* camera) { updatePropsFromCamera(); // hook up properties to update the underlying camera - Exposure.addCallback([this](prtyProperty* p, bool) { - // LOG_DEBUG << "Setting exposure to " << p->get(); - update(); + Exposure.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); }); - ExposureIterations.addCallback([this](prtyProperty* p, bool) { - // LOG_DEBUG << "Setting exposure iterations to " << p->get(); - update(); + ExposureIterations.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); }); - NoiseReduction.addCallback([this](prtyProperty* p, bool) { - // LOG_DEBUG << "Setting noise reduction to " << p->get(); - update(); + NoiseReduction.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); }); - ApertureSize.addCallback([this](prtyProperty* p, bool) { - // LOG_DEBUG << "Setting aperture size to " << p->get(); - update(); + ApertureSize.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); }); - FieldOfView.addCallback([this](prtyProperty* p, bool) { - // LOG_DEBUG << "Setting field of view to " << p->get(); - update(); + FieldOfView.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); }); - FocalDistance.addCallback([this](prtyProperty* p, bool) { - // LOG_DEBUG << "Setting focal distance to " << p->get(); - update(); + FocalDistance.addCallback([this](prtyProperty* p, bool fromUi) { + if (fromUi) + update(); }); } From 177ff94fd3435fe536321cb1470b22a4be9d1d10 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 18 Jun 2025 16:03:11 -0700 Subject: [PATCH 16/60] fleshing out the property system cleanup --- renderlib/AppearanceDataObject.hpp | 26 +- renderlib/CameraDataObject.hpp | 16 +- renderlib/Logging.h | 19 + renderlib/core/CMakeLists.txt | 1 + renderlib/core/env/envSTLHelpers.hpp | 196 ++++++++++ renderlib/core/prty/.DS_Store | Bin 0 -> 8196 bytes renderlib/core/prty/CMakeLists.txt | 35 +- renderlib/core/prty/prtyBoolean.cpp | 105 +++++ renderlib/core/prty/prtyBoolean.hpp | 61 +++ renderlib/core/prty/prtyEnum.cpp | 79 ++++ renderlib/core/prty/prtyEnum.hpp | 61 +++ renderlib/core/prty/prtyFloat.cpp | 170 ++++++++ renderlib/core/prty/prtyFloat.hpp | 127 ++++++ renderlib/core/prty/prtyInt32.cpp | 150 ++++++++ renderlib/core/prty/prtyInt32.hpp | 73 ++++ renderlib/core/prty/prtyInt8.cpp | 150 ++++++++ renderlib/core/prty/prtyInt8.hpp | 77 ++++ renderlib/core/prty/prtyInterest.cpp | 76 ++++ renderlib/core/prty/prtyInterest.hpp | 59 +++ renderlib/core/prty/prtyInterestUtil.cpp | 77 ++++ renderlib/core/prty/prtyInterestUtil.hpp | 55 +++ renderlib/core/prty/prtyObject.cpp | 209 ++++++++++ renderlib/core/prty/prtyObject.hpp | 103 +++++ renderlib/core/prty/prtyPackage.cpp | 30 ++ renderlib/core/prty/prtyPackage.hpp | 33 ++ renderlib/core/prty/prtyProperty.cpp | 214 +++++++++++ renderlib/core/prty/prtyProperty.h | 133 ------- renderlib/core/prty/prtyProperty.hpp | 233 +++++++++++ renderlib/core/prty/prtyPropertyCallback.hpp | 60 +++ renderlib/core/prty/prtyPropertyReference.cpp | 14 + renderlib/core/prty/prtyPropertyReference.hpp | 56 +++ renderlib/core/prty/prtyPropertyTemplate.hpp | 71 ++++ renderlib/core/prty/prtyPropertyUIInfo.cpp | 206 ++++++++++ renderlib/core/prty/prtyPropertyUIInfo.hpp | 119 ++++++ .../core/prty/prtyPropertyUIInfoContainer.cpp | 328 ++++++++++++++++ .../core/prty/prtyPropertyUIInfoContainer.hpp | 157 ++++++++ renderlib/core/prty/prtyText.cpp | 111 ++++++ renderlib/core/prty/prtyText.hpp | 62 +++ renderlib/core/prty/prtyUndoTemplate.cpp | 9 + renderlib/core/prty/prtyUndoTemplate.hpp | 126 ++++++ renderlib/core/prty/prtyUnits.cpp | 132 +++++++ renderlib/core/prty/prtyUnits.hpp | 90 +++++ renderlib/core/undo/CMakeLists.txt | 11 + renderlib/core/undo/undoMultipleOperation.cpp | 141 +++++++ renderlib/core/undo/undoMultipleOperation.hpp | 97 +++++ .../core/undo/undoMultipleOperationBlock.hpp | 47 +++ renderlib/core/undo/undoUndoInterest.cpp | 9 + renderlib/core/undo/undoUndoInterest.hpp | 29 ++ renderlib/core/undo/undoUndoMgr.cpp | 362 ++++++++++++++++++ renderlib/core/undo/undoUndoMgr.hpp | 144 +++++++ renderlib/core/undo/undoUndoOperation.cpp | 58 +++ renderlib/core/undo/undoUndoOperation.hpp | 69 ++++ 52 files changed, 4923 insertions(+), 153 deletions(-) create mode 100644 renderlib/core/env/envSTLHelpers.hpp create mode 100644 renderlib/core/prty/.DS_Store create mode 100644 renderlib/core/prty/prtyBoolean.cpp create mode 100644 renderlib/core/prty/prtyBoolean.hpp create mode 100644 renderlib/core/prty/prtyEnum.cpp create mode 100644 renderlib/core/prty/prtyEnum.hpp create mode 100644 renderlib/core/prty/prtyFloat.cpp create mode 100644 renderlib/core/prty/prtyFloat.hpp create mode 100644 renderlib/core/prty/prtyInt32.cpp create mode 100644 renderlib/core/prty/prtyInt32.hpp create mode 100644 renderlib/core/prty/prtyInt8.cpp create mode 100644 renderlib/core/prty/prtyInt8.hpp create mode 100644 renderlib/core/prty/prtyInterest.cpp create mode 100644 renderlib/core/prty/prtyInterest.hpp create mode 100644 renderlib/core/prty/prtyInterestUtil.cpp create mode 100644 renderlib/core/prty/prtyInterestUtil.hpp create mode 100644 renderlib/core/prty/prtyObject.cpp create mode 100644 renderlib/core/prty/prtyObject.hpp create mode 100644 renderlib/core/prty/prtyPackage.cpp create mode 100644 renderlib/core/prty/prtyPackage.hpp create mode 100644 renderlib/core/prty/prtyProperty.cpp delete mode 100644 renderlib/core/prty/prtyProperty.h create mode 100644 renderlib/core/prty/prtyProperty.hpp create mode 100644 renderlib/core/prty/prtyPropertyCallback.hpp create mode 100644 renderlib/core/prty/prtyPropertyReference.cpp create mode 100644 renderlib/core/prty/prtyPropertyReference.hpp create mode 100644 renderlib/core/prty/prtyPropertyTemplate.hpp create mode 100644 renderlib/core/prty/prtyPropertyUIInfo.cpp create mode 100644 renderlib/core/prty/prtyPropertyUIInfo.hpp create mode 100644 renderlib/core/prty/prtyPropertyUIInfoContainer.cpp create mode 100644 renderlib/core/prty/prtyPropertyUIInfoContainer.hpp create mode 100644 renderlib/core/prty/prtyText.cpp create mode 100644 renderlib/core/prty/prtyText.hpp create mode 100644 renderlib/core/prty/prtyUndoTemplate.cpp create mode 100644 renderlib/core/prty/prtyUndoTemplate.hpp create mode 100644 renderlib/core/prty/prtyUnits.cpp create mode 100644 renderlib/core/prty/prtyUnits.hpp create mode 100644 renderlib/core/undo/CMakeLists.txt create mode 100644 renderlib/core/undo/undoMultipleOperation.cpp create mode 100644 renderlib/core/undo/undoMultipleOperation.hpp create mode 100644 renderlib/core/undo/undoMultipleOperationBlock.hpp create mode 100644 renderlib/core/undo/undoUndoInterest.cpp create mode 100644 renderlib/core/undo/undoUndoInterest.hpp create mode 100644 renderlib/core/undo/undoUndoMgr.cpp create mode 100644 renderlib/core/undo/undoUndoMgr.hpp create mode 100644 renderlib/core/undo/undoUndoOperation.cpp create mode 100644 renderlib/core/undo/undoUndoOperation.hpp diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index 13a627e8..74ee491d 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -1,6 +1,8 @@ #pragma once -#include "core/prty/prtyProperty.h" +#include "core/prty/prtyInt8.hpp" +#include "core/prty/prtyFloat.hpp" +#include "core/prty/prtyBoolean.hpp" #include "AppScene.h" #include "RenderSettings.h" #include "glm.h" @@ -10,17 +12,17 @@ class AppearanceDataObject public: AppearanceDataObject(RenderSettings* rs, Scene* scene); - prtyProperty RendererType{ "RendererType", 0 }; - prtyProperty ShadingType{ "ShadingType", 0 }; - prtyProperty DensityScale{ "DensityScale", 1.0f }; - prtyProperty GradientFactor{ "GradientFactor", 0.5f }; - prtyProperty StepSizePrimaryRay{ "StepSizePrimaryRay", 1.0f }; - prtyProperty StepSizeSecondaryRay{ "StepSizeSecondaryRay", 1.0f }; - prtyProperty Interpolate{ "Interpolate", false }; - prtyProperty BackgroundColor{ "BackgroundColor", glm::vec3(0.0f, 0.0f, 0.0f) }; - prtyProperty ShowBoundingBox{ "ShowBoundingBox", false }; - prtyProperty BoundingBoxColor{ "BoundingBoxColor", glm::vec3(1.0f, 1.0f, 1.0f) }; - prtyProperty ShowScaleBar{ "ShowScaleBar", false }; + prtyInt8 RendererType{ "RendererType", 0 }; + prtyInt8 ShadingType{ "ShadingType", 0 }; + prtyFloat DensityScale{ "DensityScale", 1.0f }; + prtyFloat GradientFactor{ "GradientFactor", 0.5f }; + prtyFloat StepSizePrimaryRay{ "StepSizePrimaryRay", 1.0f }; + prtyFloat StepSizeSecondaryRay{ "StepSizeSecondaryRay", 1.0f }; + prtyBoolean Interpolate{ "Interpolate", false }; + prtyVec3 BackgroundColor{ "BackgroundColor", glm::vec3(0.0f, 0.0f, 0.0f) }; + prtyBoolean ShowBoundingBox{ "ShowBoundingBox", false }; + prtyVec3 BoundingBoxColor{ "BoundingBoxColor", glm::vec3(1.0f, 1.0f, 1.0f) }; + prtyBoolean ShowScaleBar{ "ShowScaleBar", false }; RenderSettings* m_renderSettings; Scene* m_scene; diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index 6456956b..a11924c9 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -1,6 +1,8 @@ #pragma once -#include "core/prty/prtyProperty.h" +#include "core/prty/prtyFloat.hpp" +#include "core/prty/prtyInt8.hpp" +#include "core/prty/prtyBoolean.hpp" #include "CCamera.h" class CameraDataObject @@ -8,12 +10,12 @@ class CameraDataObject public: CameraDataObject(CCamera* camera); - prtyProperty Exposure{ "Exposure", 0.75f }; - prtyProperty ExposureIterations{ "ExposureIterations", 1 }; - prtyProperty NoiseReduction{ "NoiseReduction", false }; - prtyProperty ApertureSize{ "ApertureSize", 0.0f }; - prtyProperty FieldOfView{ "FieldOfView", 30.0f }; - prtyProperty FocalDistance{ "FocalDistance", 0.0f }; + prtyFloat Exposure{ "Exposure", 0.75f }; + prtyInt8 ExposureIterations{ "ExposureIterations", 1 }; + prtyBoolean NoiseReduction{ "NoiseReduction", false }; + prtyFloat ApertureSize{ "ApertureSize", 0.0f }; + prtyFloat FieldOfView{ "FieldOfView", 30.0f }; + prtyFloat FocalDistance{ "FocalDistance", 0.0f }; CCamera* m_camera; diff --git a/renderlib/Logging.h b/renderlib/Logging.h index 762e420a..2100ce1b 100644 --- a/renderlib/Logging.h +++ b/renderlib/Logging.h @@ -65,3 +65,22 @@ void Enable(bool enabled); }; + +#if defined(_DEBUG) || defined(DEBUG) || defined(_DEBUG) +#define DBG_ASSERT(condition, message) \ + do { \ + \ + if (!(condition)) \ + { \ + LOG_ERROR << "Assertion failed: " << #condition << ", message: " << message; \ + std::abort(); \ + } \ + } while (false) +#else +#define DBG_ASSERT(condition, message) \ + do { \ + if (!(condition)) { \ + LOG_ERROR << "Assertion failed: " << #condition << ", message: " << message; \ + } \ + } while (false) +#endif \ No newline at end of file diff --git a/renderlib/core/CMakeLists.txt b/renderlib/core/CMakeLists.txt index bded3c29..c5301ab1 100644 --- a/renderlib/core/CMakeLists.txt +++ b/renderlib/core/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(prty) +add_subdirectory(undo) diff --git a/renderlib/core/env/envSTLHelpers.hpp b/renderlib/core/env/envSTLHelpers.hpp new file mode 100644 index 00000000..7c7eccf4 --- /dev/null +++ b/renderlib/core/env/envSTLHelpers.hpp @@ -0,0 +1,196 @@ +/****************************************************************************\ +** envSTLHelpers.hpp +** +** envSTLHelpers is meant to contain definitions useful when using the +** STL in our library. +** +** +** +\****************************************************************************/ + +#ifdef ENV_STLHELPERS_HPP +#error envSTLHelpers.hpp multiple included +#endif +#define ENV_STLHELPERS_HPP + +#include // for_each +#include + +//============================================================================ +// envSTLHelpers +//============================================================================ +namespace envSTLHelpers { + +//---------------------------------------------------------------------------- +// DeleteContainer is meant to be used on containers of pointers. It will +// delete every object in the container and empty the container. +//---------------------------------------------------------------------------- +template +void +DeleteContainer(C& io_Container) +{ + typename C::iterator it = io_Container.begin(); + typename C::iterator end = io_Container.end(); + + while (it != end) { + delete *it; + ++it; + } + + io_Container.clear(); +} + +//---------------------------------------------------------------------------- +// copy_if is the "missing" STL function which copies only if the predicate +// returns true. +//---------------------------------------------------------------------------- +template +Out +copy_if(In first, In last, Out res, Pred p) +{ + while (first != last) { + if (p(*first)) + *res++ = *first; + ++first; + } + + return res; +} + +//---------------------------------------------------------------------------- +// ForEachPair calls the given function object for each unique pair +// combination of objects in the given sequence. (Objects are not paired +// with themselves). This can be visualized as all of the combinations +// in the lower triangle of a matrix (not including the diagonal). +//---------------------------------------------------------------------------- +template +inline void +ForEachPair(Iterator i_Begin, Iterator i_End, Function i_Function) +{ + if (i_Begin == i_End) + return; // no objects + + Iterator outer = i_Begin; + Iterator next_to_last = i_End; + --next_to_last; + + for (; outer != next_to_last; ++outer) { + Iterator inner = outer; + ++inner; + + for (; inner != i_End; ++inner) + i_Function(*outer, *inner); + } +} + +//---------------------------------------------------------------------------- +// ForAll works the same way as if you called std::for_each passing +// in the begin and end iterators. +//---------------------------------------------------------------------------- +template +inline void +ForAll(Container& i_Container, Function i_Function) +{ + std::for_each(i_Container.begin(), i_Container.end(), i_Function); +} + +//---------------------------------------------------------------------------- +// ForAll works the same way as if you called std::for_each passing +// in the begin and end iterators. +//---------------------------------------------------------------------------- +template +inline void +RForAll(Container& i_Container, Function i_Function) +{ + std::for_each(i_Container.rbegin(), i_Container.rend(), i_Function); +} + +//---------------------------------------------------------------------------- +// ForAllForAll is used for nested containers. It will call the function on +// each item in the nested vectors. +//---------------------------------------------------------------------------- +template +inline void +ForAllForAll(Container& i_Container, Function i_Function) +{ + typename Container::iterator it, end = i_Container.end(); + for (it = i_Container.begin(); it != end; ++it) { + ForAll(*it, i_Function); + } +} + +//---------------------------------------------------------------------------- +// RemoveOneValue +//---------------------------------------------------------------------------- +template +bool +RemoveOneValue(C& io_Container, const V& i_Value) +{ + typename C::iterator it = io_Container.begin(); + typename C::iterator end = io_Container.end(); + + while (it != end) { + if (*it == i_Value) { + io_Container.erase(it); + return true; + } + ++it; + } + return false; +} + +//---------------------------------------------------------------------------- +// RemoveAllValues +//---------------------------------------------------------------------------- +template +void +RemoveAllValues(C& io_Container, const V& i_Value) +{ + typename C::iterator it = io_Container.begin(); + + while (it != io_Container.end()) { + if (*it == i_Value) + it = io_Container.erase(it); + else + ++it; + } +} + +//---------------------------------------------------------------------------- +// DeleteOneValue +//---------------------------------------------------------------------------- +template +bool +DeleteOneValue(C& io_Container, const V& i_Value) +{ + typename C::iterator it = io_Container.begin(); + typename C::iterator end = io_Container.end(); + + while (it != end) { + if (*it == i_Value) { + delete (*it); + io_Container.erase(it); + return true; + } + ++it; + } + return false; +} + +//---------------------------------------------------------------------------- +// Contains - returns true if value exists in container +//---------------------------------------------------------------------------- +template +bool +Contains(C& io_Container, const V& i_Value) +{ + typename C::const_iterator it, end = io_Container.end(); + for (it = io_Container.begin(); it != end; ++it) { + if (*it == i_Value) { + return true; + } + } + return false; +} + +} diff --git a/renderlib/core/prty/.DS_Store b/renderlib/core/prty/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..befacae59005b7afd78a32f2c110c71e110e8c9c GIT binary patch literal 8196 zcmeHMO>fgc5Pe&Es04%}AruZs{sobM3rCZ-NRgd!0+Qk z-^{EW+wmTuNX%Nhv)SD@AJ1!VCIJwpm+u|{V*op>B6n}H87ML@b)#&>k-LxKtX`Y}XTTY72AlzB;9q2bXSS4`#JO*?-Z}%$z<n2nI)pmP5=?f?6jo)8z=c zNpGD2XJC^7$=yfT!y)GQ)XCo`%;LYInib`8QIrd=lSk_r>*Ti<_JBLMz-O-fhAB#3 z1$E4EjtM?+=Aw%Z-+Sm=4f=qXOPnQezk0aa4emKDmb6$6BezbH$QdnGc!I~nNc<%7 zM=R2`uZDb@zzIWb+-~Em;a22prN5C3bM&z1@x3JenEszK{$V}jER0(Ij~YEMvA{?A zuuQS0u@B$nBXYguPMPC`8Yb*--epG6vAo_ReRN`vbkJ-5j>ud|d%~dXxMbWN{>M$+ zef%DyD0nSmOoRG#2et3#gQUJ!^z6NQx8mMfDnA1e$}`l7Fzw+R>Numlf*w{$ecY)X zefN_d9%IJqoL-g*_T&j|N4wtj;tSsg37qWOHjc-1#vz{Hc7RjX_L)5vKmU~mZ=8W^ zW8j8a9!vgzkpBJu+Wd3F&VV!U=NSmw`>*$>v|~r}ra{TIGuF4PQe<6iQXy<)iHvJH dPTBln$bJ^*@+fPQoMG`V0!o87&cI(~;0k4IE9C$H literal 0 HcmV?d00001 diff --git a/renderlib/core/prty/CMakeLists.txt b/renderlib/core/prty/CMakeLists.txt index ad102c3f..abbb170d 100644 --- a/renderlib/core/prty/CMakeLists.txt +++ b/renderlib/core/prty/CMakeLists.txt @@ -1,3 +1,36 @@ target_sources(renderlib PRIVATE -"${CMAKE_CURRENT_SOURCE_DIR}/prtyProperty.h" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyEnum.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyEnum.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyFloat.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyFloat.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInt32.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInt32.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInt8.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInt8.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInterest.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInterest.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInterestUtil.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyInterestUtil.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyObject.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyObject.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPackage.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPackage.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyProperty.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyProperty.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyCallback.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyReference.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyReference.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyTemplate.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfo.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfo.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfoContainer.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfoContainer.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyText.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyText.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyUndoTemplate.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyUndoTemplate.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyUnits.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyUnits.hpp" ) \ No newline at end of file diff --git a/renderlib/core/prty/prtyBoolean.cpp b/renderlib/core/prty/prtyBoolean.cpp new file mode 100644 index 00000000..5efd33b1 --- /dev/null +++ b/renderlib/core/prty/prtyBoolean.cpp @@ -0,0 +1,105 @@ +/****************************************************************************\ +** prtyBoolean.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyBoolean.hpp" + +// #include "core/ch/chReader.hpp" +// #include "core/ch/chWriter.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyBoolean::prtyBoolean() + : prtyPropertyTemplate("Boolean", false) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyBoolean::prtyBoolean(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, false) +{ +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyBoolean::prtyBoolean(const std::string& i_Name, bool i_bInitialValue) + : prtyPropertyTemplate(i_Name, i_bInitialValue) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyBoolean::GetType() +{ + return "Boolean"; +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyBoolean& +prtyBoolean::operator=(const prtyBoolean& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + + SetValue(i_Property.GetValue()); + return *this; +} +prtyBoolean& +prtyBoolean::operator=(const bool i_Value) +{ + SetValue(i_Value); + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyBoolean::operator==(const prtyBoolean& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyBoolean::operator!=(const prtyBoolean& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyBoolean::operator==(const bool i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyBoolean::operator!=(const bool i_Value) const +{ + return (m_Value != i_Value); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyBoolean::Read(chReader& io_Reader) +{ + // bool temp; + // io_Reader.Read(temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyBoolean::Write(chWriter& io_Writer) const +{ + // io_Writer.Write(GetValue()); +} diff --git a/renderlib/core/prty/prtyBoolean.hpp b/renderlib/core/prty/prtyBoolean.hpp new file mode 100644 index 00000000..92adebd2 --- /dev/null +++ b/renderlib/core/prty/prtyBoolean.hpp @@ -0,0 +1,61 @@ +/****************************************************************************\ +** prtyBoolean.hpp +** +** Boolean property +** +** +** +\****************************************************************************/ +#ifdef PRTY_BOOLEAN_HPP +#error prtyBoolean.hpp multiply included +#endif +#define PRTY_BOOLEAN_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +//============================================================================ +//============================================================================ +class prtyBoolean : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyBoolean(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyBoolean(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyBoolean(const std::string& i_Name, bool i_bInitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyBoolean& operator=(const prtyBoolean& i_Property); + prtyBoolean& operator=(const bool i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyBoolean& i_Property) const; + bool operator!=(const prtyBoolean& i_Property) const; + bool operator==(const bool i_Value) const; + bool operator!=(const bool i_Value) const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; +}; diff --git a/renderlib/core/prty/prtyEnum.cpp b/renderlib/core/prty/prtyEnum.cpp new file mode 100644 index 00000000..d09ce87f --- /dev/null +++ b/renderlib/core/prty/prtyEnum.cpp @@ -0,0 +1,79 @@ +/****************************************************************************\ +** prtyEnum.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyEnum.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyEnum::prtyEnum() + : prtyInt8("Enum") +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyEnum::prtyEnum(const std::string& i_Name) + : prtyInt8(i_Name) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyEnum::prtyEnum(const std::string& i_Name, const char& i_InitialValue) + : prtyInt8(i_Name, i_InitialValue) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyEnum::GetType() +{ + return "Enum"; +} + +//-------------------------------------------------------------------- +// Set an EnumTag - these will get displayed (in a combobox for +// instance) +//-------------------------------------------------------------------- +void +prtyEnum::SetEnumTag(int i_Index, const std::string& i_Tag) +{ + if (i_Index >= (int)m_EnumTags.size()) { + m_EnumTags.resize(i_Index + 1); + } + m_EnumTags[i_Index] = i_Tag; + + // int numtags = m_EnumTags.size(); + // this->SetMaximum(numtags); +} + +const std::string& +prtyEnum::GetEnumTag(int i_Index) +{ + return m_EnumTags[i_Index]; +} + +//-------------------------------------------------------------------- +// Return number of enumeration tags +//-------------------------------------------------------------------- +int +prtyEnum::GetNumTags() const +{ + return m_EnumTags.size(); +} + +//-------------------------------------------------------------------- +// Clear enum tags +//-------------------------------------------------------------------- +void +prtyEnum::ClearTags() +{ + m_EnumTags.clear(); +} \ No newline at end of file diff --git a/renderlib/core/prty/prtyEnum.hpp b/renderlib/core/prty/prtyEnum.hpp new file mode 100644 index 00000000..d069fe5a --- /dev/null +++ b/renderlib/core/prty/prtyEnum.hpp @@ -0,0 +1,61 @@ +/****************************************************************************\ +** prtyEnum.hpp +** +** Enum property +** +** +** +\****************************************************************************/ +#ifdef PRTY_ENUM_HPP +#error prtyEnum.hpp multiply included +#endif +#define PRTY_ENUM_HPP + +#ifndef PRTY_INT8_HPP +#include "core/prty/prtyInt8.hpp" +#endif + +#include + +//============================================================================ +//============================================================================ +class prtyEnum : public prtyInt8 +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyEnum(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyEnum(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyEnum(const std::string& i_Name, const char& i_InitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // Set an EnumTag - these will get displayed (in a combobox for + // instance) + //-------------------------------------------------------------------- + void SetEnumTag(int i_Index, const std::string& i_Tag); + const std::string& GetEnumTag(int i_Index); + + //-------------------------------------------------------------------- + // Return number of enumeration tags + //-------------------------------------------------------------------- + int GetNumTags() const; + + //-------------------------------------------------------------------- + // Clear enum tags + //-------------------------------------------------------------------- + void ClearTags(); + +public: + std::vector m_EnumTags; // tags to display for this enum +}; diff --git a/renderlib/core/prty/prtyFloat.cpp b/renderlib/core/prty/prtyFloat.cpp new file mode 100644 index 00000000..d1ad6f49 --- /dev/null +++ b/renderlib/core/prty/prtyFloat.cpp @@ -0,0 +1,170 @@ +/****************************************************************************\ +** prtyFloat.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyFloat.hpp" +#include "core/prty/prtyUnits.hpp" + +// #include "core/ch/chReader.hpp" +// #include "core/ch/chWriter.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyFloat::prtyFloat() + : prtyPropertyTemplate("Float", 0.0f) + , m_bUseUnits(false) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyFloat::prtyFloat(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, 0.0f) + , m_bUseUnits(false) +{ +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyFloat::prtyFloat(const std::string& i_Name, float i_fInitialValue) + : prtyPropertyTemplate(i_Name, i_fInitialValue) + , m_bUseUnits(false) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyFloat::GetType() +{ + return "Float"; +} + +//-------------------------------------------------------------------- +// Set whether this property should consider the current units +// when displaying its value in the user interface. +//-------------------------------------------------------------------- +bool +prtyFloat::GetUseUnits() const +{ + return m_bUseUnits; +} +void +prtyFloat::SetUseUnits(bool i_bUseUnits) +{ + m_bUseUnits = i_bUseUnits; +} + +//-------------------------------------------------------------------- +// Get and Set value in the current display units. +// Converts to internal units and then calls Get/SetValue() +//-------------------------------------------------------------------- +float +prtyFloat::GetScaledValue() const +{ + if (this->GetUseUnits()) + return (this->GetValue() / prtyUnits::GetUnitScaling()); + else + return this->GetValue(); +} +void +prtyFloat::SetScaledValue(const float i_fValue, bool i_bDirty) // UndoFlags i_Undoable) +{ + if (this->GetUseUnits()) + this->SetValue(i_fValue * prtyUnits::GetUnitScaling(), i_bDirty); // i_Undoable); + else + return this->SetValue(i_fValue, i_bDirty); // i_Undoable); +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyFloat& +prtyFloat::operator=(const prtyFloat& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + SetValue(i_Property.GetValue()); + m_bUseUnits = i_Property.m_bUseUnits; + return *this; +} +prtyFloat& +prtyFloat::operator=(const float i_Value) +{ + // bga - This used to just do an operator= on the values, meaning + // that notifications were not made. But that is inconsistent with the + // other properties. + SetValue(i_Value); + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyFloat::operator==(const prtyFloat& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyFloat::operator!=(const prtyFloat& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyFloat::operator==(const float i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyFloat::operator!=(const float i_Value) const +{ + return (m_Value != i_Value); +} + +bool +prtyFloat::operator>(const float i_Value) const +{ + return (m_Value > i_Value); +} +bool +prtyFloat::operator>=(const float i_Value) const +{ + return (m_Value >= i_Value); +} +bool +prtyFloat::operator<(const float i_Value) const +{ + return (m_Value < i_Value); +} +bool +prtyFloat::operator<=(const float i_Value) const +{ + return (m_Value <= i_Value); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyFloat::Read(chReader& io_Reader) +{ + // float temp; + // io_Reader.Read(temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyFloat::Write(chWriter& io_Writer) const +{ + // float temp = GetValue(); + // io_Writer.Write(temp); +} diff --git a/renderlib/core/prty/prtyFloat.hpp b/renderlib/core/prty/prtyFloat.hpp new file mode 100644 index 00000000..58925e59 --- /dev/null +++ b/renderlib/core/prty/prtyFloat.hpp @@ -0,0 +1,127 @@ +/****************************************************************************\ +** prtyFloat.hpp +** +** Float property +** +** +** +\****************************************************************************/ +#ifdef PRTY_FLOAT_HPP +#error prtyFloat.hpp multiply included +#endif +#define PRTY_FLOAT_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +//============================================================================ +//============================================================================ +class prtyFloat : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyFloat(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyFloat(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyFloat(const std::string& i_Name, float i_fInitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // Set whether this property should consider the current units + // when displaying its value in the user interface. + // prtyFloat has a default value of false. + //-------------------------------------------------------------------- + bool GetUseUnits() const; + void SetUseUnits(bool i_bUseUnits); + + //-------------------------------------------------------------------- + // Get and Set value in the current display units. + // Converts to internal units and then calls Get/SetValue() + // If this property does not use units, the unscaled value is used. + //-------------------------------------------------------------------- + float GetScaledValue() const; + void SetScaledValue(const float i_fValue, bool i_bDirty = false); // UndoFlags i_Undoable = eNoUndo); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyFloat& operator=(const prtyFloat& i_Property); + prtyFloat& operator=(const float i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyFloat& i_Property) const; + bool operator!=(const prtyFloat& i_Property) const; + bool operator==(const float i_Value) const; + bool operator!=(const float i_Value) const; + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator>(const float i_Value) const; + bool operator>=(const float i_Value) const; + bool operator<(const float i_Value) const; + bool operator<=(const float i_Value) const; + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; + +private: + bool m_bUseUnits; +}; + +//============================================================================ +// prtyDistance is just a convenience name for a prtyFloat that should +// scale with the current units. +//============================================================================ +class prtyDistance : public prtyFloat +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyDistance() + : prtyFloat() + { + SetUseUnits(true); + } + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyDistance(const std::string& i_Name) + : prtyFloat(i_Name) + { + SetUseUnits(true); + } + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyDistance(const std::string& i_Name, float i_fInitialValue) + : prtyFloat(i_Name, i_fInitialValue) + { + SetUseUnits(true); + } + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyDistance& operator=(const float i_Value) + { + prtyFloat::operator=(i_Value); + return *this; + } +}; diff --git a/renderlib/core/prty/prtyInt32.cpp b/renderlib/core/prty/prtyInt32.cpp new file mode 100644 index 00000000..53d64351 --- /dev/null +++ b/renderlib/core/prty/prtyInt32.cpp @@ -0,0 +1,150 @@ +/****************************************************************************\ +** prtyInt32.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyInt32.hpp" + +// #include "core/ch/chChunkParserUtil.hpp" +// #include "core/ch/chReader.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyInt32::prtyInt32() + : prtyPropertyTemplate("Int32", 0) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyInt32::prtyInt32(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, 0) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyInt32::prtyInt32(const std::string& i_Name, const int& i_InitialValue) + : prtyPropertyTemplate(i_Name, i_InitialValue) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyInt32::GetType() +{ + return "Int32"; +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyInt32& +prtyInt32::operator=(const prtyInt32& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + + SetValue(i_Property.GetValue()); + return *this; +} +prtyInt32& +prtyInt32::operator=(const int i_Value) +{ + SetValue(i_Value); + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyInt32::operator==(const prtyInt32& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyInt32::operator!=(const prtyInt32& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyInt32::operator==(const int i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyInt32::operator!=(const int i_Value) const +{ + return (m_Value != i_Value); +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyInt32::operator>(const int i_Value) const +{ + return (m_Value > i_Value); +} +bool +prtyInt32::operator>=(const int i_Value) const +{ + return (m_Value >= i_Value); +} +bool +prtyInt32::operator<(const int i_Value) const +{ + return (m_Value < i_Value); +} +bool +prtyInt32::operator<=(const int i_Value) const +{ + return (m_Value <= i_Value); +} +bool +prtyInt32::operator>(const prtyInt32& i_Value) const +{ + return (m_Value > i_Value.GetValue()); +} +bool +prtyInt32::operator>=(const prtyInt32& i_Value) const +{ + return (m_Value >= i_Value.GetValue()); +} +bool +prtyInt32::operator<(const prtyInt32& i_Value) const +{ + return (m_Value < i_Value.GetValue()); +} +bool +prtyInt32::operator<=(const prtyInt32& i_Value) const +{ + return (m_Value <= i_Value.GetValue()); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyInt32::Read(chReader& io_Reader) +{ + // int32_t temp; + // io_Reader.Read(temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyInt32::Write(chWriter& io_Writer) const +{ + // int32_t temp = GetValue(); + // io_Writer.Write(temp); +} diff --git a/renderlib/core/prty/prtyInt32.hpp b/renderlib/core/prty/prtyInt32.hpp new file mode 100644 index 00000000..7bb7756d --- /dev/null +++ b/renderlib/core/prty/prtyInt32.hpp @@ -0,0 +1,73 @@ +/****************************************************************************\ +** prtyInt32.hpp +** +** Int32 property +** +** +** +\****************************************************************************/ +#ifdef PRTY_INT32_HPP +#error prtyInt32.hpp multiply included +#endif +#define PRTY_INT32_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +//============================================================================ +//============================================================================ +class prtyInt32 : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyInt32(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyInt32(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyInt32(const std::string& i_Name, const int& i_InitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyInt32& operator=(const prtyInt32& i_Property); + prtyInt32& operator=(const int i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyInt32& i_Property) const; + bool operator!=(const prtyInt32& i_Property) const; + bool operator==(const int i_Value) const; + bool operator!=(const int i_Value) const; + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator>(const int i_Value) const; + bool operator>=(const int i_Value) const; + bool operator<(const int i_Value) const; + bool operator<=(const int i_Value) const; + bool operator>(const prtyInt32& i_Value) const; + bool operator>=(const prtyInt32& i_Value) const; + bool operator<(const prtyInt32& i_Value) const; + bool operator<=(const prtyInt32& i_Value) const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; +}; diff --git a/renderlib/core/prty/prtyInt8.cpp b/renderlib/core/prty/prtyInt8.cpp new file mode 100644 index 00000000..618bbdf8 --- /dev/null +++ b/renderlib/core/prty/prtyInt8.cpp @@ -0,0 +1,150 @@ +/****************************************************************************\ +** prtyInt8.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyInt8.hpp" + +// #include "core/ch/chReader.hpp" +// #include "core/ch/chWriter.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyInt8::prtyInt8() + : prtyPropertyTemplate("Int8", 0) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyInt8::prtyInt8(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, 0) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyInt8::prtyInt8(const std::string& i_Name, int8_t i_InitialValue) + : prtyPropertyTemplate(i_Name, i_InitialValue) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyInt8::GetType() +{ + return "Int8"; +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyInt8& +prtyInt8::operator=(const prtyInt8& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + + SetValue(i_Property.GetValue()); + return *this; +} +prtyInt8& +prtyInt8::operator=(const int8_t i_Value) +{ + SetValue(i_Value); + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyInt8::operator==(const prtyInt8& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyInt8::operator!=(const prtyInt8& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyInt8::operator==(const int8_t i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyInt8::operator!=(const int8_t i_Value) const +{ + return (m_Value != i_Value); +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyInt8::operator>(const int8_t i_Value) const +{ + return (m_Value > i_Value); +} +bool +prtyInt8::operator>=(const int8_t i_Value) const +{ + return (m_Value >= i_Value); +} +bool +prtyInt8::operator<(const int8_t i_Value) const +{ + return (m_Value < i_Value); +} +bool +prtyInt8::operator<=(const int8_t i_Value) const +{ + return (m_Value <= i_Value); +} +bool +prtyInt8::operator>(const prtyInt8& i_Value) const +{ + return (m_Value > i_Value.GetValue()); +} +bool +prtyInt8::operator>=(const prtyInt8& i_Value) const +{ + return (m_Value >= i_Value.GetValue()); +} +bool +prtyInt8::operator<(const prtyInt8& i_Value) const +{ + return (m_Value < i_Value.GetValue()); +} +bool +prtyInt8::operator<=(const prtyInt8& i_Value) const +{ + return (m_Value <= i_Value.GetValue()); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyInt8::Read(chReader& io_Reader) +{ + // int8_t temp; + // io_Reader.Read(temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyInt8::Write(chWriter& io_Writer) const +{ + // int8_t temp = GetValue(); + // io_Writer.Write(temp); +} diff --git a/renderlib/core/prty/prtyInt8.hpp b/renderlib/core/prty/prtyInt8.hpp new file mode 100644 index 00000000..5d73572b --- /dev/null +++ b/renderlib/core/prty/prtyInt8.hpp @@ -0,0 +1,77 @@ +#pragma once +/****************************************************************************\ +** prtyInt8.hpp +** +** Int8 property +** +** NOTE: a possible code optimization would be to elminate the int8 and +** just use int32 and set the min and max values to be correct. +** +** +** +\****************************************************************************/ +#ifdef PRTY_INT8_HPP +#error prtyInt8.hpp multiply included +#endif +#define PRTY_INT8_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +//============================================================================ +//============================================================================ +class prtyInt8 : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyInt8(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyInt8(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyInt8(const std::string& i_Name, int8_t i_InitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyInt8& operator=(const prtyInt8& i_Property); + prtyInt8& operator=(const int8_t i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyInt8& i_Property) const; + bool operator!=(const prtyInt8& i_Property) const; + bool operator==(const int8_t i_Value) const; + bool operator!=(const int8_t i_Value) const; + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator>(const int8_t i_Value) const; + bool operator>=(const int8_t i_Value) const; + bool operator<(const int8_t i_Value) const; + bool operator<=(const int8_t i_Value) const; + bool operator>(const prtyInt8& i_Value) const; + bool operator>=(const prtyInt8& i_Value) const; + bool operator<(const prtyInt8& i_Value) const; + bool operator<=(const prtyInt8& i_Value) const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; +}; diff --git a/renderlib/core/prty/prtyInterest.cpp b/renderlib/core/prty/prtyInterest.cpp new file mode 100644 index 00000000..effe9373 --- /dev/null +++ b/renderlib/core/prty/prtyInterest.cpp @@ -0,0 +1,76 @@ +/****************************************************************************\ +** prtyInterest.hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyInterest.hpp" + +//---------------------------------------------------------------------------- +// Constructor/Destructor +//---------------------------------------------------------------------------- +prtyInterest::prtyInterest(std::string i_Name, void (*i_CallbackFunction)(), bool i_bEditable, bool i_bProcedural) + : m_Name(i_Name) + , m_CallbackFunction(i_CallbackFunction) + , m_bEditable(i_bEditable) + , m_bProcedural(i_bProcedural) +{ +} +prtyInterest::~prtyInterest() +{ + m_CallbackFunction = NULL; +} + +//---------------------------------------------------------------------------- +// Is this interest editable in a control +//---------------------------------------------------------------------------- +bool +prtyInterest::IsEditable() +{ + return m_bEditable; +} +void +prtyInterest::SetEditable(bool i_bEditable) +{ + m_bEditable = i_bEditable; +} + +//---------------------------------------------------------------------------- +// Is this interest a procedural texture, this will override any pre-existing +// data in the control +//---------------------------------------------------------------------------- +bool +prtyInterest::IsProcedural() +{ + return m_bProcedural; +} +void +prtyInterest::SetProcedural(bool i_bProcedural) +{ + m_bProcedural = i_bProcedural; +} + +//---------------------------------------------------------------------------- +// Get the name of the interest +//---------------------------------------------------------------------------- +std::string& +prtyInterest::GetName() +{ + return m_Name; +} +void +prtyInterest::SetName(std::string& i_Name) +{ + m_Name = i_Name; +} + +//---------------------------------------------------------------------------- +// Execute the interest's callback function +//---------------------------------------------------------------------------- +void +prtyInterest::Invoke() +{ + if (m_CallbackFunction) { + m_CallbackFunction(); + } +} diff --git a/renderlib/core/prty/prtyInterest.hpp b/renderlib/core/prty/prtyInterest.hpp new file mode 100644 index 00000000..f42d8c91 --- /dev/null +++ b/renderlib/core/prty/prtyInterest.hpp @@ -0,0 +1,59 @@ +/****************************************************************************\ +** prtyInterest.cpp +** +** +** +\****************************************************************************/ + +#ifdef PRTY_INTEREST_HPP +#error prtyInterest.hpp multiply included +#endif +#define PRTY_INTEREST_HPP + +#include + +//============================================================================ +//============================================================================ +class prtyInterest +{ +public: + //------------------------------------------------------------------------ + // Constructor/Destructor + //------------------------------------------------------------------------ + prtyInterest(std::string i_Name, + void (*i_CallbackFunction)() = NULL, + bool i_bEditable = true, + bool i_bProcedural = false); + ~prtyInterest(); + + //------------------------------------------------------------------------ + // Is this interest editable in a control + //------------------------------------------------------------------------ + bool IsEditable(); + void SetEditable(bool i_bEditable); + + //------------------------------------------------------------------------ + // Is this interest a procedural texture, this will override any pre-existing + // data in the control + //------------------------------------------------------------------------ + bool IsProcedural(); + void SetProcedural(bool i_bProcedural); + + //------------------------------------------------------------------------ + // Get the name of the interest + //------------------------------------------------------------------------ + std::string& GetName(); + void SetName(std::string& i_Name); + + //------------------------------------------------------------------------ + // Execute the interest's callback function + //------------------------------------------------------------------------ + void Invoke(); + +private: + bool m_bEditable; + bool m_bProcedural; + std::string m_Name; + void (*m_CallbackFunction)(); + +}; // end prtyInterest class diff --git a/renderlib/core/prty/prtyInterestUtil.cpp b/renderlib/core/prty/prtyInterestUtil.cpp new file mode 100644 index 00000000..2e3b5e0b --- /dev/null +++ b/renderlib/core/prty/prtyInterestUtil.cpp @@ -0,0 +1,77 @@ +/****************************************************************************\ +** prtyInterestUtil.cpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyInterestUtil.hpp" + +#include "core/env/envSTLHelpers.hpp" + +//============================================================================ +//============================================================================ +namespace prtyInterestUtil { +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +namespace { +std::vector l_Interests; + +} // end anonymous namespace + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +Init() +{ +} + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +DeInit() +{ + envSTLHelpers::DeleteContainer(l_Interests); +} + +//------------------------------------------------------------------------ +// Run the callback function for the interest +//------------------------------------------------------------------------ +void +InvokeInterest(prtyInterest* i_Interest) +{ + i_Interest->Invoke(); +} + +//------------------------------------------------------------------------ +// add a new interest to our list +//------------------------------------------------------------------------ +void +AddInterest(std::string& i_InterestName, void (*i_CallbackFunction)(), bool i_bEditable, bool i_bProcedural) +{ + prtyInterest* new_interest = new prtyInterest(i_InterestName, i_CallbackFunction, i_bEditable, i_bProcedural); + l_Interests.push_back(new_interest); +} + +//------------------------------------------------------------------------ +// remove an interest from the list +//------------------------------------------------------------------------ +void +RemoveInterest(std::string& i_InterestName) +{ + for (int i = 0; i < l_Interests.size(); i++) { + if (l_Interests[i]->GetName() == i_InterestName) { + envSTLHelpers::DeleteOneValue(l_Interests, l_Interests[i]); + } + } +} + +//------------------------------------------------------------------------ +// Retrieve the interest list +//------------------------------------------------------------------------ +void +GetInterestList(std::vector& o_Interests) +{ + o_Interests = l_Interests; +} + +} // end namespace prtyInterestUtil \ No newline at end of file diff --git a/renderlib/core/prty/prtyInterestUtil.hpp b/renderlib/core/prty/prtyInterestUtil.hpp new file mode 100644 index 00000000..547e8822 --- /dev/null +++ b/renderlib/core/prty/prtyInterestUtil.hpp @@ -0,0 +1,55 @@ +/****************************************************************************\ +** prtyInterestUtil.hpp +** +** +** +\****************************************************************************/ +#ifdef PRTY_INTERESTUTIL_HPP +#error prtyInterestUtil.hpp multiply included +#endif +#define PRTY_INTERESTUTIL_HPP + +#ifndef PRTY_INTEREST_HPP +#include "core/prty/prtyInterest.hpp" +#endif + +#include +#include + +//============================================================================ +//============================================================================ +namespace prtyInterestUtil { +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +Init(); + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +DeInit(); + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +InvokeInterest(prtyInterest* i_Interest); + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +AddInterest(std::string& i_Name, + void (*i_CallbackFunction)() = NULL, + bool i_bEditable = true, + bool i_bProcedural = false); + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +RemoveInterest(std::string& i_Name); + +//------------------------------------------------------------------------ +//------------------------------------------------------------------------ +void +GetInterestList(std::vector& o_Interests); + +} // end namespace prtyInterestUtil \ No newline at end of file diff --git a/renderlib/core/prty/prtyObject.cpp b/renderlib/core/prty/prtyObject.cpp new file mode 100644 index 00000000..fd7d05ed --- /dev/null +++ b/renderlib/core/prty/prtyObject.cpp @@ -0,0 +1,209 @@ +/****************************************************************************\ +** prtyObject.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyObject.hpp" + +#include "core/prty/prtyProperty.hpp" + +#include "core/env/envSTLHelpers.hpp" +#include "core/undo/undoUndoMgr.hpp" + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +namespace { +//-------------------------------------------------------------------- +// Simplest property reference, used by default - it just keeps a +// pointer to the property in the assumption that the prtyObject +// will not be deleted. Bad assumption, but it works in some cases. +// In other cases, the virtual function +// prtyObject::CreateReferenceForProperty +// will have to be overriden in order to create a true logical +// reference that handles deletion and recreation. +//-------------------------------------------------------------------- +class StaticPropertyReference : public prtyPropertyReference +{ +public: + StaticPropertyReference(prtyProperty* i_Property) + : m_Property(i_Property) + { + } + + virtual prtyProperty* GetProperty() { return m_Property; } + +private: + prtyProperty* m_Property; +}; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyObject::prtyObject() + : m_bReadOnly(false) +{ +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyObject::~prtyObject() +{ + m_PropertiesInfo.DeleteAll(); +} + +//-------------------------------------------------------------------- +// If you pass in a direct pointer, a shared_ptr will be wrap +// it, meaning that the ownership has passed to this class. +// If you want to maintain your own copy, pass in a shared_ptr +// and keep a copy of the shared_ptr yourself. +//-------------------------------------------------------------------- +void +prtyObject::AddProperty(prtyPropertyUIInfo* i_pUIInfo) +{ + // When a property is assigned to this object, then this object + // becomes the reference creator + i_pUIInfo->AssignReferenceCreator(this); + + m_PropertiesInfo.Add(i_pUIInfo); +} +void +prtyObject::AddProperty(std::shared_ptr i_pUIInfo) +{ + // When a property is assigned to this object, then this object + // becomes the reference creator + i_pUIInfo->AssignReferenceCreator(this); + + m_PropertiesInfo.Add(i_pUIInfo); +} + +//-------------------------------------------------------------------- +// Remove the property from this object +//-------------------------------------------------------------------- +void +prtyObject::RemoveProperty(std::shared_ptr i_pUIInfo) +{ + m_PropertiesInfo.Remove(i_pUIInfo); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyPropertyUIInfoContainer& +prtyObject::GetListContainer() +{ + return m_PropertiesInfo; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const PropertyUIIList& +prtyObject::GetList() const +{ + return m_PropertiesInfo.GetList(); +} + +//------------------------------------------------------------------------ +// Sort the list by PropertyName +//------------------------------------------------------------------------ +void +prtyObject::SortListByPropertyName() +{ + m_PropertiesInfo.SortByPropertyName(); +} + +//------------------------------------------------------------------------ +// Sort the list by Category +//------------------------------------------------------------------------ +void +prtyObject::SortListByCategory() +{ + m_PropertiesInfo.SortByCategory(); +} + +//------------------------------------------------------------------------ +// +//------------------------------------------------------------------------ +const prtyProperty* +prtyObject::GetProperty(const std::string& i_Name) +{ + return m_PropertiesInfo.GetProperty(i_Name); +} + +//------------------------------------------------------------------------ +// function to dump properties data to log file +//------------------------------------------------------------------------ +void +prtyObject::DebugOutput() +{ + // int i = 0; + // for (i = 0; i < m_PropertiesInfo.GetNumberOfProperties(); ++i) + { + PropertyUIIList& Uiil = m_PropertiesInfo.GetPropertyUIInfoList(); + + PropertyUIIList::iterator begin = Uiil.begin(); + PropertyUIIList::iterator it = begin; + while (it != Uiil.end()) { + std::shared_ptr& pPUII = (*it); + if (pPUII != 0) { + int i = 0; + for (i = 0; i < pPUII->GetNumberOfProperties(); ++i) { + prtyProperty* pProperty = pPUII->GetProperty(i); + if (pProperty != 0) { + // TODO need a way to get the property value as a string + // perhaps a "GetValue()" that returns a string? + // + // DBG_LOG2("%02d. %s", i, pProperty->GetPropertyName().c_str()); + } + } + } + ++it; + } + } +} + +//------------------------------------------------------------------------ +// ReadOnly - flag for user interface. If true, do not allow user +// to alter properties (controls should be read-only). +//------------------------------------------------------------------------ +bool +prtyObject::IsReadOnly() const +{ + return m_bReadOnly; +} +void +prtyObject::SetReadOnly(bool i_bValue) +{ + m_bReadOnly = i_bValue; +} + +//-------------------------------------------------------------------- +// CreateReferenceForProperty - given a property, create a +// shared_ptr to a prtyPropertyReference to this property. +//-------------------------------------------------------------------- +// virtual +std::shared_ptr +prtyObject::CreateReferenceForProperty(prtyProperty& i_Property) +{ + std::shared_ptr static_reference(new StaticPropertyReference(&i_Property)); + return static_reference; +} + +//-------------------------------------------------------------------- +// CreateUndoForProperty - given a property of this object, create an +// undo operation that preserves the properties current state. +// This should be called before the value of the property is changed. +//-------------------------------------------------------------------- +// virtual +void +prtyObject::CreateUndoForProperty(prtyProperty& i_Property) +{ + std::shared_ptr property_reference = this->CreateReferenceForProperty(i_Property); + if (property_reference) { + undoUndoOperation* pUndoOp = i_Property.CreateUndoOperation(property_reference); + if (pUndoOp) { + undoUndoMgr::AddOperation(pUndoOp); + } + } +} diff --git a/renderlib/core/prty/prtyObject.hpp b/renderlib/core/prty/prtyObject.hpp new file mode 100644 index 00000000..0257919f --- /dev/null +++ b/renderlib/core/prty/prtyObject.hpp @@ -0,0 +1,103 @@ +/****************************************************************************\ +** prtyObject.hpp +** +** Object base class +** +** +** +\****************************************************************************/ +#ifdef PRTY_OBJECT_HPP +#error prtyObject.hpp multiply included +#endif +#define PRTY_OBJECT_HPP + +#ifndef PRTY_PROPERTYUIINFO_HPP +#include "core/prty/prtyPropertyUIInfo.hpp" +#endif +#ifndef PRTY_PROPERTYUIINFOCONTAINER_HPP +#include "core/prty/prtyPropertyUIInfoContainer.hpp" +#endif +#ifndef PRTY_PROPERTYREFERENCE_HPP +#include "core/prty/prtyPropertyReference.hpp" +#endif + +#include + +//============================================================================ +//============================================================================ +class prtyObject : public prtyReferenceCreator +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyObject(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual ~prtyObject(); + + //-------------------------------------------------------------------- + // If you pass in a direct pointer, a shared_ptr will be wrap + // it, meaning that the ownership has passed to this class. + // If you want to maintain your own copy, pass in a shared_ptr + // and keep a copy of the shared_ptr yourself. + //-------------------------------------------------------------------- + void AddProperty(prtyPropertyUIInfo* i_pUIInfo); + void AddProperty(std::shared_ptr i_pUIInfo); + + //-------------------------------------------------------------------- + // Remove the property from this object + //-------------------------------------------------------------------- + void RemoveProperty(std::shared_ptr i_pUIInfo); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyPropertyUIInfoContainer& GetListContainer(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const PropertyUIIList& GetList() const; + + //------------------------------------------------------------------------ + // Sort the list by PropertyName + //------------------------------------------------------------------------ + void SortListByPropertyName(); + + //------------------------------------------------------------------------ + // Sort the list by Category + //------------------------------------------------------------------------ + void SortListByCategory(); + + //------------------------------------------------------------------------ + //------------------------------------------------------------------------ + const prtyProperty* GetProperty(const std::string& i_Name); + + //------------------------------------------------------------------------ + // function to dump properties data to log file + //------------------------------------------------------------------------ + void DebugOutput(); + + //------------------------------------------------------------------------ + // ReadOnly - flag for user interface. If true, do not allow user + // to alter properties (controls should be read-only). + //------------------------------------------------------------------------ + bool IsReadOnly() const; + void SetReadOnly(bool i_bValue); + + //-------------------------------------------------------------------- + // CreateReferenceForProperty - given a property, create a + // shared_ptr to a prtyPropertyReference to this property. + //-------------------------------------------------------------------- + virtual std::shared_ptr CreateReferenceForProperty(prtyProperty& i_Property); + + //-------------------------------------------------------------------- + // CreateUndoForProperty - given a property of this object, create an + // undo operation that preserves the properties current state. + // This should be called before the value of the property is changed. + //-------------------------------------------------------------------- + virtual void CreateUndoForProperty(prtyProperty& i_Property); + +private: + prtyPropertyUIInfoContainer m_PropertiesInfo; + bool m_bReadOnly; +}; diff --git a/renderlib/core/prty/prtyPackage.cpp b/renderlib/core/prty/prtyPackage.cpp new file mode 100644 index 00000000..cbbcba78 --- /dev/null +++ b/renderlib/core/prty/prtyPackage.cpp @@ -0,0 +1,30 @@ +/***************************************************************************** +** prtyPackage.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ + +#include "core/prty/prtyPackage.hpp" + +#include "core/prty/prtyInterestUtil.hpp" + +//---------------------------------------------------------------------------- +// initialize prty packages +//---------------------------------------------------------------------------- +void +prtyPackage::Init() +{ + prtyInterestUtil::Init(); +} + +//---------------------------------------------------------------------------- +// clean up prty packages +//---------------------------------------------------------------------------- +void +prtyPackage::CleanUp() +{ + prtyInterestUtil::DeInit(); +} \ No newline at end of file diff --git a/renderlib/core/prty/prtyPackage.hpp b/renderlib/core/prty/prtyPackage.hpp new file mode 100644 index 00000000..1172dc42 --- /dev/null +++ b/renderlib/core/prty/prtyPackage.hpp @@ -0,0 +1,33 @@ +/***************************************************************************** +** prtyPackage.hpp +** +** package for property classes +** +** +** +** +\****************************************************************************/ + +#ifdef PRTY_PACKAGE_HPP +#error prtyPackage.hpp multiply included +#endif +#define PRTY_PACKAGE_HPP + +//============================================================================ +//============================================================================ +class prtyPackage +{ +public: + //------------------------------------------------------------------------ + // Init must be called before you use this package. A good place to + // do this is in your main function, with your other package initializers. + //------------------------------------------------------------------------ + static void Init(); + + //------------------------------------------------------------------------ + // CleanUp should be called after you are done with this package. + // A good place to do this is in your main function, after you are done + // with other deinitialization and cleanup tasks. + //------------------------------------------------------------------------ + static void CleanUp(); +}; \ No newline at end of file diff --git a/renderlib/core/prty/prtyProperty.cpp b/renderlib/core/prty/prtyProperty.cpp new file mode 100644 index 00000000..4b123c62 --- /dev/null +++ b/renderlib/core/prty/prtyProperty.cpp @@ -0,0 +1,214 @@ +/****************************************************************************\ +** prtyProperty.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyProperty.hpp" + +// #include "core/dbg/dbgMsg.hpp" +#include "core/env/envSTLHelpers.hpp" + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyProperty::prtyProperty() + : m_Name("property") + , m_bVisible(true) +{ + m_Flags.m_bAnimatable = false; + m_Flags.m_bScripted = false; + m_Flags.m_bValueVariation = false; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyProperty::prtyProperty(const std::string& i_Name) + : m_Name(i_Name) + , m_bVisible(true) +{ + m_Flags.m_bAnimatable = false; + m_Flags.m_bScripted = false; + m_Flags.m_bValueVariation = false; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyProperty::prtyProperty(const prtyProperty& i_Property) + : m_Name(i_Property.m_Name) + , m_bVisible(i_Property.m_bVisible) +// m_Type(i_Property.m_Type) +{ + m_Flags.m_bAnimatable = false; + m_Flags.m_bScripted = false; + m_Flags.m_bValueVariation = false; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyProperty::~prtyProperty() +{ + // if (!m_CallbackObjects.empty()) + //{ + // DBG_LOG("Property destructor, num callback objects: %d" << m_CallbackObjects.size()); + // } + + // shared_ptr handles this for us now + // envSTLHelpers::DeleteContainer(this->m_CallbackObjects); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const std::string& +prtyProperty::GetPropertyName() const +{ + return m_Name; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyProperty::SetPropertyName(const std::string& i_Name) +{ + m_Name = i_Name; +} + +//-------------------------------------------------------------------- +// Animatable - can this property be animated? +//-------------------------------------------------------------------- +bool +prtyProperty::IsAnimatable() const +{ + return m_Flags.m_bAnimatable; +} +void +prtyProperty::SetAnimatable(bool i_bVal) +{ + m_Flags.m_bAnimatable = i_bVal; +} + +//-------------------------------------------------------------------- +// Scripted - Is this property currently being animated? +//-------------------------------------------------------------------- +bool +prtyProperty::IsScripted() const +{ + return m_Flags.m_bScripted; +} +void +prtyProperty::SetScripted(bool i_bVal) +{ + m_Flags.m_bScripted = i_bVal; +} + +//-------------------------------------------------------------------- +// ValueVariation - Does the current value vary from the scripted value? +//-------------------------------------------------------------------- +bool +prtyProperty::HasValueVariation() const +{ + return m_Flags.m_bValueVariation; +} +void +prtyProperty::SetValueVariation(bool i_bVal) +{ + m_Flags.m_bValueVariation = i_bVal; +} + +//-------------------------------------------------------------------- +// assignment operator - does not copy the callbacks +//-------------------------------------------------------------------- +prtyProperty& +prtyProperty::operator=(const prtyProperty& i_Property) +{ + // m_Type = i_Property.m_Type; + m_Name = i_Property.m_Name; + + // flags should not be copied + // m_Flags = i_Property.m_Flags; + + return *this; +} + +//-------------------------------------------------------------------- +// AddCallback using interface, used by unmanaged classes. +// +// NOTE: This property will take ownership of the callback +// pointer and will delete it in its destructor! It should be +// created on the heap and probably should use the +// prtyCallbackWrapper template. +//-------------------------------------------------------------------- +void +prtyProperty::AddCallback(prtyPropertyCallback* i_pCallback) +{ + if (i_pCallback != NULL) + m_CallbackObjects.push_back(std::shared_ptr(i_pCallback)); +} + +//-------------------------------------------------------------------- +// AddCallback shared pointer variation for when you want to +// keep a copy of the callback also. +//-------------------------------------------------------------------- +void +prtyProperty::AddCallback(std::shared_ptr i_pCallback) +{ + if (i_pCallback.get() != NULL) + m_CallbackObjects.push_back(i_pCallback); +} + +//-------------------------------------------------------------------- +// RemoveCallback by shared_ptr. You should be keeping a shared_ptr +// to the callback passed to AddCallback() if you want to remove +// it later. Don't use the direct pointer function when adding +// if you want to keep a copy. +//-------------------------------------------------------------------- +void +prtyProperty::RemoveCallback(std::shared_ptr i_pCallback) +{ + envSTLHelpers::RemoveOneValue(m_CallbackObjects, i_pCallback); +} + +//-------------------------------------------------------------------- +// call all the callbacks +//-------------------------------------------------------------------- +void +prtyProperty::NotifyCallbacksPropertyChanged(bool i_bWithUndo) +{ + const int num_callbackobjs = m_CallbackObjects.size(); + for (int i = 0; i < num_callbackobjs; ++i) { + m_CallbackObjects[i]->PropertyChanged(this, i_bWithUndo); + } +} + +//-------------------------------------------------------------------- +// In some cases we want the form builder to check whether or not +// this property should be visible. +//-------------------------------------------------------------------- +void +prtyProperty::SetVisible(bool i_bVisible) +{ + m_bVisible = i_bVisible; +} + +bool +prtyProperty::GetVisible() const +{ + return m_bVisible; +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +// const std::string& prtyProperty::GetType() +//{ +// return m_Type; +//} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +// void prtyProperty::SetType(const std::string i_Type) +//{ +// m_Type = i_Type; +//} diff --git a/renderlib/core/prty/prtyProperty.h b/renderlib/core/prty/prtyProperty.h deleted file mode 100644 index 6da5f0d5..00000000 --- a/renderlib/core/prty/prtyProperty.h +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include "Logging.h" - -#include -#include -#include -#include -#include -#include - -// only enable this to verbosely dump every single property setter. -// This implies that the value type must be streamable to std::ostream. -#ifndef PRTY_PROPERTY_DEBUG -#define PRTY_PROPERTY_DEBUG 0 -#endif - -// a property has a name and a value. -// the init value is default-constructed or passed in. -// The value type must be copyable, assignable, and default-constructible. -// The value must also be streamable to std::ostream. -template && std::is_copy_assignable_v && std::is_default_constructible_v && - std::is_move_constructible_v && std::is_move_assignable_v && - std::is_convertible_v() << std::declval()), std::ostream&>>> -class prtyProperty -{ -public: - prtyProperty(std::string name) - : name(name) - { - } - - prtyProperty(std::string name, const T& val) - : name(name) - , value(val) - { - } - - virtual ~prtyProperty() {} - - void set(const T& val, bool isFromUI = false) - { - // TODO - check if the value has changed - // TODO - do we notify if value hasn't changed? - -#if PRTY_PROPERTY_DEBUG - LOG_INFO << "Property " << name << " set from " << value << " to " << val; -#endif - - value = val; - - // call all callbacks - notifyAll(isFromUI); - } - - std::string getName() const { return name; } - - // copy???? - T get() const { return value; } - - // non-copy, just use paren operator - T& operator()() const { return value; } - - // set up the rule of 5 - prtyProperty(const prtyProperty& other) - : name(other.name) - , value(other.value) - { - } - - prtyProperty& operator=(const prtyProperty& other) - { - if (this != &other) { - name = other.name; - value = other.value; - } - return *this; - } - - prtyProperty(prtyProperty&& other) - : name(std::move(other.name)) - , value(std::move(other.value)) - { - } - - prtyProperty& operator=(prtyProperty&& other) - { - if (this != &other) { - name = std::move(other.name); - value = std::move(other.value); - } - return *this; - } - - // direct assignment from a value - prtyProperty& operator=(const T& val) - { - value = val; - // call all callbacks - notifyAll(false); - return *this; - } - - // callback for when the property's value is set. - // The boolean flag is true if the change is coming from the - // user interface and therefore should mark the document - // containing the property as dirty. - typedef std::function*, bool)> prtyPropertyCallback; - - void addCallback(prtyPropertyCallback cb) { callbacks.push_back(cb); } - void removeCallback(prtyPropertyCallback cb) - { - auto it = std::find(callbacks.begin(), callbacks.end(), cb); - if (it != callbacks.end()) { - callbacks.erase(it); - } - } - - void notifyAll(bool isFromUI = false) - { - for (auto& cb : callbacks) { - cb(this, isFromUI); - } - } - -private: - std::string name; - T value; - - std::vector callbacks; -}; diff --git a/renderlib/core/prty/prtyProperty.hpp b/renderlib/core/prty/prtyProperty.hpp new file mode 100644 index 00000000..e879ce0b --- /dev/null +++ b/renderlib/core/prty/prtyProperty.hpp @@ -0,0 +1,233 @@ +/****************************************************************************\ +** prtyProperty.hpp +** +** A property corresponds to a value, singular or compound. +** (int, float, vector, matrix, color, etc.) +** +** How to create a new property: +** 1) Create new property class +** a) a child of prtyProperty +** b) 2 constructors: one takes the name, other takes name + initial value +** c) GetValue and SetValue. SetValue should handle undo or not +** d) operators (at least =) [other useful ==, !=] +** e) the data itself +** 2) Create the property's undo class +** 3) [optional] Create at least one control connection for the property +** a) a class that ties the property to a specific control +** b) implement this classes instantiation in a control factory +** +** How to create a new control: +** 1) Create new property-control class +** a) a child of prtyControl +** 2) Create the instantiation of the control in appropriate Control Factory +** a) make sure at correct property type is checked (from #1) +** 3) Create a UIInfo class for this control +** +** How to USE a new property +** 1) add the property to whatever data class is going to hold it (like a struct +** of properties) [Also update any parser files] +** 2) some class must have a parent of prtyObject and then register the +** properties *only if* they are going to be used as controls that +** will be built dynamically. +** a) if a property is going to be displayed on a Form then it must be added +** to the control list. +** 3) to build the form make the call: +** prtyFormControlBuilder::BuildForm( pControl, (m_pObject->GetListContainer()) ); +** where pControl is a System::Windows::Forms::Control* +** and m_pObject->GetListContainer() is the container of registered properties +** +** Applications using prty must: +** 1) call these functions to initialize +** prtyCallbackMgr::Initialize(); +** prtyControlMgr::Initialize(); +** prtyControlMgr::AddControlFactory( new prtyControlFactoryBase() ); +** prtyControlMgr::AddControlFactory( new prtyControlFactoryTMC() ); +** 2) call these functions to deinitialize +** prtyControlMgr::DeInitialize(); +** prtyCallbackMgr::DeInitialize(); +** +** Refer to TestTerawatt/Tools/prty application for an example. +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_PROPERTY_HPP +#error prtyProperty.hpp multiply included +#endif +#define PRTY_PROPERTY_HPP + +#ifndef PRTY_PROPERTYCALLBACK_HPP +#include "core/prty/prtyPropertyCallback.hpp" +#endif +#ifndef UNDO_UNDOOPERATION_HPP +#include "core/undo/undoUndoOperation.hpp" +#endif + +#include +#include +#include +#include + +//============================================================================ +// forward references +//============================================================================ +class prtyProperty; +class prtyPropertyReference; +class chReader; +class chWriter; + +//============================================================================ +// typedefs +//============================================================================ +namespace { +typedef std::vector property_list; +}; + +//============================================================================ +//============================================================================ +class prtyProperty +{ +public: + // Undo is not created on a property anymore, use the prtyObject to + // create undo operations. SetValue() functions should just take a boolean + // for whether the change is coming from the user interface in order to + // set a dirty bit for a document. + // + // enum UndoFlags + //{ + // eNoUndo = 0, + // eContinueUndo, // continue current undo operation + // eNewUndo, // new operation + // eFromUndo // change is coming from an undo operation being undone or redone + //}; + +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyProperty(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyProperty(const std::string& i_Name); + + //-------------------------------------------------------------------- + // copy constructor does not copy callbacks + //-------------------------------------------------------------------- + prtyProperty(const prtyProperty& i_Property); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + ~prtyProperty(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const std::string& GetPropertyName() const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void SetPropertyName(const std::string& i_Name); + + //-------------------------------------------------------------------- + // Animatable - can this property be animated? + //-------------------------------------------------------------------- + bool IsAnimatable() const; + void SetAnimatable(bool i_bVal); + + //-------------------------------------------------------------------- + // Scripted - Is this property currently being animated? + //-------------------------------------------------------------------- + bool IsScripted() const; + void SetScripted(bool i_bVal); + + //-------------------------------------------------------------------- + // ValueVariation - Does the current value vary from the scripted value? + //-------------------------------------------------------------------- + bool HasValueVariation() const; + void SetValueVariation(bool i_bVal); + + //-------------------------------------------------------------------- + // assignment operator - does not copy the callbacks + //-------------------------------------------------------------------- + prtyProperty& operator=(const prtyProperty& i_Property); + + //-------------------------------------------------------------------- + // AddCallback using interface, used by unmanaged classes. + // + // NOTE: This property will take ownership of the callback + // pointer and will delete it in its destructor! It should be + // created on the heap and probably should use the + // prtyCallbackWrapper template. + //-------------------------------------------------------------------- + void AddCallback(prtyPropertyCallback* i_pCallback); + + //-------------------------------------------------------------------- + // AddCallback shared pointer variation for when you want to + // keep a copy of the callback also. + //-------------------------------------------------------------------- + void AddCallback(std::shared_ptr i_pCallback); + + //-------------------------------------------------------------------- + // RemoveCallback by shared_ptr. You should be keeping a shared_ptr + // to the callback passed to AddCallback() if you want to remove + // it later. Don't use the direct pointer function when adding + // if you want to keep a copy. + //-------------------------------------------------------------------- + void RemoveCallback(std::shared_ptr i_pCallback); + + //-------------------------------------------------------------------- + // Call all the callbacks - + // i_bWithUndo should be set to (i_Undoable != eNoUndo) + // in derived classes SetValue() functions. + //-------------------------------------------------------------------- + void NotifyCallbacksPropertyChanged(bool i_bWithUndo); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType() = 0; + + //-------------------------------------------------------------------- + // Create an undo operation of the correct type for this + // property. A reference to this property should be passed in. + // Ownership passes to the caller. + //-------------------------------------------------------------------- + virtual undoUndoOperation* CreateUndoOperation(std::shared_ptr i_pPropertyRef) = 0; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader) = 0; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const = 0; + + //-------------------------------------------------------------------- + // In some cases we want the form builder to check whether or not + // this property should be visible. + //-------------------------------------------------------------------- + void SetVisible(bool i_bVisible); + bool GetVisible() const; + +protected: + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + // void SetType(const std::string i_Type); + +protected: + /*static*/ undoUndoOperation* ms_LastUndoOp; + +private: + // std::string m_Type; // type of property (each property class) + std::string m_Name; // name (situation-specific) of property + std::vector> m_CallbackObjects; + bool m_bVisible; + // Animation state flags + struct + { + bool m_bAnimatable : 1; // can this property be animated? + bool m_bScripted : 1; // Is this property currently being animated? + bool m_bValueVariation : 1; // Does the current value vary from the scripted value? + } m_Flags; +}; diff --git a/renderlib/core/prty/prtyPropertyCallback.hpp b/renderlib/core/prty/prtyPropertyCallback.hpp new file mode 100644 index 00000000..2b8bf952 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyCallback.hpp @@ -0,0 +1,60 @@ +/****************************************************************************\ +** prtyPropertyCallback.hpp +** +** Template and interface for handling property changed callbacks. +** +** You create and register a callback to a member function with this syntax: +** m_Property.AddCallback(new prtyCallbackWrapper(this, &xxxObject::FunctionName)); +** +** +** +\****************************************************************************/ +#ifdef PRTY_PROPERTYCALLBACK_HPP +#error prtyPropertyCallback.hpp multiply included +#endif +#define PRTY_PROPERTYCALLBACK_HPP + +//============================================================================ +// forward references +//============================================================================ +class prtyProperty; + +//============================================================================ +// Interface +//============================================================================ +class prtyPropertyCallback +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual ~prtyPropertyCallback() = 0; + + //-------------------------------------------------------------------- + // PropertyChanged is called when a property's value is changed + // through a "SetValue" function. The boolean flag is true + // if the change is coming from the user interface and therefore + // should mark the document containing the property as dirty. + //-------------------------------------------------------------------- + virtual void PropertyChanged(prtyProperty* i_pProperty, bool i_bDirty) = 0; +}; + +//============================================================================ +// Wrapper template +//============================================================================ +template +struct prtyCallbackWrapper : public prtyPropertyCallback +{ + prtyCallbackWrapper(T* i_this, void (T::*i_memberFunc)(prtyProperty*, bool)) + : obj_ptr(i_this) + , func_ptr(i_memberFunc) + { + } + + T* obj_ptr; + void (T::*func_ptr)(prtyProperty*, bool); + + virtual void PropertyChanged(prtyProperty* i_pProperty, bool i_bWithUndo) + { + (obj_ptr->*func_ptr)(i_pProperty, i_bWithUndo); + } +}; diff --git a/renderlib/core/prty/prtyPropertyReference.cpp b/renderlib/core/prty/prtyPropertyReference.cpp new file mode 100644 index 00000000..a2ecf039 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyReference.cpp @@ -0,0 +1,14 @@ +/****************************************************************************\ +** prtyPropertyReference.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyPropertyReference.hpp" + +//============================================================================ +//============================================================================ +namespace { +} diff --git a/renderlib/core/prty/prtyPropertyReference.hpp b/renderlib/core/prty/prtyPropertyReference.hpp new file mode 100644 index 00000000..d63b94e3 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyReference.hpp @@ -0,0 +1,56 @@ +/*****************************************************************************\ +** prtyPropertyReference.hpp +** +** Provides a safe way to refer to a property for undo operations. +** Derivations of this class should provide a way to access a property +** by a reference that is consistent through deletion and restoration of +** the parent property object. +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_PROPERTYREFERENCE_HPP +#error prtyPropertyReference.hpp multiply included +#endif +#define PRTY_PROPERTYREFERENCE_HPP + +#include + +//============================================================================ +// Forward References +//============================================================================ +class prtyProperty; + +//============================================================================ +// A prtyReference is a logical reference to a property that may point to +// different actual prtyProperty classes at different times. This may happen +// during undo and redo when an object is deleted and restored. +//============================================================================ +class prtyPropertyReference +{ +public: + //-------------------------------------------------------------------- + // virtual destructor + //-------------------------------------------------------------------- + virtual ~prtyPropertyReference() {} + + //-------------------------------------------------------------------- + // GetProperty - return a pointer to a property that is usable + // for a short period of time. + //-------------------------------------------------------------------- + virtual prtyProperty* GetProperty() = 0; +}; + +//============================================================================ +// prtyReferenceCreator creates logical references to properties +//============================================================================ +class prtyReferenceCreator +{ +public: + //-------------------------------------------------------------------- + // CreateReferenceForProperty - given a property, create a + // shared_ptr to a prtyPropertyReference to this property. + //-------------------------------------------------------------------- + virtual std::shared_ptr CreateReferenceForProperty(prtyProperty& i_Property) = 0; +}; diff --git a/renderlib/core/prty/prtyPropertyTemplate.hpp b/renderlib/core/prty/prtyPropertyTemplate.hpp new file mode 100644 index 00000000..fc0e8b62 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyTemplate.hpp @@ -0,0 +1,71 @@ +/****************************************************************************\ +** prtyPropertyTemplate.hpp +** +** Template for properties +** +** +** +\****************************************************************************/ +#ifdef PRTY_PROPERTYTEMPLATE_HPP +#error prtyPropertyTemplate.hpp multiply included +#endif +#define PRTY_PROPERTYTEMPLATE_HPP + +#ifndef PRTY_PROPERTY_HPP +#include "core/prty/prtyProperty.hpp" +#endif +#ifndef PRTY_UNDOTEMPLATE_HPP +#include "core/prty/prtyUndoTemplate.hpp" +#endif + +//============================================================================ +//============================================================================ +template +class prtyPropertyTemplate : public prtyProperty +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyPropertyTemplate(const std::string& i_Name, ConstRefType i_InitialValue) + : prtyProperty(i_Name) + , m_Value(i_InitialValue) + { + } + + //---------------------------------------------------------------------------- + // Get value of property + //---------------------------------------------------------------------------- + inline ConstRefType GetValue() const { return m_Value; } + + //---------------------------------------------------------------------------- + // Set value of property. The boolean flag is true + // if the change is coming from the user interface and therefore + // should mark the document containing the property as dirty. + //---------------------------------------------------------------------------- + // void SetValue(ConstRefType i_Value, UndoFlags i_Undoable = eNoUndo) + void SetValue(ConstRefType i_Value, bool i_bDirty = false) + { + if (m_Value != i_Value) { + m_Value = i_Value; + NotifyCallbacksPropertyChanged(i_bDirty); + // NotifyCallbacksPropertyChanged(i_Undoable != eNoUndo); + } + } + + //-------------------------------------------------------------------- + // Set value of property without notifying the callbacks + //-------------------------------------------------------------------- + void SetValueWithoutNotify(ConstRefType i_Value) { m_Value = i_Value; } + + //-------------------------------------------------------------------- + // Create and return undo operation of correct type for this property. + // Ownership passes to the caller. + //-------------------------------------------------------------------- + undoUndoOperation* CreateUndoOperation(std::shared_ptr i_pPropertyRef) + { + return new prtyUndoTemplate(i_pPropertyRef, this->GetValue()); + } + +protected: + ValueType m_Value; +}; diff --git a/renderlib/core/prty/prtyPropertyUIInfo.cpp b/renderlib/core/prty/prtyPropertyUIInfo.cpp new file mode 100644 index 00000000..111d76bd --- /dev/null +++ b/renderlib/core/prty/prtyPropertyUIInfo.cpp @@ -0,0 +1,206 @@ +/****************************************************************************\ +** prtyPropertyUIInfo.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyPropertyUIInfo.hpp" + +#include "core/prty/prtyProperty.hpp" + +#include "Logging.h" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyPropertyUIInfo::prtyPropertyUIInfo(prtyProperty* i_pProperty) + : m_Category("") + , m_Description("") + , m_bReadOnly(false) +{ + if (i_pProperty != 0) { + AddProperty(i_pProperty); + } +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyPropertyUIInfo::prtyPropertyUIInfo(prtyProperty* i_pProperty, + const std::string& i_Category, + const std::string& i_Description) + : m_Category(i_Category) + , m_Description(i_Description) + , m_bReadOnly(false) +{ + if (i_pProperty != 0) { + AddProperty(i_pProperty); + } +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyPropertyUIInfo::~prtyPropertyUIInfo() {} + +//-------------------------------------------------------------------- +// Return pointer to new equivalent prtyPropertyUIInfo +//-------------------------------------------------------------------- +// virtual +prtyPropertyUIInfo* +prtyPropertyUIInfo::Clone() +{ + return new prtyPropertyUIInfo(this->GetProperty(0)); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +int +prtyPropertyUIInfo::GetNumberOfProperties() const +{ + return m_Properties.size(); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyProperty* +prtyPropertyUIInfo::GetProperty(int i_Index) const +{ + DBG_ASSERT((i_Index >= 0) && (i_Index < m_Properties.size()), "Invalid property list index"); + + return m_Properties[i_Index]; +} +prtyProperty* +prtyPropertyUIInfo::GetProperty(const std::string& i_Name) const +{ + for (int i = 0; i < m_Properties.size(); ++i) { + if (strcmp(i_Name.c_str(), m_Properties[i]->GetPropertyName().c_str()) == 0) + return m_Properties[i]; + } + return 0; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyReferenceCreator* +prtyPropertyUIInfo::GetReferenceCreator(int i_Index) const +{ + DBG_ASSERT((i_Index >= 0) && (i_Index < m_ReferenceCreators.size()), "Invalid reference creator list index"); + return m_ReferenceCreators[i_Index]; +} + +//-------------------------------------------------------------------- +// Add property to list, optionally passing a reference creator +// that can be used when creating undo operations. +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::AddProperty(prtyProperty* i_pProperty, prtyReferenceCreator* i_pReferenceCreator) +{ + m_Properties.push_back(i_pProperty); + m_ReferenceCreators.push_back(i_pReferenceCreator); + + // DBG_LOG2("=UIInfo add property (%s) count = %d", this->GetControlName().c_str(), m_Properties.size() ); +} + +//-------------------------------------------------------------------- +// Can be used to assign a new reference creator to all existing +// properties in this UIInfo. This will not affect new properties +// added after this call. +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::AssignReferenceCreator(prtyReferenceCreator* i_pReferenceCreator) +{ + for (int i = 0; i < m_ReferenceCreators.size(); ++i) + m_ReferenceCreators[i] = i_pReferenceCreator; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +const std::string& +prtyPropertyUIInfo::GetControlName() const +{ + return m_ControlName; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +const std::string& +prtyPropertyUIInfo::GetCategory() const +{ + return m_Category; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetCategory(const std::string& i_Category) +{ + m_Category = i_Category; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const std::string& +prtyPropertyUIInfo::GetDescription() const +{ + return m_Description; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetDescription(const std::string& i_Description) +{ + m_Description = i_Description; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const bool +prtyPropertyUIInfo::GetReadOnly() const +{ + return m_bReadOnly; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetReadOnly(const bool i_bReadOnly) +{ + m_bReadOnly = i_bReadOnly; +} + +//-------------------------------------------------------------------- +// ConfirmationString is message to display to user that he needs +// to confirm before the value of the property can be changed. +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetConfirmationString(const std::string& i_Confirmation) +{ + m_ConfirmationString = i_Confirmation; +} +const std::string& +prtyPropertyUIInfo::GetConfirmationString() const +{ + return m_ConfirmationString; +} + +//-------------------------------------------------------------------- +// Call this function when the property UI Info has been changed +// after a control for it has already been created. It will +// cause the control to be updated. +// Note: Con't call this automatically from derived classes, +// just let the prtyObject that owns this UI Info handle it. +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::UpdateControl() +{ + // prtyIntCallbackMgr::UpdateControl(this); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetControlName(const std::string i_ControlName) +{ + m_ControlName = i_ControlName; +} diff --git a/renderlib/core/prty/prtyPropertyUIInfo.hpp b/renderlib/core/prty/prtyPropertyUIInfo.hpp new file mode 100644 index 00000000..c832c570 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyUIInfo.hpp @@ -0,0 +1,119 @@ +/****************************************************************************\ +** prtyPropertyUIInfo.hpp +** +** Property UI info +** +** +** +\****************************************************************************/ +#ifdef PRTY_PROPERTYUIINFO_HPP +#error prtyPropertyUIInfo.hpp multiply included +#endif +#define PRTY_PROPERTYUIINFO_HPP + +#include +#include + +//============================================================================ +//============================================================================ +class prtyProperty; +class prtyReferenceCreator; + +//============================================================================ +//============================================================================ +class prtyPropertyUIInfo +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyPropertyUIInfo(prtyProperty* i_pProperty); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyPropertyUIInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual ~prtyPropertyUIInfo(); + + //-------------------------------------------------------------------- + // Return pointer to new equivalent prtyPropertyUIInfo + //-------------------------------------------------------------------- + virtual prtyPropertyUIInfo* Clone(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + int GetNumberOfProperties() const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyProperty* GetProperty(int i_Index) const; + prtyProperty* GetProperty(const std::string& i_Name) const; + + //---------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + prtyReferenceCreator* GetReferenceCreator(int i_Index) const; + + //-------------------------------------------------------------------- + // Add property to list, optionally passing a reference creator + // that can be used when creating undo operations. + //-------------------------------------------------------------------- + void AddProperty(prtyProperty* i_pProperty, prtyReferenceCreator* i_pReferenceCreator = NULL); + + //-------------------------------------------------------------------- + // Can be used to assign a new reference creator to all existing + // properties in this UIInfo. This will not affect new properties + // added after this call. + //-------------------------------------------------------------------- + void AssignReferenceCreator(prtyReferenceCreator* i_pReferenceCreator); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const std::string& GetControlName() const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const std::string& GetCategory() const; + void SetCategory(const std::string& i_Category); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const std::string& GetDescription() const; + void SetDescription(const std::string& i_Description); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const bool GetReadOnly() const; + void SetReadOnly(const bool i_bReadOnly); + + //-------------------------------------------------------------------- + // ConfirmationString is message to display to user that he needs + // to confirm before the value of the property can be changed. + //-------------------------------------------------------------------- + void SetConfirmationString(const std::string& i_Confirmation); + const std::string& GetConfirmationString() const; + + //-------------------------------------------------------------------- + // Call this function when the property UI Info has been changed + // after a control for it has already been created. It will + // cause the control to be updated. + // Note: Con't call this automatically from derived classes, + // just let the prtyObject that owns this UI Info handle it. + //-------------------------------------------------------------------- + void UpdateControl(); + +protected: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void SetControlName(const std::string i_ControlName); + +private: + std::vector m_Properties; + std::vector m_ReferenceCreators; + + std::string m_ControlName; + std::string m_Category; + std::string m_Description; + bool m_bReadOnly; + std::string m_ConfirmationString; +}; diff --git a/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp b/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp new file mode 100644 index 00000000..d73c2879 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp @@ -0,0 +1,328 @@ +/****************************************************************************\ +** prtyPropertyUIInfoContainer.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyPropertyUIInfoContainer.hpp" + +#include "Logging.h" +#include "core/env/envSTLHelpers.hpp" +#include "core/prty/prtyProperty.hpp" + +#include +#include + +//============================================================================ +//============================================================================ +namespace { +struct property_match +{ + property_match(prtyProperty* i_pProperty) + : m_pProperty(i_pProperty) {}; + inline bool operator()(const std::shared_ptr& i_PUII) + { + for (int i = 0; i < i_PUII->GetNumberOfProperties(); ++i) { + if (m_pProperty == i_PUII->GetProperty(i)) + return true; + } + return false; + } + const prtyProperty* m_pProperty; +}; +struct property_name_match +{ + property_name_match(const prtyProperty* i_pProperty) + : m_pProperty(i_pProperty) {}; + inline bool operator()(const std::shared_ptr& i_PUII) + { + for (int i = 0; i < i_PUII->GetNumberOfProperties(); ++i) { + if (m_pProperty->GetPropertyName() == i_PUII->GetProperty(i)->GetPropertyName()) + return true; + } + return false; + } + const prtyProperty* m_pProperty; +}; +struct property_name_match_alt +{ + property_name_match_alt(const std::string& i_Name) + : m_Name(i_Name) {}; + inline bool operator()(const std::shared_ptr& i_PUII) + { + for (int i = 0; i < i_PUII->GetNumberOfProperties(); ++i) { + if (strcmp(m_Name.c_str(), i_PUII->GetProperty(i)->GetPropertyName().c_str()) == 0) + return true; + } + return false; + } + const std::string m_Name; +}; +struct propertyname_sort +{ + inline bool operator()(std::shared_ptr& lhs, std::shared_ptr& rhs) + { + for (int i = 0; i < lhs->GetNumberOfProperties(); ++i) { + for (int j = 0; j < rhs->GetNumberOfProperties(); ++j) { + if (lhs->GetProperty(i)->GetPropertyName() < rhs->GetProperty(j)->GetPropertyName()) + return true; + } + } + return false; + } +}; +struct category_sort +{ + inline bool operator()(std::shared_ptr& lhs, std::shared_ptr& rhs) + { + return (lhs->GetCategory() < rhs->GetCategory()); + } +}; +} + +//-------------------------------------------------------------------- +// destructor +//-------------------------------------------------------------------- +prtyPropertyUIInfoContainer::~prtyPropertyUIInfoContainer() +{ + // Note: shared pointers handle this now + // do NOT delete UIInfos since this container may not own them. + // RemoveAll(); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// void prtyPropertyUIInfoContainer::Add(prtyProperty* i_pProperty, +// const std::string& i_Category, +// const std::string& i_Description ) +//{ +// shared_ptr pPUII( new prtyPropertyUIInfo(i_pProperty) ); +// m_PropertyUIInfoList.push_back( pPUII ); +// +// pPUII->SetCategory(i_Category); +// pPUII->SetDescription(i_Description); +//} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfoContainer::Add(std::shared_ptr& i_pUIInfo) +{ + DBG_ASSERT(i_pUIInfo != 0, "Cannot add a NULL prtyPropertyUIInfo"); + + m_PropertyUIInfoList.push_back(i_pUIInfo); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfoContainer::Add(prtyPropertyUIInfo* i_pUIInfo) +{ + DBG_ASSERT(i_pUIInfo != 0, "Cannot add a NULL prtyPropertyUIInfo"); + + m_PropertyUIInfoList.push_back(std::shared_ptr(i_pUIInfo)); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfoContainer::Add(const PropertyUIIList& i_UIInfoList) +{ + PropertyUIIList::const_iterator it, end = i_UIInfoList.end(); + for (it = i_UIInfoList.begin(); it != end; ++it) { + DBG_ASSERT((*it) != 0, "UIInfo listhas a NULL property in its list"); + + // TODO check for duplicates + m_PropertyUIInfoList.push_back((*it)); + } +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +void +prtyPropertyUIInfoContainer::Remove(prtyProperty* i_pProperty) +{ + PropertyUIIList::iterator it = + std::find_if(m_PropertyUIInfoList.begin(), m_PropertyUIInfoList.end(), property_match(i_pProperty)); + if (it != m_PropertyUIInfoList.end()) { + m_PropertyUIInfoList.erase(it); + } +} +void +prtyPropertyUIInfoContainer::Remove(std::shared_ptr& i_pUIInfo) +{ + DBG_ASSERT(i_pUIInfo != 0, "Cannot remove a NULL prtyPropertyUIInfo"); + + // DBG_LOG("before UII remove = " << m_PropertyUIInfoList.size() << " items" ); + m_PropertyUIInfoList.remove(i_pUIInfo); + // DBG_LOG("after UII remove = " << m_PropertyUIInfoList.size() << " items" ); +} + +//-------------------------------------------------------------------- +// Remove all UIInfos from the container, but DO NOT delete them +//-------------------------------------------------------------------- +void +prtyPropertyUIInfoContainer::RemoveAll() +{ + m_PropertyUIInfoList.clear(); +} + +//-------------------------------------------------------------------- +// Delete all UIInfos from the container +//-------------------------------------------------------------------- +void +prtyPropertyUIInfoContainer::DeleteAll() +{ + // Note: shared pointers handle this now, no real distinction between + // RemoveAll() and DeleteAll() + m_PropertyUIInfoList.clear(); + // envSTLHelpers::DeleteContainer(m_PropertyUIInfoList); +} + +//-------------------------------------------------------------------- +// find if the property is in the list by NAME +//-------------------------------------------------------------------- +bool +prtyPropertyUIInfoContainer::IsPropertyInList(const prtyProperty* i_pProperty) +{ + PropertyUIIList::iterator it = + std::find_if(m_PropertyUIInfoList.begin(), m_PropertyUIInfoList.end(), property_name_match(i_pProperty)); + if (it != m_PropertyUIInfoList.end()) { + return true; + } + return false; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const prtyProperty* +prtyPropertyUIInfoContainer::GetProperty(const std::string& i_Name) +{ + PropertyUIIList::iterator it = + std::find_if(m_PropertyUIInfoList.begin(), m_PropertyUIInfoList.end(), property_name_match_alt(i_Name)); + if (it != m_PropertyUIInfoList.end()) { + return (*it)->GetProperty(i_Name); + } + return NULL; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const std::shared_ptr +prtyPropertyUIInfoContainer::GetPropertyUIInfo(const std::string& i_Name) +{ + PropertyUIIList::iterator it = + std::find_if(m_PropertyUIInfoList.begin(), m_PropertyUIInfoList.end(), property_name_match_alt(i_Name)); + if (it != m_PropertyUIInfoList.end()) { + return (*it); + } + return std::shared_ptr(); +} + +//-------------------------------------------------------------------- +// get the UIInfo list +//-------------------------------------------------------------------- +PropertyUIIList& +prtyPropertyUIInfoContainer::GetPropertyUIInfoList() +{ + return m_PropertyUIInfoList; +} + +//------------------------------------------------------------------------ +// Sort the list by Category +//------------------------------------------------------------------------ +void +prtyPropertyUIInfoContainer::SortByCategory() +{ + // Sort the vector using predicate and std::sort + // std::sort(m_PropertyUIInfoList.begin(), m_PropertyUIInfoList.end(), category_sort()); + m_PropertyUIInfoList.sort(category_sort()); +} + +//------------------------------------------------------------------------ +// Sort the list by PropertyName +//------------------------------------------------------------------------ +void +prtyPropertyUIInfoContainer::SortByPropertyName() +{ + // Sort the vector using predicate and std::sort + // std::sort(m_PropertyUIInfoList.begin(), m_PropertyUIInfoList.end(), propertyname_sort()); + m_PropertyUIInfoList.sort(propertyname_sort()); +} + +//------------------------------------------------------------------------ +// Subcategories allow one property object to have a hierarchy of +// properties where unique names are only needed within each subcategory. +//------------------------------------------------------------------------ +int +prtyPropertyUIInfoContainer::GetNumSubCategories() const +{ + return m_SubCategories.size(); +} +const prtyPropertyUIInfoContainer& +prtyPropertyUIInfoContainer::GetSubCategory(int i_Index) const +{ + DBG_ASSERT(m_SubCategories[i_Index].m_Container, "Null property subcategory"); + return (*m_SubCategories[i_Index].m_Container); +} + +//------------------------------------------------------------------------ +// Add subcategory with given set of properties +//------------------------------------------------------------------------ +void +prtyPropertyUIInfoContainer::AddSubCategory(const std::string& i_CategoryName, + const std::shared_ptr& i_Properties) +{ + sSubCategory subcat = { i_CategoryName, i_Properties }; + m_SubCategories.push_back(subcat); +} + +//------------------------------------------------------------------------ +// Remove subcategory +//------------------------------------------------------------------------ +void +prtyPropertyUIInfoContainer::RemoveSubCategory(const std::shared_ptr& i_Properties) +{ + std::vector::iterator it; + for (it = m_SubCategories.begin(); it != m_SubCategories.end(); ++it) { + if (it->m_Container == i_Properties) + break; + } + + if (it != m_SubCategories.end()) + m_SubCategories.erase(it); +} + +//------------------------------------------------------------------------ +// There are two types of sub category name functions. One is the internal +// name for finding sub categories for python and scripting. The other +// is the display name, which can be localized. +//------------------------------------------------------------------------ +const std::string& +prtyPropertyUIInfoContainer::GetSubCategoryName(int i_Index) const +{ + return m_SubCategories[i_Index].m_Name; +} +const std::string& +prtyPropertyUIInfoContainer::GetSubCategoryDisplayName(int i_Index) const +{ + // No localization yet + return m_SubCategories[i_Index].m_Name; +} + +//------------------------------------------------------------------------ +// Set/Get show subcategory flag +//------------------------------------------------------------------------ +void +prtyPropertyUIInfoContainer::SetShowSubCategory(bool i_bShow) +{ + m_bShowSubCategories = i_bShow; +} + +bool +prtyPropertyUIInfoContainer::GetShowSubCategory() const +{ + return m_bShowSubCategories; +} \ No newline at end of file diff --git a/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp b/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp new file mode 100644 index 00000000..62b44c40 --- /dev/null +++ b/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp @@ -0,0 +1,157 @@ +/****************************************************************************\ +** prtyPropertyUIInfoContainer.hpp +** +** Container for property UI info +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_PROPERTYUIINFOCONTAINER_HPP +#error prtyPropertyUIInfoContainer.hpp multiply included +#endif +#define PRTY_PROPERTYUIINFOCONTAINER_HPP + +#ifndef PRTY_PROPERTYUIINFO_HPP +#include "core/prty/prtyPropertyUIInfo.hpp" +#endif + +#include + +//============================================================================ +//============================================================================ +class prtyProperty; +class nameString; + +//============================================================================ +//============================================================================ +// typedef std::list PropertyUIIList; + +// Using shared pointer here allows multiple views of the same properties, +// and allows the controls to maintain weak poitners to the ui info +// in order to know when the property info is no longer valid. +typedef std::list> PropertyUIIList; + +//============================================================================ +//============================================================================ +class prtyPropertyUIInfoContainer +{ +public: + //-------------------------------------------------------------------- + // destructor - this calls OWNS the prtyPropertyUIInfo instantiations + //-------------------------------------------------------------------- + ~prtyPropertyUIInfoContainer(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // void Add(prtyProperty* i_pProperty, + // const std::string& i_Category, + // const std::string& i_Description); + + //-------------------------------------------------------------------- + // Internally, the property UI Info list uses shared_ptr, so + // if you want to maintain a copy yourself, pass in a shared + // pointer. Otherwise, ownership of the pointer will be + // controlled by this list. + //-------------------------------------------------------------------- + void Add(prtyPropertyUIInfo* i_pUIInfo); + void Add(std::shared_ptr& i_pUIInfo); + void Add(const PropertyUIIList& i_UIInfoList); + + //-------------------------------------------------------------------- + // If you want to remove a UIInfo, keep a copy of the shared_ptr + // around and use that to remove it. + //-------------------------------------------------------------------- + void Remove(prtyProperty* i_pProperty); + void Remove(std::shared_ptr& i_pUIInfo); + + //-------------------------------------------------------------------- + // Remove all UIInfos from the container, but DO NOT delete them + // Note: this changes now that the internals are share_ptr. + // There is no more difference between RemoveAll() and + // DeleteAll(). + //-------------------------------------------------------------------- + void RemoveAll(); + + //-------------------------------------------------------------------- + // Delete all UIInfos from the container + //-------------------------------------------------------------------- + void DeleteAll(); + + //-------------------------------------------------------------------- + // find if the property is in the list by NAME + //-------------------------------------------------------------------- + bool IsPropertyInList(const prtyProperty* i_pProperty); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + inline const PropertyUIIList& GetList() const { return m_PropertyUIInfoList; } + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const prtyProperty* GetProperty(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const std::shared_ptr GetPropertyUIInfo(const std::string& i_Name); + + //-------------------------------------------------------------------- + // get the UIInfo list + //-------------------------------------------------------------------- + PropertyUIIList& GetPropertyUIInfoList(); + + //------------------------------------------------------------------------ + // Sort the list by PropertyName + //------------------------------------------------------------------------ + void SortByPropertyName(); + + //------------------------------------------------------------------------ + // Sort the list by Category + //------------------------------------------------------------------------ + void SortByCategory(); + + //------------------------------------------------------------------------ + // Subcategories allow one property object to have a hierarchy of + // properties where unique names are only needed within each subcategory. + //------------------------------------------------------------------------ + int GetNumSubCategories() const; + const prtyPropertyUIInfoContainer& GetSubCategory(int i_Index) const; + + //------------------------------------------------------------------------ + // Add subcategory with given set of properties + //------------------------------------------------------------------------ + void AddSubCategory(const std::string& i_CategoryName, + const std::shared_ptr& i_Properties); + + //------------------------------------------------------------------------ + // Remove subcategory + //------------------------------------------------------------------------ + void RemoveSubCategory(const std::shared_ptr& i_Properties); + + //------------------------------------------------------------------------ + // There are two types of sub category name functions. One is the internal + // name for finding sub categories for python and scripting. The other + // is the display name, which can be localized. + //------------------------------------------------------------------------ + const std::string& GetSubCategoryName(int i_Index) const; + const std::string& GetSubCategoryDisplayName(int i_Index) const; + + //------------------------------------------------------------------------ + // Set/Get show subcategory flag + //------------------------------------------------------------------------ + void SetShowSubCategory(bool i_bShow); + bool GetShowSubCategory() const; + +private: + PropertyUIIList m_PropertyUIInfoList; + + struct sSubCategory + { + std::string m_Name; + std::shared_ptr m_Container; + }; + + std::vector m_SubCategories; + + bool m_bShowSubCategories; +}; diff --git a/renderlib/core/prty/prtyText.cpp b/renderlib/core/prty/prtyText.cpp new file mode 100644 index 00000000..33039fe9 --- /dev/null +++ b/renderlib/core/prty/prtyText.cpp @@ -0,0 +1,111 @@ +/****************************************************************************\ +** prtyText.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyText.hpp" + +// #include "core/ch/chChunkParserUtil.hpp" +// #include "core/ch/chReader.hpp" + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyText::prtyText() + : prtyPropertyTemplate("Text", std::string()) +{ +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyText::prtyText(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, std::string()) +{ +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +prtyText::prtyText(const std::string& i_Name, const std::string& i_InitialValue) + : prtyPropertyTemplate(i_Name, i_InitialValue) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyText::GetType() +{ + return "Text"; +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyText& +prtyText::operator=(const prtyText& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + + SetValue(i_Property.GetValue()); + return *this; +} +prtyText& +prtyText::operator=(const std::string& i_Value) +{ + SetValue(i_Value); + return *this; +} +prtyText& +prtyText::operator=(const char* i_Value) +{ + SetValue(std::string(i_Value)); + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyText::operator==(const prtyText& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyText::operator!=(const prtyText& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyText::operator==(const std::string& i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyText::operator!=(const std::string& i_Value) const +{ + return (m_Value != i_Value); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyText::Read(chReader& io_Reader) +{ + // std::string temp; + // chChunkParserUtil::Read(io_Reader, temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyText::Write(chWriter& io_Writer) const +{ + // chChunkParserUtil::Write(io_Writer, GetValue()); +} diff --git a/renderlib/core/prty/prtyText.hpp b/renderlib/core/prty/prtyText.hpp new file mode 100644 index 00000000..aa76024a --- /dev/null +++ b/renderlib/core/prty/prtyText.hpp @@ -0,0 +1,62 @@ +/****************************************************************************\ +** prtyText.hpp +** +** Text property +** +** +** +\****************************************************************************/ +#ifdef PRTY_TEXT_HPP +#error prtyText.hpp multiply included +#endif +#define PRTY_TEXT_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +//============================================================================ +//============================================================================ +class prtyText : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyText(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyText(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyText(const std::string& i_Name, const std::string& i_InitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyText& operator=(const prtyText& i_Property); + prtyText& operator=(const std::string& i_Value); + prtyText& operator=(const char* i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyText& i_Property) const; + bool operator!=(const prtyText& i_Property) const; + bool operator==(const std::string& i_Value) const; + bool operator!=(const std::string& i_Value) const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; +}; diff --git a/renderlib/core/prty/prtyUndoTemplate.cpp b/renderlib/core/prty/prtyUndoTemplate.cpp new file mode 100644 index 00000000..a01eaeee --- /dev/null +++ b/renderlib/core/prty/prtyUndoTemplate.cpp @@ -0,0 +1,9 @@ +/***************************************************************************** +** prtyUndoTemplate.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "prtyUndoTemplate.hpp" diff --git a/renderlib/core/prty/prtyUndoTemplate.hpp b/renderlib/core/prty/prtyUndoTemplate.hpp new file mode 100644 index 00000000..75e698d2 --- /dev/null +++ b/renderlib/core/prty/prtyUndoTemplate.hpp @@ -0,0 +1,126 @@ +/***************************************************************************** +** prtyUndoTemplate.hpp +** +** store a state of Text for undo/redo +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_UNDOTEMPLATE_HPP +#error prtyUndoTemplate.hpp multiply included +#endif +#define PRTY_UNDOTEMPLATE_HPP + +#ifndef UNDO_UNDOOPERATION_HPP +#include "core/undo/undoUndoOperation.hpp" +#endif +#ifndef PRTY_PROPERTYREFERENCE_HPP +#include "core/prty/prtyPropertyReference.hpp" +#endif + +#include "core/prty/prtyProperty.hpp" + +//============================================================================ +//============================================================================ +template +class prtyUndoTemplate : public undoUndoOperation +{ +public: + //-------------------------------------------------------------------- + // constructor takes old to be restored if undone + //-------------------------------------------------------------------- + prtyUndoTemplate(std::shared_ptr i_pPropertyRef, const BackupType& i_PropertyBackup) + : m_pPropertyRef(i_pPropertyRef) + , m_PropertyBackup(i_PropertyBackup) + { + } + + //-------------------------------------------------------------------- + // Get Name for the operation + //-------------------------------------------------------------------- + std::string GetDisplayName() + { + prtyProperty* pProperty = (m_pPropertyRef) ? m_pPropertyRef->GetProperty() : NULL; + return ((pProperty) ? pProperty->GetPropertyName() : ""); + } + + //-------------------------------------------------------------------- + // Get memory usage for this operation (in KB). This can be + // accurate or approximate. + //-------------------------------------------------------------------- + float GetMemoryUsage() + { + return (sizeof(BackupType) / 1000.0f); // convert to KB + } + + //-------------------------------------------------------------------- + // Undo is called on an operation when the user chooses + // Edit->Undo from the menu. + //-------------------------------------------------------------------- + void Undo() + { + PropertyType* pProperty = resolve_property(); + if (pProperty) { + BackupType temp = pProperty->GetValue(); + const bool bFromUndo = true; + pProperty->SetValue(m_PropertyBackup, bFromUndo); + m_PropertyBackup = temp; // switch backup from undo to redo + } + } + + //-------------------------------------------------------------------- + // Redo is called on an operation when the user chooses + // Edit->Redo from the menu and this operation is the next in + // line to be redone. + //-------------------------------------------------------------------- + void Redo() + { + PropertyType* pProperty = resolve_property(); + if (pProperty) { + BackupType temp = pProperty->GetValue(); + const bool bFromUndo = true; + pProperty->SetValue(m_PropertyBackup, bFromUndo); + m_PropertyBackup = temp; // switch backup from undo to redo + } + } + + //-------------------------------------------------------------------- + // Commit is called on an operation when it is no longer + // possible for the user to undo this operation. The + // destructor will soon be called. + //-------------------------------------------------------------------- + void Commit() + { + // nothing needed + } + + //-------------------------------------------------------------------- + // Destroy is called on an operation when it has been undone + // and it can no longer be redone. This may happen after the + // history gets long enough or a new operation is made when + // its current state is "undone". The destructor will soon be + // called. + //-------------------------------------------------------------------- + void Destroy() + { + // nothing needed + } + +private: + //-------------------------------------------------------------------- + // convert property reference into a property of our type + //-------------------------------------------------------------------- + PropertyType* resolve_property() + { + if (m_pPropertyRef) { + prtyProperty* pProperty = m_pPropertyRef->GetProperty(); + if (pProperty) + return dynamic_cast(pProperty); + } + return NULL; + } + + std::shared_ptr m_pPropertyRef; + BackupType m_PropertyBackup; +}; diff --git a/renderlib/core/prty/prtyUnits.cpp b/renderlib/core/prty/prtyUnits.cpp new file mode 100644 index 00000000..d5e1100e --- /dev/null +++ b/renderlib/core/prty/prtyUnits.cpp @@ -0,0 +1,132 @@ +/****************************************************************************\ +** prtyUnits.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyUnits.hpp" + +// library +// #include "core/dbg/dbgMsg.hpp" +#include "core/env/envSTLHelpers.hpp" + +#include + +//============================================================================ +//============================================================================ +namespace { +std::vector l_UnitsInterestList; + +// Internal units are centimeters, but the default +// display units is meters. +prtyUnits::UnitTypes l_CurrentUnits = prtyUnits::e_Meters; +float l_UnitsScaling = 100.0f; +// prtyUnits::UnitTypes l_CurrentUnits = prtyUnits::e_Centimeters; +// float l_UnitsScaling = 1.0f; +} + +//-------------------------------------------------------------------- +// UnitSystem - set/get units to use for displaying distances +// in user interface. This is converted into the UnitScaling +// that converts from internal units (cm) into display units. +//-------------------------------------------------------------------- +void +prtyUnits::SetUnitSystem(UnitTypes i_Units) +{ + // Set UnitsScaling based on a factor that converts + // centimeters to the current units + switch (i_Units) { + default: + case e_Centimeters: + l_UnitsScaling = 1.0f; + break; + case e_Meters: + l_UnitsScaling = 100.0f; + break; + case e_Inches: + l_UnitsScaling = 2.54f; + break; + case e_Feet: + l_UnitsScaling = 2.54f * 12.0f; + break; + } + + // notify scale interests + std::vector::iterator it, end = l_UnitsInterestList.end(); + for (it = l_UnitsInterestList.begin(); it != end; ++it) { + (*it)->UnitsChanged(); + } +} +prtyUnits::UnitTypes +prtyUnits::GetUnitSystem() +{ + return l_CurrentUnits; +} + +//-------------------------------------------------------------------- +// Get conversion scaling to convert from display units to +// internal units (cm). Divide by the scaling to convert from +// internal units to display units. +//-------------------------------------------------------------------- +float +prtyUnits::GetUnitScaling() +{ + return l_UnitsScaling; +} + +//-------------------------------------------------------------------- +// GetShortString - return a short encoding for the current units, +// and a function to set the units using this string. +// examples: "cm", "m", "in", "ft" +//-------------------------------------------------------------------- +prtyUnits::UnitTypes +prtyUnits::GetUnitsByShortString(const std::string& i_Units) +{ + if (i_Units == "m") + return e_Meters; + else if (i_Units == "in") + return e_Inches; + else if (i_Units == "ft") + return e_Feet; + else + return e_Centimeters; +} +std::string +prtyUnits::GetShortString(UnitTypes i_Units) +{ + switch (i_Units) { + default: + case e_Centimeters: + return "cm"; + case e_Meters: + return "m"; + case e_Inches: + return "in"; + case e_Feet: + return "ft"; + } +} + +//-------------------------------------------------------------------- +// RegisterUnitsInterest() - add a Units interest to the system +//-------------------------------------------------------------------- +void +prtyUnits::RegisterUnitsInterest(prtyUnitsInterest* i_pInterest) +{ + DBG_ASSERT(i_pInterest != 0, "Cannot register a NULL Scale Interest"); + l_UnitsInterestList.push_back(i_pInterest); +} + +//-------------------------------------------------------------------- +// UnRegisterUnitsInterest() - remove a Units interest from the system. +// +// Note: this will NOT delete the Units interest. It is up to the +// registerer. +//-------------------------------------------------------------------- +void +prtyUnits::UnRegisterUnitsInterest(prtyUnitsInterest* i_pInterest) +{ + envSTLHelpers::RemoveOneValue(l_UnitsInterestList, i_pInterest); +} diff --git a/renderlib/core/prty/prtyUnits.hpp b/renderlib/core/prty/prtyUnits.hpp new file mode 100644 index 00000000..498bb26b --- /dev/null +++ b/renderlib/core/prty/prtyUnits.hpp @@ -0,0 +1,90 @@ +/*****************************************************************************\ +** prtyUnits.hpp +** +** Tracks the units for display of properties realted to distance. +** +** +** +\****************************************************************************/ +#ifdef PRTY_UNITS_HPP +#error prtyUnits.hpp multiply included +#endif +#define PRTY_UNITS_HPP + +#include + +//============================================================================ +// Forward References +//============================================================================ +class prtyUnitsInterest; + +//============================================================================ +//============================================================================ +class prtyUnitsInterest +{ +public: + //-------------------------------------------------------------------- + // UnitsChanged - notification that the units for the + // user interface has changed. + //-------------------------------------------------------------------- + virtual void UnitsChanged() = 0; +}; + +//============================================================================ +//============================================================================ +namespace prtyUnits { +//-------------------------------------------------------------------- +// Enumeration of unit systems +//-------------------------------------------------------------------- +enum UnitTypes +{ + e_Centimeters = 0, + e_Meters, + e_Inches, + e_Feet +}; + +//-------------------------------------------------------------------- +// UnitSystem - set/get units to use for displaying distances +// in user interface. This is converted into the UnitScaling +// that converts from internal units (cm) into display units. +//-------------------------------------------------------------------- +void +SetUnitSystem(UnitTypes i_Units); +UnitTypes +GetUnitSystem(); + +//-------------------------------------------------------------------- +// Get conversion scaling to convert from display units to +// internal units (cm). Divide by the scaling to convert from +// internal units to display units. +//-------------------------------------------------------------------- +float +GetUnitScaling(); + +//-------------------------------------------------------------------- +// GetShortString - return a short encoding for the current units, +// and a function to get the units using this string. +// examples: "cm", "m", "in", "ft" +//-------------------------------------------------------------------- +UnitTypes +GetUnitsByShortString(const std::string& i_Units); +std::string +GetShortString(UnitTypes i_Units); + +//-------------------------------------------------------------------- +// RegisterUnitsInterest() - add a Units interest to the system +//-------------------------------------------------------------------- +void +RegisterUnitsInterest(prtyUnitsInterest* i_pInterest); + +//-------------------------------------------------------------------- +// UnRegisterUnitsInterest() - remove a Units interest from the system. +// +// Note: this will NOT delete the Units interest. It is up to the +// registerer. +//-------------------------------------------------------------------- +void +UnRegisterUnitsInterest(prtyUnitsInterest* i_pInterest); + +}; diff --git a/renderlib/core/undo/CMakeLists.txt b/renderlib/core/undo/CMakeLists.txt new file mode 100644 index 00000000..31a49707 --- /dev/null +++ b/renderlib/core/undo/CMakeLists.txt @@ -0,0 +1,11 @@ +target_sources(renderlib PRIVATE +"${CMAKE_CURRENT_SOURCE_DIR}/undoMultipleOperation.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoMultipleOperation.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoMultipleOperationBlock.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoUndoInterest.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoUndoInterest.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoUndoMgr.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoUndoMgr.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoUndoOperation.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/undoUndoOperation.hpp" +) \ No newline at end of file diff --git a/renderlib/core/undo/undoMultipleOperation.cpp b/renderlib/core/undo/undoMultipleOperation.cpp new file mode 100644 index 00000000..e18671e7 --- /dev/null +++ b/renderlib/core/undo/undoMultipleOperation.cpp @@ -0,0 +1,141 @@ +/***************************************************************************** +** undoMultipleOperation.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/undo/undoMultipleOperation.hpp" + +#include "Logging.h" +#include "core/env/envSTLHelpers.hpp" + +//-------------------------------------------------------------------- +// If a name is passed in here, then it will be used for the +// operation block as a whole. Otherwise, the name will come from +// the first operation's display name. +//-------------------------------------------------------------------- +undoMultipleOperation::undoMultipleOperation(const char* i_Name) +{ + if (i_Name != NULL) + m_Name = i_Name; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +undoMultipleOperation::~undoMultipleOperation() +{ + envSTLHelpers::DeleteContainer(m_Operations); +} + +//-------------------------------------------------------------------- +// Add operation to this multiple operation block. +// Ownership passes to this object. +//-------------------------------------------------------------------- +void +undoMultipleOperation::AddOperation(undoUndoOperation* i_pOperation) +{ + DBG_ASSERT(i_pOperation, "NULL operation passed to AddOperation"); + m_Operations.push_back(i_pOperation); + + // DBG_LOG("AddOperation, new size: " << m_Operations.size()); +} + +//-------------------------------------------------------------------- +// Returns number of operations in the stack. +//-------------------------------------------------------------------- +int +undoMultipleOperation::GetNumOperations() +{ + return m_Operations.size(); +} + +//-------------------------------------------------------------------- +// Returns true iff the operation is in the list of operations +// in this block. +//-------------------------------------------------------------------- +bool +undoMultipleOperation::ContainsOperation(undoUndoOperation* i_pOperation) +{ + return envSTLHelpers::Contains(m_Operations, i_pOperation); +} + +//-------------------------------------------------------------------- +// Get Name for the operation +//-------------------------------------------------------------------- +std::string +undoMultipleOperation::GetDisplayName() +{ + // DBG_LOG("GetDisplayName, size: " << m_Operations.size()); + + if (m_Name.empty() && !m_Operations.empty()) { + return m_Operations[0]->GetDisplayName(); + } + return m_Name; +} + +//-------------------------------------------------------------------- +// Get memory usage for this operation (in KB). This can be accurate +// or approximate. +//-------------------------------------------------------------------- +float +undoMultipleOperation::GetMemoryUsage() +{ + float sum = 0.0f; + const int num_ops = m_Operations.size(); + for (int i = 0; i < num_ops; i++) { + sum += m_Operations[i]->GetMemoryUsage(); + } + return sum; +} + +//-------------------------------------------------------------------- +// Undo is called on an operation when the user chooses +// Edit->Undo from the menu. +//-------------------------------------------------------------------- +void +undoMultipleOperation::Undo() +{ + // bga- undo has to be done in reverse in order to restore original state correctly + // envSTLHelpers::ForAll(m_Operations, envSTLHelpers::MemFun(&undoUndoOperation::Undo)); + const int num_ops = m_Operations.size(); + for (int i = num_ops - 1; i >= 0; i--) { + m_Operations[i]->Undo(); + } +} + +//-------------------------------------------------------------------- +// Redo is called on an operation when the user chooses +// Edit->Redo from the menu and this operation is the next in +// line to be redone. +//-------------------------------------------------------------------- +void +undoMultipleOperation::Redo() +{ + envSTLHelpers::ForAll(m_Operations, std::mem_fn(&undoUndoOperation::Redo)); +} + +//-------------------------------------------------------------------- +// Commit is called on an operation when it is no longer +// possible for the user to undo this operation. The +// destructor will soon be called. This may happen if the +// history gets too long, or the file is saved. +//-------------------------------------------------------------------- +void +undoMultipleOperation::Commit() +{ + envSTLHelpers::ForAll(m_Operations, std::mem_fn(&undoUndoOperation::Commit)); +} + +//-------------------------------------------------------------------- +// Destroy is called on an operation when it has been undone +// and it can no longer be redone. This may happen after +// a new operation is made when its current state is "undone". +// The destructor will soon be called. +//-------------------------------------------------------------------- +void +undoMultipleOperation::Destroy() +{ + envSTLHelpers::ForAll(m_Operations, std::mem_fn(&undoUndoOperation::Destroy)); +} \ No newline at end of file diff --git a/renderlib/core/undo/undoMultipleOperation.hpp b/renderlib/core/undo/undoMultipleOperation.hpp new file mode 100644 index 00000000..86aa150d --- /dev/null +++ b/renderlib/core/undo/undoMultipleOperation.hpp @@ -0,0 +1,97 @@ +/***************************************************************************** +** undoMultipleOperation.hpp +** +** This class can be used to group a number of single undo operations +** into one undo operation that can be undone and redone in one step. +** +** +** +\****************************************************************************/ +#ifdef UNDO_MULTIPLEOPERATION_HPP +#error undoUndoOperation.hpp multiply included +#endif +#define UNDO_MULTIPLEOPERATION_HPP + +#ifndef UNDO_UNDOOPERATION_HPP +#include "core/undo/undoUndoOperation.hpp" +#endif + +#include + +//============================================================================ +//============================================================================ +class undoMultipleOperation : public undoUndoOperation +{ +public: + //-------------------------------------------------------------------- + // If a name is passed in here, then it will be used for the + // operation block as a whole. Otherwise, the name will come from + // the first operation's display name. + //-------------------------------------------------------------------- + undoMultipleOperation(const char* i_Name = NULL); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual ~undoMultipleOperation(); + + //-------------------------------------------------------------------- + // Add operation to this multiple operation block. + // Ownership passes to this object. + //-------------------------------------------------------------------- + void AddOperation(undoUndoOperation* i_pOperation); + + //-------------------------------------------------------------------- + // Returns number of operations in the stack. + //-------------------------------------------------------------------- + int GetNumOperations(); + + //-------------------------------------------------------------------- + // Returns true iff the operation is in the list of operations + // in this block. + //-------------------------------------------------------------------- + bool ContainsOperation(undoUndoOperation* i_pOperation); + + //-------------------------------------------------------------------- + // Get Name for the operation + //-------------------------------------------------------------------- + virtual std::string GetDisplayName(); + + //-------------------------------------------------------------------- + // Get memory usage for this operation (in KB). This can be accurate + // or approximate. + //-------------------------------------------------------------------- + virtual float GetMemoryUsage(); + + //-------------------------------------------------------------------- + // Undo is called on an operation when the user chooses + // Edit->Undo from the menu. + //-------------------------------------------------------------------- + virtual void Undo(); + + //-------------------------------------------------------------------- + // Redo is called on an operation when the user chooses + // Edit->Redo from the menu and this operation is the next in + // line to be redone. + //-------------------------------------------------------------------- + virtual void Redo(); + + //-------------------------------------------------------------------- + // Commit is called on an operation when it is no longer + // possible for the user to undo this operation. The + // destructor will soon be called. This may happen if the + // history gets too long, or the file is saved. + //-------------------------------------------------------------------- + virtual void Commit(); + + //-------------------------------------------------------------------- + // Destroy is called on an operation when it has been undone + // and it can no longer be redone. This may happen after + // a new operation is made when its current state is "undone". + // The destructor will soon be called. + //-------------------------------------------------------------------- + virtual void Destroy(); + +private: + std::string m_Name; + std::vector m_Operations; +}; diff --git a/renderlib/core/undo/undoMultipleOperationBlock.hpp b/renderlib/core/undo/undoMultipleOperationBlock.hpp new file mode 100644 index 00000000..28892ba0 --- /dev/null +++ b/renderlib/core/undo/undoMultipleOperationBlock.hpp @@ -0,0 +1,47 @@ +/***************************************************************************** +** undoMultipleOperationBlock.hpp +** +** A helper class for begining and ending a multiple operation +** undo block. The class begin the block on constructor and ends +** it on destructor so that exceptions don't throw off the block stack. +** +** +** +\****************************************************************************/ +#ifdef UNDO_UNDOMULTIPLEOPERATIONBLOCK_HPP +#error undoMultipleOperationBlock.hpp multiply included +#endif +#define UNDO_UNDOMULTIPLEOPERATIONBLOCK_HPP + +#ifndef UNDO_UNDOMGR_HPP +#include "core/undo/undoUndoMgr.hpp" +#endif + +//============================================================================ +//============================================================================ +class undoMultipleOperationBlock +{ +public: + //-------------------------------------------------------------------- + // Creates a multiple operation undo block if i_bDoBlock is true. + //-------------------------------------------------------------------- + undoMultipleOperationBlock(const char* i_Name = NULL, bool i_bDoBlock = true) + : m_bDoBlock(i_bDoBlock) + { + if (m_bDoBlock) + undoUndoMgr::BeginMultipleOperationBlock(i_Name); + } + + //-------------------------------------------------------------------- + // Ends multiple operation block in destructor if one was started + // in constructor + //-------------------------------------------------------------------- + ~undoMultipleOperationBlock() + { + if (m_bDoBlock) + undoUndoMgr::EndMultipleOperationBlock(); + } + +private: + bool m_bDoBlock; +}; diff --git a/renderlib/core/undo/undoUndoInterest.cpp b/renderlib/core/undo/undoUndoInterest.cpp new file mode 100644 index 00000000..ca46f3e4 --- /dev/null +++ b/renderlib/core/undo/undoUndoInterest.cpp @@ -0,0 +1,9 @@ +/****************************************************************************\ +** undoUndoInterest.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/undo/undoUndoInterest.hpp" diff --git a/renderlib/core/undo/undoUndoInterest.hpp b/renderlib/core/undo/undoUndoInterest.hpp new file mode 100644 index 00000000..b8763235 --- /dev/null +++ b/renderlib/core/undo/undoUndoInterest.hpp @@ -0,0 +1,29 @@ +/****************************************************************************\ +** undoUndoInterest.hpp +** +** An Undo Interest is something that cares about the undo system +** changing. +** +** +** +\****************************************************************************/ +#ifdef UNDO_UNDOINTEREST_HPP +#error undoUndoInterest.hpp multiply included +#endif +#define UNDO_UNDOINTEREST_HPP + +//============================================================================ +//============================================================================ +class undoUndoInterest +{ +public: + //-------------------------------------------------------------------- + // UndoAdded - undo event added to the stack + //-------------------------------------------------------------------- + virtual void UndoAdded() = 0; + + //-------------------------------------------------------------------- + // StackChanged - undo stack changed + //-------------------------------------------------------------------- + virtual void StackChanged() = 0; +}; diff --git a/renderlib/core/undo/undoUndoMgr.cpp b/renderlib/core/undo/undoUndoMgr.cpp new file mode 100644 index 00000000..0a9db9c2 --- /dev/null +++ b/renderlib/core/undo/undoUndoMgr.cpp @@ -0,0 +1,362 @@ +/***************************************************************************** +** undoUndoMgr.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/undo/undoUndoMgr.hpp" + +#include "core/undo/undoMultipleOperation.hpp" +#include "core/undo/undoUndoInterest.hpp" + +#include "Logging.h" +#include "core/env/envSTLHelpers.hpp" + +#include +#include + +//============================================================================ +//============================================================================ +namespace undoUndoMgr { +namespace { +// Use deque to put new operations in front, removing +// off of the back to reduce memory and tracking the +// number of undone operation with a counter that +// can be indexed into deque from the front. +std::deque l_Operations; +int l_NumUndos = 0; + +// Stack of open multiple operation blocks +std::stack l_BlockUndos; + +// limits on size of deque +float l_MemoryMaxUsage = 0; +int l_MinSizeOfUndoStack = 40; + +float l_CurrentMemoryUsage = 0; + +std::vector l_Interests; + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +notify_interests_undo_added() +{ + int num = l_Interests.size(); + for (int i = 0; i < num; i++) { + l_Interests[i]->UndoAdded(); + } +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +notify_interests_stack_changed() +{ + int num = l_Interests.size(); + for (int i = 0; i < num; i++) { + l_Interests[i]->StackChanged(); + } +} + +//-------------------------------------------------------------------- +// Call Destroy on undone operations, delete them +// and remove them from the list +//-------------------------------------------------------------------- +void +destroy_undone() +{ + for (int i = 0; i < l_NumUndos; i++) { + undoUndoOperation* op = l_Operations.front(); + l_CurrentMemoryUsage -= op->GetMemoryUsage(); + op->Destroy(); + delete op; + l_Operations.pop_front(); + } + l_NumUndos = 0; + + notify_interests_stack_changed(); +} + +//-------------------------------------------------------------------- +// add operation to stack +//-------------------------------------------------------------------- +void +add_operation(undoUndoOperation* i_Op) +{ + if (l_NumUndos > 0) { + // Destroy undone operations + destroy_undone(); + } + + // Track memory usage and maybe remove operations from + // the back, calling Commit() on them + while ((l_CurrentMemoryUsage > l_MemoryMaxUsage) && (l_Operations.size() > l_MinSizeOfUndoStack)) { + undoUndoOperation* op = l_Operations.back(); + l_CurrentMemoryUsage -= op->GetMemoryUsage(); + op->Commit(); + delete op; + l_Operations.pop_back(); + } + + l_Operations.push_front(i_Op); + l_CurrentMemoryUsage += i_Op->GetMemoryUsage(); +} +} // end of namespace + +//-------------------------------------------------------------------- +// Set memory limit for history buffer (in KB) except it is allowed +// to go over the limit in order to maintain at least a certain +// minimum size to the undo stack. +//-------------------------------------------------------------------- +void +SetLimits(float i_MemoryMaxUsage, int i_MinSizeOfUndoStack) +{ + l_MemoryMaxUsage = i_MemoryMaxUsage; + l_MinSizeOfUndoStack = i_MinSizeOfUndoStack; + if (l_MinSizeOfUndoStack < 0) + l_MinSizeOfUndoStack = 0; +} + +//-------------------------------------------------------------------- +// Call AddOperation to add an undo step to the stack +//-------------------------------------------------------------------- +void +AddOperation(undoUndoOperation* i_Op) +{ + if (!l_BlockUndos.empty()) { + undoMultipleOperation* multi_op = l_BlockUndos.top(); + multi_op->AddOperation(i_Op); + } else { + add_operation(i_Op); + notify_interests_undo_added(); + } +} + +//-------------------------------------------------------------------- +// BeginMultipleOperationBlock - subsequent calls to AddOperation +// will be added to a undoMultipleOperation block. After the +// call to EndMultipleOperationBlock, this set of operations +// will appear as one operation in the stack. +//-------------------------------------------------------------------- +void +BeginMultipleOperationBlock(const char* i_Name) +{ + undoMultipleOperation* multi_op = new undoMultipleOperation(i_Name); + l_BlockUndos.push(multi_op); +} +void +EndMultipleOperationBlock() +{ + undoMultipleOperation* multi_op = l_BlockUndos.top(); + DBG_ASSERT(multi_op, "EndMultipleOperationBlock does not match number of Begin calls"); + l_BlockUndos.pop(); + + // Only add the multi-op if stack is finished and + // some operations have been added to it. + if (l_BlockUndos.empty() && multi_op->GetNumOperations() > 0) { + add_operation(multi_op); + notify_interests_undo_added(); + } else { + // If we don't add the operation, need to delete it. + delete multi_op; + } +} + +//-------------------------------------------------------------------- +// Returns pointer to last operation to have been added. May return NULL +// if the buffer is cleared, or if some operations have been undone. +//-------------------------------------------------------------------- +undoUndoOperation* +PeekLastOperation() +{ + if (l_Operations.empty()) + return NULL; + if (l_NumUndos > 0) + return NULL; + return l_Operations.front(); +} + +//-------------------------------------------------------------------- +// See if the given operation is either the last operation, or is +// part of a multiple undo block that is the last operation. +//-------------------------------------------------------------------- +bool +IsInLastOperation(undoUndoOperation* i_pOperation) +{ + if (!i_pOperation) + return false; + + undoUndoOperation* pLastOp = PeekLastOperation(); + if (pLastOp == i_pOperation) + return true; + + // If the last operation is a multiple undo block, then + // look for the operation in this block. + undoMultipleOperation* pMultiOp = dynamic_cast(pLastOp); + if (pMultiOp) { + bool found = pMultiOp->ContainsOperation(i_pOperation); + return found; + } + + return false; +} + +//-------------------------------------------------------------------- +// Call Commit when it is no longer possible for the user to +// undo any operation. This should be called when an undoable +// operation takes place or some serializing (read or write) +// has taken place +//-------------------------------------------------------------------- +void +Commit() +{ + if (l_NumUndos > 0) { + // Destroy undone operations + destroy_undone(); + } + + // Call Commit on all other operations, delete them + // and clear the whole queue + while (!l_Operations.empty()) { + undoUndoOperation* op = l_Operations.back(); + l_CurrentMemoryUsage -= op->GetMemoryUsage(); + op->Commit(); + delete op; + l_Operations.pop_back(); + } + + notify_interests_stack_changed(); +} + +//-------------------------------------------------------------------- +// Call Undo when the user chooses Edit->Undo from the menu. +//-------------------------------------------------------------------- +void +Undo() +{ + if (l_NumUndos < l_Operations.size()) { + l_Operations[l_NumUndos]->Undo(); + l_NumUndos++; + + notify_interests_stack_changed(); + } +} + +//-------------------------------------------------------------------- +// Use this to set the Enabled state of the Edit->Undo button +//-------------------------------------------------------------------- +bool +CanUndo() +{ + return (l_Operations.size() > l_NumUndos); +} + +//-------------------------------------------------------------------- +// Returns display string for the type of operation to be undone +// if Undo were to be called. +//-------------------------------------------------------------------- +std::string +GetUndoOperationName() +{ + if (l_NumUndos < l_Operations.size()) { + return l_Operations[l_NumUndos]->GetDisplayName(); + } + return ""; +} + +//-------------------------------------------------------------------- +// Returns the index in the stack for the next undo operation. +// -1 is returned if the stack is empty or nothing left to undo. +//-------------------------------------------------------------------- +int +GetUndoOperationIndex() +{ + if (l_NumUndos < l_Operations.size()) { + return l_NumUndos; + } + return -1; +} + +//-------------------------------------------------------------------- +// Call Redo when the user chooses Edit->Redo from the menu +//-------------------------------------------------------------------- +void +Redo() +{ + if (l_NumUndos > 0) { + l_NumUndos--; + l_Operations[l_NumUndos]->Redo(); + + notify_interests_stack_changed(); + } +} + +//-------------------------------------------------------------------- +// Use this to set the Enabled state of the Edit->Redo button +//-------------------------------------------------------------------- +bool +CanRedo() +{ + return (l_NumUndos > 0); +} + +//-------------------------------------------------------------------- +// Returns display string for the type of operation to be redone +// if Redo were to be called. +//-------------------------------------------------------------------- +std::string +GetRedoOperationName() +{ + if (l_NumUndos > 0) { + return l_Operations[l_NumUndos - 1]->GetDisplayName(); + } + return ""; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +GetUndoStack(std::vector& i_Stack) +{ + i_Stack.resize(l_Operations.size()); + + for (int i = 0; i < l_Operations.size(); i++) { + undoUndoOperation* op = l_Operations[i]; + i_Stack[i] = op->GetDisplayName(); + } +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +float +GetMaximumMemoryUsage() +{ + return l_MemoryMaxUsage; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +float +GetCurrentMemoryUsage() +{ + return l_CurrentMemoryUsage; +} + +//-------------------------------------------------------------------- +// Add/RemoveInterest() - add or remove an interest for Undo +//-------------------------------------------------------------------- +void +AddInterest(undoUndoInterest* i_pInterest) +{ + l_Interests.push_back(i_pInterest); +} +void +RemoveInterest(undoUndoInterest* i_pInterest) +{ + envSTLHelpers::RemoveOneValue(l_Interests, i_pInterest); +} + +} // end of namespace diff --git a/renderlib/core/undo/undoUndoMgr.hpp b/renderlib/core/undo/undoUndoMgr.hpp new file mode 100644 index 00000000..b9bea890 --- /dev/null +++ b/renderlib/core/undo/undoUndoMgr.hpp @@ -0,0 +1,144 @@ +/***************************************************************************** +** undoUndoMgr.hpp +** +** An UndoOperation should be created each time a step is +** taken that can be undone. The UndoMgr keeps track of the +** last few operations. +** +** +** +\****************************************************************************/ +#ifdef UNDO_UNDOMGR_HPP +#error undoUndoMgr.hpp multiply included +#endif +#define UNDO_UNDOMGR_HPP + +#include +#include + +//============================================================================ +//============================================================================ +class undoUndoInterest; +class undoUndoOperation; + +//============================================================================ +//============================================================================ +namespace undoUndoMgr { +//-------------------------------------------------------------------- +// Set memory limit for history buffer (in KB) except it is allowed +// to go over the limit in order to maintain at least a certain +// minimum size to the undo stack. +//-------------------------------------------------------------------- +void +SetLimits(float i_MemoryMaxUsage, int i_MinSizeOfUndoStack = 3); + +//-------------------------------------------------------------------- +// Call AddOperation to add an undo step to the stack +//-------------------------------------------------------------------- +void +AddOperation(undoUndoOperation* i_Op); + +//-------------------------------------------------------------------- +// BeginMultipleOperationBlock - subsequent calls to AddOperation +// will be added to a undoMultipleOperation block. After the +// call to EndMultipleOperationBlock, this set of operations +// will appear as one operation in the stack. +// Name is optional. +//-------------------------------------------------------------------- +void +BeginMultipleOperationBlock(const char* i_Name = NULL); +void +EndMultipleOperationBlock(); + +//-------------------------------------------------------------------- +// Returns pointer to last operation to have been added. May return NULL +// if the buffer is cleared, or if some operations have been undone. +//-------------------------------------------------------------------- +undoUndoOperation* +PeekLastOperation(); + +//-------------------------------------------------------------------- +// See if the given operation is either the last operation, or is +// part of a multiple undo block that is the last operation. +//-------------------------------------------------------------------- +bool +IsInLastOperation(undoUndoOperation* i_pOperation); + +//-------------------------------------------------------------------- +// Call Commit when it is no longer possible for the user to +// undo any operation. This should be called when an undoable +// operation takes place or some serializing (read or write) +// has taken place +//-------------------------------------------------------------------- +void +Commit(); + +//-------------------------------------------------------------------- +// Call Undo when the user chooses Edit->Undo from the menu. +//-------------------------------------------------------------------- +void +Undo(); + +//-------------------------------------------------------------------- +// Use this to set the Enabled state of the Edit->Undo button +//-------------------------------------------------------------------- +bool +CanUndo(); + +//-------------------------------------------------------------------- +// Returns display string for the type of operation to be undone +// if Undo were to be called. +//-------------------------------------------------------------------- +std::string +GetUndoOperationName(); + +//-------------------------------------------------------------------- +// Returns the index in the stack for the next undo operation. +// -1 is returned if the stack is empty or nothing left to undo. +//-------------------------------------------------------------------- +int +GetUndoOperationIndex(); + +//-------------------------------------------------------------------- +// Call Redo when the user chooses Edit->Redo from the menu +//-------------------------------------------------------------------- +void +Redo(); + +//-------------------------------------------------------------------- +// Use this to set the Enabled state of the Edit->Redo button +//-------------------------------------------------------------------- +bool +CanRedo(); + +//-------------------------------------------------------------------- +// Returns display string for the type of operation to be redone +// if Redo were to be called. +//-------------------------------------------------------------------- +std::string +GetRedoOperationName(); + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +GetUndoStack(std::vector& i_Stack); + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +float +GetMaximumMemoryUsage(); + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +float +GetCurrentMemoryUsage(); + +//-------------------------------------------------------------------- +// Add/RemoveInterest() - add or remove an interest for Undo +//-------------------------------------------------------------------- +void +AddInterest(undoUndoInterest* i_pInterest); +void +RemoveInterest(undoUndoInterest* i_pInterest); + +} // end of namespace diff --git a/renderlib/core/undo/undoUndoOperation.cpp b/renderlib/core/undo/undoUndoOperation.cpp new file mode 100644 index 00000000..ab0229bf --- /dev/null +++ b/renderlib/core/undo/undoUndoOperation.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** +** undoUndoOperation.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/undo/undoUndoOperation.hpp" + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +undoUndoOperation::undoUndoOperation() {} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +undoUndoOperation::~undoUndoOperation() {} + +//-------------------------------------------------------------------- +// Get Name for the operation +//-------------------------------------------------------------------- +std::string +undoUndoOperation::GetDisplayName() +{ + return ""; +} + +//-------------------------------------------------------------------- +// Get memory usage for this operation (in KB). This can be accurate +// or approximate. +//-------------------------------------------------------------------- +float +undoUndoOperation::GetMemoryUsage() +{ + return 0.0f; +} + +//-------------------------------------------------------------------- +// Commit is called on an operation when it is no longer +// possible for the user to undo this operation. The +// destructor will soon be called. This may happen if the +// history gets too long, or the file is saved. +//-------------------------------------------------------------------- +void +undoUndoOperation::Commit() +{ +} + +//-------------------------------------------------------------------- +// Destroy is called on an operation when it has been undone +// and it can no longer be redone. This may happen after +// a new operation is made when its current state is "undone". +// The destructor will soon be called. +//-------------------------------------------------------------------- +void +undoUndoOperation::Destroy() +{ +} \ No newline at end of file diff --git a/renderlib/core/undo/undoUndoOperation.hpp b/renderlib/core/undo/undoUndoOperation.hpp new file mode 100644 index 00000000..c2e8fe35 --- /dev/null +++ b/renderlib/core/undo/undoUndoOperation.hpp @@ -0,0 +1,69 @@ +/***************************************************************************** +** undoUndoOperation.hpp +** +** This is the abstract base class for operations that can +** be undone +** +** +** +\****************************************************************************/ +#ifdef UNDO_UNDOOPERATION_HPP +#error undoUndoOperation.hpp multiply included +#endif +#define UNDO_UNDOOPERATION_HPP + +#include + +//============================================================================ +//============================================================================ +class undoUndoOperation +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + undoUndoOperation(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual ~undoUndoOperation(); + + //-------------------------------------------------------------------- + // Get Name for the operation + //-------------------------------------------------------------------- + virtual std::string GetDisplayName(); + + //-------------------------------------------------------------------- + // Get memory usage for this operation (in KB). This can be accurate + // or approximate. + //-------------------------------------------------------------------- + virtual float GetMemoryUsage(); + + //-------------------------------------------------------------------- + // Undo is called on an operation when the user chooses + // Edit->Undo from the menu. + //-------------------------------------------------------------------- + virtual void Undo() = 0; + + //-------------------------------------------------------------------- + // Redo is called on an operation when the user chooses + // Edit->Redo from the menu and this operation is the next in + // line to be redone. + //-------------------------------------------------------------------- + virtual void Redo() = 0; + + //-------------------------------------------------------------------- + // Commit is called on an operation when it is no longer + // possible for the user to undo this operation. The + // destructor will soon be called. This may happen if the + // history gets too long, or the file is saved. + //-------------------------------------------------------------------- + virtual void Commit(); + + //-------------------------------------------------------------------- + // Destroy is called on an operation when it has been undone + // and it can no longer be redone. This may happen after + // a new operation is made when its current state is "undone". + // The destructor will soon be called. + //-------------------------------------------------------------------- + virtual void Destroy(); +}; From f73205f49309c511cd637f475758da01e0ad105c Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 18 Jun 2025 16:32:35 -0700 Subject: [PATCH 17/60] still missing prtyVec3 --- renderlib/AppearanceDataObject.cpp | 148 +++++++++++++-------------- renderlib/CameraDataObject.cpp | 69 +++++++------ renderlib/core/prty/prtyProperty.hpp | 4 +- 3 files changed, 111 insertions(+), 110 deletions(-) diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 1601b132..09fd7467 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -9,73 +9,73 @@ AppearanceDataObject::AppearanceDataObject(RenderSettings* renderSettings, Scene { updatePropsFromRenderSettings(); // hook up properties to update the underlying camera - RendererType.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - ShadingType.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - DensityScale.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - GradientFactor.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - StepSizeSecondaryRay.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - Interpolate.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - BackgroundColor.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - ShowBoundingBox.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - BoundingBoxColor.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - ShowScaleBar.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); + // RendererType.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // ShadingType.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // DensityScale.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // GradientFactor.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // StepSizeSecondaryRay.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // Interpolate.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // BackgroundColor.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // ShowBoundingBox.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // BoundingBoxColor.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // ShowScaleBar.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); } void AppearanceDataObject::updatePropsFromRenderSettings() { if (m_renderSettings) { - ShadingType.set(m_renderSettings->m_RenderSettings.m_ShadingType); - RendererType.set(m_renderSettings->m_rendererType); - DensityScale.set(m_renderSettings->m_RenderSettings.m_DensityScale); - GradientFactor.set(m_renderSettings->m_RenderSettings.m_GradientFactor); - StepSizePrimaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactor); - StepSizeSecondaryRay.set(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); - Interpolate.set(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); + ShadingType.SetValue(m_renderSettings->m_RenderSettings.m_ShadingType); + RendererType.SetValue(m_renderSettings->m_rendererType); + DensityScale.SetValue(m_renderSettings->m_RenderSettings.m_DensityScale); + GradientFactor.SetValue(m_renderSettings->m_RenderSettings.m_GradientFactor); + StepSizePrimaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactor); + StepSizeSecondaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); + Interpolate.SetValue(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); } if (m_scene) { - BackgroundColor.set(glm::vec3(m_scene->m_material.m_backgroundColor[0], - m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2])); - ShowBoundingBox.set(m_scene->m_material.m_showBoundingBox); - BoundingBoxColor.set(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], - m_scene->m_material.m_boundingBoxColor[1], - m_scene->m_material.m_boundingBoxColor[2])); - ShowScaleBar.set(m_scene->m_showScaleBar); + BackgroundColor.SetValue(glm::vec3(m_scene->m_material.m_backgroundColor[0], + m_scene->m_material.m_backgroundColor[1], + m_scene->m_material.m_backgroundColor[2])); + ShowBoundingBox.SetValue(m_scene->m_material.m_showBoundingBox); + BoundingBoxColor.SetValue(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], + m_scene->m_material.m_boundingBoxColor[1], + m_scene->m_material.m_boundingBoxColor[2])); + ShowScaleBar.SetValue(m_scene->m_showScaleBar); } } @@ -84,21 +84,21 @@ AppearanceDataObject::update() { // update low-level object from properties if (m_renderSettings) { - m_renderSettings->m_RenderSettings.m_ShadingType = ShadingType.get(); - m_renderSettings->m_rendererType = RendererType.get(); - m_renderSettings->m_RenderSettings.m_DensityScale = DensityScale.get(); - m_renderSettings->m_RenderSettings.m_GradientFactor = GradientFactor.get(); - m_renderSettings->m_RenderSettings.m_StepSizeFactor = StepSizePrimaryRay.get(); - m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = StepSizeSecondaryRay.get(); - m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = Interpolate.get(); - m_scene->m_material.m_backgroundColor[0] = BackgroundColor.get().x; - m_scene->m_material.m_backgroundColor[1] = BackgroundColor.get().y; - m_scene->m_material.m_backgroundColor[2] = BackgroundColor.get().z; - m_scene->m_material.m_showBoundingBox = ShowBoundingBox.get(); - m_scene->m_material.m_boundingBoxColor[0] = BoundingBoxColor.get().x; - m_scene->m_material.m_boundingBoxColor[1] = BoundingBoxColor.get().y; - m_scene->m_material.m_boundingBoxColor[2] = BoundingBoxColor.get().z; - m_scene->m_showScaleBar = ShowScaleBar.get(); + m_renderSettings->m_RenderSettings.m_ShadingType = ShadingType.GetValue(); + m_renderSettings->m_rendererType = RendererType.GetValue(); + m_renderSettings->m_RenderSettings.m_DensityScale = DensityScale.GetValue(); + m_renderSettings->m_RenderSettings.m_GradientFactor = GradientFactor.GetValue(); + m_renderSettings->m_RenderSettings.m_StepSizeFactor = StepSizePrimaryRay.GetValue(); + m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = StepSizeSecondaryRay.GetValue(); + m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = Interpolate.GetValue(); + m_scene->m_material.m_backgroundColor[0] = BackgroundColor.GetValue().x; + m_scene->m_material.m_backgroundColor[1] = BackgroundColor.GetValue().y; + m_scene->m_material.m_backgroundColor[2] = BackgroundColor.GetValue().z; + m_scene->m_material.m_showBoundingBox = ShowBoundingBox.GetValue(); + m_scene->m_material.m_boundingBoxColor[0] = BoundingBoxColor.GetValue().x; + m_scene->m_material.m_boundingBoxColor[1] = BoundingBoxColor.GetValue().y; + m_scene->m_material.m_boundingBoxColor[2] = BoundingBoxColor.GetValue().z; + m_scene->m_showScaleBar = ShowScaleBar.GetValue(); m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); diff --git a/renderlib/CameraDataObject.cpp b/renderlib/CameraDataObject.cpp index 55c206f6..beb42004 100644 --- a/renderlib/CameraDataObject.cpp +++ b/renderlib/CameraDataObject.cpp @@ -7,42 +7,43 @@ CameraDataObject::CameraDataObject(CCamera* camera) { updatePropsFromCamera(); // hook up properties to update the underlying camera - Exposure.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - ExposureIterations.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - NoiseReduction.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - ApertureSize.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - FieldOfView.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); - FocalDistance.addCallback([this](prtyProperty* p, bool fromUi) { - if (fromUi) - update(); - }); + // Exposure.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // ExposureIterations.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // NoiseReduction.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // ApertureSize.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // FieldOfView.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); + // FocalDistance.addCallback([this](prtyProperty* p, bool fromUi) { + // if (fromUi) + // update(); + // }); } void CameraDataObject::updatePropsFromCamera() { if (m_camera) { - Exposure.set(1.0f - m_camera->m_Film.m_Exposure); - ExposureIterations.set(m_camera->m_Film.m_ExposureIterations); + Exposure.SetValue(1.0f - m_camera->m_Film.m_Exposure); + ExposureIterations.SetValue(m_camera->m_Film.m_ExposureIterations); + // TODO this is not hooked up to the camera properly // NoiseReduction.set(m_camera->m_Film.m_NoiseReduction); - ApertureSize.set(m_camera->m_Aperture.m_Size); - FieldOfView.set(m_camera->m_FovV); - FocalDistance.set(m_camera->m_Focus.m_FocalDistance); + ApertureSize.SetValue(m_camera->m_Aperture.m_Size); + FieldOfView.SetValue(m_camera->m_FovV); + FocalDistance.SetValue(m_camera->m_Focus.m_FocalDistance); } } void @@ -50,17 +51,17 @@ CameraDataObject::update() { // update low-level camera object from properties if (m_camera) { - m_camera->m_Film.m_Exposure = 1.0f - Exposure.get(); - m_camera->m_Film.m_ExposureIterations = ExposureIterations.get(); + m_camera->m_Film.m_Exposure = 1.0f - Exposure.GetValue(); + m_camera->m_Film.m_ExposureIterations = ExposureIterations.GetValue(); // Aperture - m_camera->m_Aperture.m_Size = ApertureSize.get(); + m_camera->m_Aperture.m_Size = ApertureSize.GetValue(); // Projection - m_camera->m_FovV = FieldOfView.get(); + m_camera->m_FovV = FieldOfView.GetValue(); // Focus - m_camera->m_Focus.m_FocalDistance = FocalDistance.get(); + m_camera->m_Focus.m_FocalDistance = FocalDistance.GetValue(); m_camera->Update(); diff --git a/renderlib/core/prty/prtyProperty.hpp b/renderlib/core/prty/prtyProperty.hpp index e879ce0b..4577a628 100644 --- a/renderlib/core/prty/prtyProperty.hpp +++ b/renderlib/core/prty/prtyProperty.hpp @@ -46,7 +46,7 @@ ** prtyControlMgr::DeInitialize(); ** prtyCallbackMgr::DeInitialize(); ** -** Refer to TestTerawatt/Tools/prty application for an example. +** Refer to test/prty application for an example. ** ** ** @@ -152,7 +152,7 @@ class prtyProperty prtyProperty& operator=(const prtyProperty& i_Property); //-------------------------------------------------------------------- - // AddCallback using interface, used by unmanaged classes. + // AddCallback using interface. // // NOTE: This property will take ownership of the callback // pointer and will delete it in its destructor! It should be From d2868185f3f78fab97d9ca56c7680484a27cc39b Mon Sep 17 00:00:00 2001 From: dmt Date: Wed, 18 Jun 2025 18:27:01 -0700 Subject: [PATCH 18/60] renderlib compiles --- renderlib/AppearanceDataObject.cpp | 10 +- renderlib/AppearanceDataObject.hpp | 6 +- renderlib/Logging.h | 4 +- renderlib/core/prty/CMakeLists.txt | 10 + renderlib/core/prty/prtyColor.cpp | 105 +++++++++ renderlib/core/prty/prtyColor.hpp | 64 ++++++ .../core/prty/prtyColorRGBAEditUIInfo.cpp | 39 ++++ .../core/prty/prtyColorRGBAEditUIInfo.hpp | 41 ++++ .../core/prty/prtyPropertyUIInfoContainer.hpp | 1 + renderlib/core/prty/prtyRotation.cpp | 217 ++++++++++++++++++ renderlib/core/prty/prtyRotation.hpp | 108 +++++++++ renderlib/core/prty/prtyRotationUndo.cpp | 111 +++++++++ renderlib/core/prty/prtyRotationUndo.hpp | 77 +++++++ renderlib/core/prty/prtyUnits.cpp | 3 +- renderlib/core/prty/prtyVector3d.cpp | 157 +++++++++++++ renderlib/core/prty/prtyVector3d.hpp | 90 ++++++++ 16 files changed, 1032 insertions(+), 11 deletions(-) create mode 100644 renderlib/core/prty/prtyColor.cpp create mode 100644 renderlib/core/prty/prtyColor.hpp create mode 100644 renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp create mode 100644 renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp create mode 100644 renderlib/core/prty/prtyRotation.cpp create mode 100644 renderlib/core/prty/prtyRotation.hpp create mode 100644 renderlib/core/prty/prtyRotationUndo.cpp create mode 100644 renderlib/core/prty/prtyRotationUndo.hpp create mode 100644 renderlib/core/prty/prtyVector3d.cpp create mode 100644 renderlib/core/prty/prtyVector3d.hpp diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 09fd7467..810085a1 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -68,13 +68,15 @@ AppearanceDataObject::updatePropsFromRenderSettings() Interpolate.SetValue(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); } if (m_scene) { - BackgroundColor.SetValue(glm::vec3(m_scene->m_material.m_backgroundColor[0], + BackgroundColor.SetValue(glm::vec4(m_scene->m_material.m_backgroundColor[0], m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2])); + m_scene->m_material.m_backgroundColor[2], + 1.0f)); ShowBoundingBox.SetValue(m_scene->m_material.m_showBoundingBox); - BoundingBoxColor.SetValue(glm::vec3(m_scene->m_material.m_boundingBoxColor[0], + BoundingBoxColor.SetValue(glm::vec4(m_scene->m_material.m_boundingBoxColor[0], m_scene->m_material.m_boundingBoxColor[1], - m_scene->m_material.m_boundingBoxColor[2])); + m_scene->m_material.m_boundingBoxColor[2], + 1.0f)); ShowScaleBar.SetValue(m_scene->m_showScaleBar); } } diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index 74ee491d..f389517b 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -3,6 +3,8 @@ #include "core/prty/prtyInt8.hpp" #include "core/prty/prtyFloat.hpp" #include "core/prty/prtyBoolean.hpp" +#include "core/prty/prtyVector3d.hpp" +#include "core/prty/prtyColor.hpp" #include "AppScene.h" #include "RenderSettings.h" #include "glm.h" @@ -19,9 +21,9 @@ class AppearanceDataObject prtyFloat StepSizePrimaryRay{ "StepSizePrimaryRay", 1.0f }; prtyFloat StepSizeSecondaryRay{ "StepSizeSecondaryRay", 1.0f }; prtyBoolean Interpolate{ "Interpolate", false }; - prtyVec3 BackgroundColor{ "BackgroundColor", glm::vec3(0.0f, 0.0f, 0.0f) }; + prtyColor BackgroundColor{ "BackgroundColor", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f) }; prtyBoolean ShowBoundingBox{ "ShowBoundingBox", false }; - prtyVec3 BoundingBoxColor{ "BoundingBoxColor", glm::vec3(1.0f, 1.0f, 1.0f) }; + prtyColor BoundingBoxColor{ "BoundingBoxColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) }; prtyBoolean ShowScaleBar{ "ShowScaleBar", false }; RenderSettings* m_renderSettings; diff --git a/renderlib/Logging.h b/renderlib/Logging.h index 2100ce1b..0a11f4fb 100644 --- a/renderlib/Logging.h +++ b/renderlib/Logging.h @@ -69,9 +69,7 @@ Enable(bool enabled); #if defined(_DEBUG) || defined(DEBUG) || defined(_DEBUG) #define DBG_ASSERT(condition, message) \ do { \ - \ - if (!(condition)) \ - { \ + if (!(condition)) { \ LOG_ERROR << "Assertion failed: " << #condition << ", message: " << message; \ std::abort(); \ } \ diff --git a/renderlib/core/prty/CMakeLists.txt b/renderlib/core/prty/CMakeLists.txt index abbb170d..03edfb9b 100644 --- a/renderlib/core/prty/CMakeLists.txt +++ b/renderlib/core/prty/CMakeLists.txt @@ -1,6 +1,10 @@ target_sources(renderlib PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyColor.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyColor.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyColorRGBAEditUIInfo.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyColorRGBAEditUIInfo.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyEnum.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyEnum.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyFloat.cpp" @@ -27,10 +31,16 @@ target_sources(renderlib PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfo.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfoContainer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyPropertyUIInfoContainer.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyRotation.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyRotation.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyRotationUndo.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyRotationUndo.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyText.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyText.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyUndoTemplate.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyUndoTemplate.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyUnits.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyUnits.hpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyVector3d.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/prtyVector3d.hpp" ) \ No newline at end of file diff --git a/renderlib/core/prty/prtyColor.cpp b/renderlib/core/prty/prtyColor.cpp new file mode 100644 index 00000000..31e1b52a --- /dev/null +++ b/renderlib/core/prty/prtyColor.cpp @@ -0,0 +1,105 @@ +/****************************************************************************\ +** prtyColor.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyColor.hpp" + +// #include "core/ch/chChunkParserUtil.hpp" +// #include "core/ch/chReader.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyColor::prtyColor() + : prtyPropertyTemplate("Color", glm::vec4(0, 0, 0, 0)) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyColor::prtyColor(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, glm::vec4(0, 0, 0, 0)) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyColor::prtyColor(const std::string& i_Name, const glm::vec4& i_InitialValue) + : prtyPropertyTemplate(i_Name, i_InitialValue) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyColor::GetType() +{ + return "Color"; +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyColor& +prtyColor::operator=(const prtyColor& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + + SetValue(i_Property.GetValue()); + return *this; +} +prtyColor& +prtyColor::operator=(const glm::vec4& i_Value) +{ + SetValue(i_Value); + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyColor::operator==(const prtyColor& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyColor::operator!=(const prtyColor& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyColor::operator==(const glm::vec4& i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyColor::operator!=(const glm::vec4& i_Value) const +{ + return (m_Value != i_Value); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyColor::Read(chReader& io_Reader) +{ + // glm::vec4 temp; + // chChunkParserUtil::Read(io_Reader, temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyColor::Write(chWriter& io_Writer) const +{ + // chChunkParserUtil::Write(io_Writer, GetValue()); +} diff --git a/renderlib/core/prty/prtyColor.hpp b/renderlib/core/prty/prtyColor.hpp new file mode 100644 index 00000000..d54e5495 --- /dev/null +++ b/renderlib/core/prty/prtyColor.hpp @@ -0,0 +1,64 @@ +/****************************************************************************\ +** prtyColor.hpp +** +** Color property +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_COLOR_HPP +#error prtyColor.hpp multiply included +#endif +#define PRTY_COLOR_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +#include "glm.h" + +//============================================================================ +//============================================================================ +class prtyColor : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyColor(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyColor(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyColor(const std::string& i_Name, const glm::vec4& i_InitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyColor& operator=(const prtyColor& i_Property); + prtyColor& operator=(const glm::vec4& i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyColor& i_Property) const; + bool operator!=(const prtyColor& i_Property) const; + bool operator==(const glm::vec4& i_Value) const; + bool operator!=(const glm::vec4& i_Value) const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; +}; diff --git a/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp b/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp new file mode 100644 index 00000000..6079acd9 --- /dev/null +++ b/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp @@ -0,0 +1,39 @@ +/****************************************************************************\ +** prtyColorRGBAEditUIInfo.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyColorRGBAEditUIInfo.hpp" + +#include "core/prty/prtyProperty.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyColorRGBAEditUIInfo::prtyColorRGBAEditUIInfo(prtyProperty* i_pProperty) + : prtyPropertyUIInfo(i_pProperty) +{ + SetControlName("ColorRGBAEdit"); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyColorRGBAEditUIInfo::prtyColorRGBAEditUIInfo(prtyProperty* i_pProperty, + const std::string& i_Category, + const std::string& i_Description) + : prtyPropertyUIInfo(i_pProperty, i_Category, i_Description) +{ + SetControlName("ColorRGBAEdit"); +} + +//-------------------------------------------------------------------- +// Return pointer to new equivalent prtyPropertyUIInfo +//-------------------------------------------------------------------- +// virtual +prtyPropertyUIInfo* +prtyColorRGBAEditUIInfo::Clone() +{ + return new prtyColorRGBAEditUIInfo(this->GetProperty(0)); +} diff --git a/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp b/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp new file mode 100644 index 00000000..c9a3f089 --- /dev/null +++ b/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp @@ -0,0 +1,41 @@ +/****************************************************************************\ +** prtyColorRGBAEditUIInfo.hpp +** +** ColorRGBAEdit UI info +** +** +** +\****************************************************************************/ +#ifdef PRTY_COLORRGBAEDITUIINFO_HPP +#error prtyColorRGBAEditUIInfo.hpp multiply included +#endif +#define PRTY_COLORRGBAEDITUIINFO_HPP + +#ifndef PRTY_PROPERTYUIINFO_HPP +#include "core/prty/prtyPropertyUIInfo.hpp" +#endif + +#include + +//============================================================================ +//============================================================================ +class prtyProperty; + +//============================================================================ +//============================================================================ +class prtyColorRGBAEditUIInfo : public prtyPropertyUIInfo +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyColorRGBAEditUIInfo(prtyProperty* i_pProperty); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyColorRGBAEditUIInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description); + + //-------------------------------------------------------------------- + // Return pointer to new equivalent prtyPropertyUIInfo + //-------------------------------------------------------------------- + virtual prtyPropertyUIInfo* Clone(); +}; diff --git a/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp b/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp index 62b44c40..1c2e8ea0 100644 --- a/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp +++ b/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp @@ -17,6 +17,7 @@ #endif #include +#include //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyRotation.cpp b/renderlib/core/prty/prtyRotation.cpp new file mode 100644 index 00000000..17f9df3e --- /dev/null +++ b/renderlib/core/prty/prtyRotation.cpp @@ -0,0 +1,217 @@ +/****************************************************************************\ +** prtyRotation.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyRotation.hpp" + +#include "core/prty/prtyRotationUndo.hpp" + +// #include "core/ch/chChunkParserUtil.hpp" +// #include "core/ch/chReader.hpp" +// #include "core/ma/maConstants.hpp" +#include "core/undo/undoUndoMgr.hpp" + +namespace { +const float c_fEpsilon = 1.0e-6f; + +void +update_euler_from_quaternion(const glm::quat& i_Quaternion, glm::vec3& o_EulerAngles) +{ + o_EulerAngles = glm::eulerAngles(i_Quaternion) * 3.14159f / 180.f; +} + +void +update_quaternion_from_euler(const glm::vec3& i_EulerAngles, glm::quat& o_Quaternion) +{ + o_Quaternion = glm::quat(glm::radians(i_EulerAngles)); +} +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyRotation::prtyRotation() + : prtyProperty("Rotation") +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyRotation::prtyRotation(const std::string& i_Name) + : prtyProperty(i_Name) +{ +} + +//-------------------------------------------------------------------- +// Constructor with quaternion initial value +//-------------------------------------------------------------------- +prtyRotation::prtyRotation(const std::string& i_Name, const glm::quat& i_InitialValue) + : prtyProperty(i_Name) + , m_Quaternion(i_InitialValue) +{ + update_euler_from_quaternion(m_Quaternion, m_EulerAngles); +} + +//-------------------------------------------------------------------- +// Constructor with euler angle initial value +//-------------------------------------------------------------------- +prtyRotation::prtyRotation(const std::string& i_Name, float i_X, float i_Y, float i_Z) + : m_EulerAngles(i_X, i_Y, i_Z) +{ + update_quaternion_from_euler(m_EulerAngles, m_Quaternion); +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyRotation::GetType() +{ + return "Rotation"; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +const glm::quat& +prtyRotation::GetQuaternion() const +{ + return m_Quaternion; +} +const glm::quat& +prtyRotation::GetValue() const +{ + return m_Quaternion; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +void +prtyRotation::SetValue(const glm::quat& i_Rotation, bool i_bDirty) // UndoFlags i_Undoable) +{ + this->SetQuaternion(i_Rotation, i_bDirty); // i_Undoable); +} +void +prtyRotation::SetQuaternion(const glm::quat& i_Rotation, bool i_bDirty) // UndoFlags i_Undoable) +{ + if (i_Rotation != m_Quaternion) { + m_Quaternion = i_Rotation; + update_euler_from_quaternion(m_Quaternion, m_EulerAngles); + // NotifyCallbacksPropertyChanged(i_Undoable != eNoUndo); + NotifyCallbacksPropertyChanged(i_bDirty); + } +} + +//-------------------------------------------------------------------- +// Set rotation through 3 euler angles +//-------------------------------------------------------------------- +void +prtyRotation::SetEuler(float i_X, float i_Y, float i_Z, bool i_bDirty) // UndoFlags i_Undoable) +{ + glm::vec3 euler_angles(i_X, i_Y, i_Z); + if (euler_angles != m_EulerAngles) { + m_EulerAngles = euler_angles; + update_quaternion_from_euler(m_EulerAngles, m_Quaternion); + // NotifyCallbacksPropertyChanged(i_Undoable != eNoUndo); + NotifyCallbacksPropertyChanged(i_bDirty); + } +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyRotation::GetEuler(float& o_X, float& o_Y, float& o_Z) const +{ + o_X = m_EulerAngles.x; + o_Y = m_EulerAngles.y; + o_Z = m_EulerAngles.z; +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyRotation& +prtyRotation::operator=(const glm::quat& i_Value) +{ + SetQuaternion(i_Value); + return *this; +} +prtyRotation& +prtyRotation::operator=(const prtyRotation& i_Value) +{ + // copy base data + prtyProperty::operator=(i_Value); + + m_Quaternion = i_Value.m_Quaternion; + m_EulerAngles = i_Value.m_EulerAngles; + // SetMinimum(i_Value.GetMinimum()); + // SetMaximum(i_Value.GetMaximum()); + + // Notify callbacks, since we set the values directly instead of using + // SetValue()-like functions + const bool bDirty = false; + NotifyCallbacksPropertyChanged(bDirty); + + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyRotation::operator==(const glm::quat& i_Value) const +{ + return (m_Quaternion == i_Value); +} +bool +prtyRotation::operator==(const prtyRotation& i_Value) const +{ + // Should this compare quaternion or euler angles? + // return (m_Quaternion == i_Value.m_Quaternion); + + // comparison wihtin epsilon + return (glm::length2(m_EulerAngles - i_Value.m_EulerAngles) < c_fEpsilon); +} +bool +prtyRotation::operator!=(const prtyRotation& i_Value) const +{ + // Should this compare quaternion or euler angles? + // return !(m_Quaternion == i_Value.m_Quaternion); + + // comparison wihtin epsilon + return (glm::length2(m_EulerAngles - i_Value.m_EulerAngles) >= c_fEpsilon); +} + +//-------------------------------------------------------------------- +// Create an undo operation of the correct type for this +// property. A reference to this property should be passed in. +//-------------------------------------------------------------------- +// virtual +undoUndoOperation* +prtyRotation::CreateUndoOperation(std::shared_ptr i_pPropertyRef) +{ + return new prtyRotationUndo(i_pPropertyRef, m_EulerAngles); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyRotation::Read(chReader& io_Reader) +{ + // // We need to write euler angles, how to handle versions? + // glm::quat temp; + // chChunkParserUtil::Read(io_Reader, temp); + // SetQuaternion(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyRotation::Write(chWriter& io_Writer) const +{ + // chChunkParserUtil::Write(io_Writer, m_Quaternion); +} diff --git a/renderlib/core/prty/prtyRotation.hpp b/renderlib/core/prty/prtyRotation.hpp new file mode 100644 index 00000000..e172c5c1 --- /dev/null +++ b/renderlib/core/prty/prtyRotation.hpp @@ -0,0 +1,108 @@ +/****************************************************************************\ +** prtyRotation.hpp +** +** Rotation property +** +** +** +\****************************************************************************/ +#ifdef PRTY_ROTATION_HPP +#error prtyRotation.hpp multiply included +#endif +#define PRTY_ROTATION_HPP + +#ifndef PRTY_PROPERTY_HPP +#include "core/prty/prtyProperty.hpp" +#endif + +#include "glm.h" + +#include + +//============================================================================ +//============================================================================ +class prtyRotation : public prtyProperty +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyRotation(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyRotation(const std::string& i_Name); + + //-------------------------------------------------------------------- + // Constructor with quaternion initial value + //-------------------------------------------------------------------- + prtyRotation(const std::string& i_Name, const glm::quat& i_InitialValue); + + //-------------------------------------------------------------------- + // Constructor with euler angle initial value + //-------------------------------------------------------------------- + prtyRotation(const std::string& i_Name, float i_X, float i_Y, float i_Z); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + const glm::quat& GetQuaternion() const; + const glm::quat& GetValue() const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void SetQuaternion(const glm::quat& i_Rotation, bool i_bDirty = false); // UndoFlags i_Undoable = eNoUndo); + void SetValue(const glm::quat& i_Rotation, bool i_bDirty = false); // UndoFlags i_Undoable = eNoUndo); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // const glm::quat& GetMinimum() const; + // void SetMinimum(const glm::quat& i_Minimum); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // const glm::quat& GetMaximum() const; + // void SetMaximum(const glm::quat& i_Maximum); + + //-------------------------------------------------------------------- + // Set rotation through 3 euler angles (in radians) + //-------------------------------------------------------------------- + void SetEuler(float i_X, float i_Y, float i_Z, bool i_bDirty = false); // UndoFlags i_Undoable = eNoUndo); + void GetEuler(float& o_X, float& o_Y, float& o_Z) const; + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyRotation& operator=(const glm::quat& i_Value); + prtyRotation& operator=(const prtyRotation& i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const glm::quat& i_Value) const; + bool operator==(const prtyRotation& i_Value) const; + bool operator!=(const prtyRotation& i_Value) const; + + //-------------------------------------------------------------------- + // Create an undo operation of the correct type for this + // property. A reference to this property should be passed in. + //-------------------------------------------------------------------- + virtual undoUndoOperation* CreateUndoOperation(std::shared_ptr i_pPropertyRef); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; + +private: + glm::quat m_Quaternion; + glm::vec3 m_EulerAngles; + // glm::quat m_Minimum; + // glm::quat m_Maximum; +}; diff --git a/renderlib/core/prty/prtyRotationUndo.cpp b/renderlib/core/prty/prtyRotationUndo.cpp new file mode 100644 index 00000000..e8d9978d --- /dev/null +++ b/renderlib/core/prty/prtyRotationUndo.cpp @@ -0,0 +1,111 @@ +/***************************************************************************** +** prtyRotationUndo.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyRotationUndo.hpp" + +#include "core/prty/prtyRotation.hpp" + +//-------------------------------------------------------------------- +// constructor takes old to be restored if undone +//-------------------------------------------------------------------- +prtyRotationUndo::prtyRotationUndo(std::shared_ptr i_pPropertyRef, + const glm::vec3& i_EulerBackup) + : m_pPropertyRef(i_pPropertyRef) + , m_EulerBackup(i_EulerBackup) +{ +} + +//-------------------------------------------------------------------- +// Get Name for the operation +//-------------------------------------------------------------------- +std::string +prtyRotationUndo::GetDisplayName() +{ + prtyProperty* pProperty = (m_pPropertyRef) ? m_pPropertyRef->GetProperty() : NULL; + return ((pProperty) ? pProperty->GetPropertyName() : ""); +} + +//-------------------------------------------------------------------- +// Get memory usage for this operation (in KB). This can be +// accurate or approximate. +//-------------------------------------------------------------------- +float +prtyRotationUndo::GetMemoryUsage() +{ + return (undoUndoOperation::GetMemoryUsage() + sizeof(glm::vec3)); + // return (sizeof(bool) / 1000.0f); // convert to KB +} + +//-------------------------------------------------------------------- +// Undo is called on an operation when the user chooses +// Edit->Undo from the menu. +//-------------------------------------------------------------------- +void +prtyRotationUndo::Undo() +{ + prtyProperty* pPropertyBase = (m_pPropertyRef) ? m_pPropertyRef->GetProperty() : NULL; + if (pPropertyBase) { + prtyRotation* pProperty = dynamic_cast(pPropertyBase); + if (pProperty) { + float x = 0, y = 0, z = 0; + pProperty->GetEuler(x, y, z); + + const bool bFromUndo = true; + pProperty->SetEuler(m_EulerBackup.x, m_EulerBackup.y, m_EulerBackup.z, bFromUndo); + + m_EulerBackup = glm::vec3(x, y, z); // switch backup from undo to redo + } + } +} + +//-------------------------------------------------------------------- +// Redo is called on an operation when the user chooses +// Edit->Redo from the menu and this operation is the next in +// line to be redone. +//-------------------------------------------------------------------- +void +prtyRotationUndo::Redo() +{ + prtyProperty* pPropertyBase = (m_pPropertyRef) ? m_pPropertyRef->GetProperty() : NULL; + if (pPropertyBase) { + prtyRotation* pProperty = dynamic_cast(pPropertyBase); + if (pProperty) { + float x = 0, y = 0, z = 0; + pProperty->GetEuler(x, y, z); + + const bool bFromUndo = true; + pProperty->SetEuler(m_EulerBackup.x, m_EulerBackup.y, m_EulerBackup.z, bFromUndo); + + m_EulerBackup = glm::vec3(x, y, z); // switch backup from undo to redo + } + } +} + +//-------------------------------------------------------------------- +// Commit is called on an operation when it is no longer +// possible for the user to undo this operation. The +// destructor will soon be called. +//-------------------------------------------------------------------- +void +prtyRotationUndo::Commit() +{ + // nothing needed +} + +//-------------------------------------------------------------------- +// Destroy is called on an operation when it has been undone +// and it can no longer be redone. This may happen after the +// history gets long enough or a new operation is made when +// its current state is "undone". The destructor will soon be +// called. +//-------------------------------------------------------------------- +void +prtyRotationUndo::Destroy() +{ + // nothing needed +} diff --git a/renderlib/core/prty/prtyRotationUndo.hpp b/renderlib/core/prty/prtyRotationUndo.hpp new file mode 100644 index 00000000..6649717a --- /dev/null +++ b/renderlib/core/prty/prtyRotationUndo.hpp @@ -0,0 +1,77 @@ +/***************************************************************************** +** prtyRotationUndo.hpp +** +** store a state of Rotation for undo/redo +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_ROTATIONUNDO_HPP +#error prtyRotationUndo.hpp multiply included +#endif +#define PRTY_ROTATIONUNDO_HPP + +#ifndef UNDO_UNDOOPERATION_HPP +#include "core/undo/undoUndoOperation.hpp" +#endif +#ifndef PRTY_PROPERTYREFERENCE_HPP +#include "core/prty/prtyPropertyReference.hpp" +#endif + +#include "glm.h" + +//============================================================================ +//============================================================================ +class prtyRotationUndo : public undoUndoOperation +{ +public: + //-------------------------------------------------------------------- + // constructor takes old to be restored if undone + //-------------------------------------------------------------------- + prtyRotationUndo(std::shared_ptr i_pPropertyRef, const glm::vec3& i_EulerBackup); + + //-------------------------------------------------------------------- + // Get Name for the operation + //-------------------------------------------------------------------- + virtual std::string GetDisplayName(); + + //-------------------------------------------------------------------- + // Get memory usage for this operation (in KB). This can be + // accurate or approximate. + //-------------------------------------------------------------------- + virtual float GetMemoryUsage(); + + //-------------------------------------------------------------------- + // Undo is called on an operation when the user chooses + // Edit->Undo from the menu. + //-------------------------------------------------------------------- + virtual void Undo(); + + //-------------------------------------------------------------------- + // Redo is called on an operation when the user chooses + // Edit->Redo from the menu and this operation is the next in + // line to be redone. + //-------------------------------------------------------------------- + virtual void Redo(); + + //-------------------------------------------------------------------- + // Commit is called on an operation when it is no longer + // possible for the user to undo this operation. The + // destructor will soon be called. + //-------------------------------------------------------------------- + virtual void Commit(); + + //-------------------------------------------------------------------- + // Destroy is called on an operation when it has been undone + // and it can no longer be redone. This may happen after the + // history gets long enough or a new operation is made when + // its current state is "undone". The destructor will soon be + // called. + //-------------------------------------------------------------------- + virtual void Destroy(); + +private: + std::shared_ptr m_pPropertyRef; + glm::vec3 m_EulerBackup; +}; diff --git a/renderlib/core/prty/prtyUnits.cpp b/renderlib/core/prty/prtyUnits.cpp index d5e1100e..95854207 100644 --- a/renderlib/core/prty/prtyUnits.cpp +++ b/renderlib/core/prty/prtyUnits.cpp @@ -8,8 +8,7 @@ \****************************************************************************/ #include "core/prty/prtyUnits.hpp" -// library -// #include "core/dbg/dbgMsg.hpp" +#include "Logging.h" #include "core/env/envSTLHelpers.hpp" #include diff --git a/renderlib/core/prty/prtyVector3d.cpp b/renderlib/core/prty/prtyVector3d.cpp new file mode 100644 index 00000000..45ffb9d7 --- /dev/null +++ b/renderlib/core/prty/prtyVector3d.cpp @@ -0,0 +1,157 @@ +/****************************************************************************\ +** prtyVector3d.cpp +** +** see .hpp +** +** +** +\****************************************************************************/ +#include "core/prty/prtyVector3d.hpp" +#include "core/prty/prtyUnits.hpp" + +// #include "core/ch/chChunkParserUtil.hpp" +// #include "core/ch/chReader.hpp" + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyVector3d::prtyVector3d() + : prtyPropertyTemplate("Point3d", glm::vec3(0, 0, 0)) + , m_bUseUnits(false) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyVector3d::prtyVector3d(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, glm::vec3(0, 0, 0)) + , m_bUseUnits(false) +{ +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +prtyVector3d::prtyVector3d(const std::string& i_Name, const glm::vec3& i_InitialValue) + : prtyPropertyTemplate(i_Name, i_InitialValue) + , m_bUseUnits(false) +{ +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +const char* +prtyVector3d::GetType() +{ + return "Vector3d"; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyVector3d::Set(const float i_ValueX, + const float i_ValueY, + const float i_ValueZ, + bool i_bDirty) // UndoFlags i_Undoable ) +{ + glm::vec3 newvec(i_ValueX, i_ValueY, i_ValueZ); + SetValue(newvec, i_bDirty); // i_Undoable); +} + +//-------------------------------------------------------------------- +// operators +//-------------------------------------------------------------------- +prtyVector3d& +prtyVector3d::operator=(const glm::vec3& i_Value) +{ + SetValue(i_Value); + return *this; +} +prtyVector3d& +prtyVector3d::operator=(const prtyVector3d& i_Property) +{ + // copy base data + prtyProperty::operator=(i_Property); + SetValue(i_Property.GetValue()); + m_bUseUnits = i_Property.m_bUseUnits; + return *this; +} + +//-------------------------------------------------------------------- +// comparison operators +//-------------------------------------------------------------------- +bool +prtyVector3d::operator==(const prtyVector3d& i_Property) const +{ + return (m_Value == i_Property.GetValue()); +} +bool +prtyVector3d::operator!=(const prtyVector3d& i_Property) const +{ + return (m_Value != i_Property.GetValue()); +} +bool +prtyVector3d::operator==(const glm::vec3& i_Value) const +{ + return (m_Value == i_Value); +} +bool +prtyVector3d::operator!=(const glm::vec3& i_Value) const +{ + return (m_Value != i_Value); +} + +//-------------------------------------------------------------------- +// Set whether this property should consider the current units +// when displaying its value in the user interface. +//-------------------------------------------------------------------- +bool +prtyVector3d::GetUseUnits() const +{ + return m_bUseUnits; +} +void +prtyVector3d::SetUseUnits(bool i_bUseUnits) +{ + m_bUseUnits = true; +} + +//-------------------------------------------------------------------- +// Get and Set value in the current display units. +// Converts to internal units and then calls Get/SetValue() +//-------------------------------------------------------------------- +glm::vec3 +prtyVector3d::GetScaledValue() const +{ + if (this->GetUseUnits()) + return (this->GetValue() / prtyUnits::GetUnitScaling()); + else + return this->GetValue(); +} +void +prtyVector3d::SetScaledValue(const glm::vec3& i_Value, bool i_bDirty) // UndoFlags i_Undoable) +{ + if (this->GetUseUnits()) + this->SetValue(i_Value * prtyUnits::GetUnitScaling(), i_bDirty); // i_Undoable); + else + return this->SetValue(i_Value, i_bDirty); // i_Undoable); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyVector3d::Read(chReader& io_Reader) +{ + // glm::vec3 temp; + // chChunkParserUtil::Read(io_Reader, temp); + // SetValue(temp); +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// virtual +void +prtyVector3d::Write(chWriter& io_Writer) const +{ + // chChunkParserUtil::Write(io_Writer, GetValue()); +} diff --git a/renderlib/core/prty/prtyVector3d.hpp b/renderlib/core/prty/prtyVector3d.hpp new file mode 100644 index 00000000..e703d0b8 --- /dev/null +++ b/renderlib/core/prty/prtyVector3d.hpp @@ -0,0 +1,90 @@ +/****************************************************************************\ +** prtyVector3d.hpp +** +** Vector3d property +** +** +** +\****************************************************************************/ +#pragma once +#ifdef PRTY_VECTOR3D_HPP +#error prtyVector3d.hpp multiply included +#endif +#define PRTY_VECTOR3D_HPP + +#ifndef PRTY_PROPERTYTEMPLATE_HPP +#include "core/prty/prtyPropertyTemplate.hpp" +#endif + +#include "glm.h" + +//============================================================================ +//============================================================================ +class prtyVector3d : public prtyPropertyTemplate +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyVector3d(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyVector3d(const std::string& i_Name); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + prtyVector3d(const std::string& i_Name, const glm::vec3& i_InitialValue); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType(); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void Set(const float i_ValueX, + const float i_ValueY, + const float i_ValueZ, + bool i_bDirty = false); // UndoFlags i_Undoable = eNoUndo ); + + //-------------------------------------------------------------------- + // Set whether this property should consider the current units + // when displaying its value in the user interface. + // prtyVector3d has a default value of false. + //-------------------------------------------------------------------- + bool GetUseUnits() const; + void SetUseUnits(bool i_bUseUnits); + + //-------------------------------------------------------------------- + // Get and Set value in the current display units. + // Converts to internal units and then calls Get/SetValue(). + // If this property does not use units, the unscaled value is used. + //-------------------------------------------------------------------- + glm::vec3 GetScaledValue() const; + void SetScaledValue(const glm::vec3& i_Value, bool i_bDirty = false); // UndoFlags i_Undoable = eNoUndo); + + //-------------------------------------------------------------------- + // operators + //-------------------------------------------------------------------- + prtyVector3d& operator=(const glm::vec3& i_Value); + prtyVector3d& operator=(const prtyVector3d& i_Value); + + //-------------------------------------------------------------------- + // comparison operators + //-------------------------------------------------------------------- + bool operator==(const prtyVector3d& i_Property) const; + bool operator!=(const prtyVector3d& i_Property) const; + bool operator==(const glm::vec3& i_Value) const; + bool operator!=(const glm::vec3& i_Value) const; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Read(chReader& io_Reader); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual void Write(chWriter& io_Writer) const; + +private: + bool m_bUseUnits; +}; From f97f2ededb202273b439184182292ffc61dff9ac Mon Sep 17 00:00:00 2001 From: dmt Date: Wed, 18 Jun 2025 18:54:24 -0700 Subject: [PATCH 19/60] test working --- agave_app/AppearanceWidget.h | 2 +- agave_app/CameraWidget.h | 2 +- renderlib/core/prty/prtyBoolean.hpp | 1 + renderlib/core/prty/prtyFloat.hpp | 1 + renderlib/core/prty/prtyPropertyCallback.hpp | 20 ++++- renderlib/core/prty/prtyPropertyTemplate.hpp | 1 + test/test_prty.cpp | 89 +++++++++++++------- 7 files changed, 81 insertions(+), 35 deletions(-) diff --git a/agave_app/AppearanceWidget.h b/agave_app/AppearanceWidget.h index e9e43361..4ef78ab5 100644 --- a/agave_app/AppearanceWidget.h +++ b/agave_app/AppearanceWidget.h @@ -2,7 +2,7 @@ #include "qtControls/Controls.h" -#include "renderlib/core/prty/prtyProperty.h" +// #include "renderlib/core/prty/prtyProperty.h" #include "renderlib/AppearanceDataObject.hpp" #include "renderlib/Logging.h" diff --git a/agave_app/CameraWidget.h b/agave_app/CameraWidget.h index 085a1247..c372b7ab 100644 --- a/agave_app/CameraWidget.h +++ b/agave_app/CameraWidget.h @@ -3,7 +3,7 @@ #include "Camera.h" #include "qtControls/Controls.h" -#include "renderlib/core/prty/prtyProperty.h" +// #include "renderlib/core/prty/prtyProperty.h" #include "renderlib/CameraDataObject.hpp" #include "renderlib/Logging.h" diff --git a/renderlib/core/prty/prtyBoolean.hpp b/renderlib/core/prty/prtyBoolean.hpp index 92adebd2..af38d4bd 100644 --- a/renderlib/core/prty/prtyBoolean.hpp +++ b/renderlib/core/prty/prtyBoolean.hpp @@ -6,6 +6,7 @@ ** ** \****************************************************************************/ +#pragma once #ifdef PRTY_BOOLEAN_HPP #error prtyBoolean.hpp multiply included #endif diff --git a/renderlib/core/prty/prtyFloat.hpp b/renderlib/core/prty/prtyFloat.hpp index 58925e59..ca494005 100644 --- a/renderlib/core/prty/prtyFloat.hpp +++ b/renderlib/core/prty/prtyFloat.hpp @@ -6,6 +6,7 @@ ** ** \****************************************************************************/ +#pragma once #ifdef PRTY_FLOAT_HPP #error prtyFloat.hpp multiply included #endif diff --git a/renderlib/core/prty/prtyPropertyCallback.hpp b/renderlib/core/prty/prtyPropertyCallback.hpp index 2b8bf952..3ddd849f 100644 --- a/renderlib/core/prty/prtyPropertyCallback.hpp +++ b/renderlib/core/prty/prtyPropertyCallback.hpp @@ -14,6 +14,8 @@ #endif #define PRTY_PROPERTYCALLBACK_HPP +#include + //============================================================================ // forward references //============================================================================ @@ -27,7 +29,7 @@ class prtyPropertyCallback public: //-------------------------------------------------------------------- //-------------------------------------------------------------------- - virtual ~prtyPropertyCallback() = 0; + virtual ~prtyPropertyCallback() {} //-------------------------------------------------------------------- // PropertyChanged is called when a property's value is changed @@ -58,3 +60,19 @@ struct prtyCallbackWrapper : public prtyPropertyCallback (obj_ptr->*func_ptr)(i_pProperty, i_bWithUndo); } }; + +class prtyCallbackLambda : public prtyPropertyCallback +{ + std::function m_Callback; + +public: + prtyCallbackLambda(std::function i_Callback) + : m_Callback(i_Callback) + { + } + + virtual void PropertyChanged(prtyProperty* i_pProperty, bool i_bWithUndo) override + { + m_Callback(i_pProperty, i_bWithUndo); + } +}; \ No newline at end of file diff --git a/renderlib/core/prty/prtyPropertyTemplate.hpp b/renderlib/core/prty/prtyPropertyTemplate.hpp index fc0e8b62..2f1ee775 100644 --- a/renderlib/core/prty/prtyPropertyTemplate.hpp +++ b/renderlib/core/prty/prtyPropertyTemplate.hpp @@ -6,6 +6,7 @@ ** ** \****************************************************************************/ +#pragma once #ifdef PRTY_PROPERTYTEMPLATE_HPP #error prtyPropertyTemplate.hpp multiply included #endif diff --git a/test/test_prty.cpp b/test/test_prty.cpp index e3349207..6834a057 100644 --- a/test/test_prty.cpp +++ b/test/test_prty.cpp @@ -2,66 +2,70 @@ #include -#include "core/prty/prtyProperty.h" +#include "core/prty/prtyProperty.hpp" +#include "core/prty/prtyInt8.hpp" +#include "core/prty/prtyText.hpp" +#include "core/prty/prtyPropertyTemplate.hpp" #include #include TEST_CASE("prtyProperty", "[prtyProperty]") { - prtyProperty p("int"); + prtyInt8 p("int"); // no init value // REQUIRE(p.get() == 0); - p.set(42); - REQUIRE(p.get() == 42); + p.SetValue(42); + REQUIRE(p.GetValue() == 42); - prtyProperty p2("string", "hello"); - REQUIRE(p2.get() == "hello"); - p2.set("world"); - REQUIRE(p2.get() == "world"); + prtyText p2("string", "hello"); + REQUIRE(p2.GetValue() == "hello"); + p2.SetValue("world"); + REQUIRE(p2.GetValue() == "world"); } // test prtyProperty callbacks TEST_CASE("prtyProperty callbacks", "[prtyProperty]") { - prtyProperty p("int"); + + prtyInt8 p("int"); int count = 0; - p.addCallback([&count](prtyProperty*, bool) { count++; }); + + p.AddCallback(new prtyCallbackLambda([&count](prtyProperty*, bool) { count++; })); REQUIRE(count == 0); - p.set(42); + p.SetValue(42); + REQUIRE(count == 1); + p.SetValue(42); REQUIRE(count == 1); - // callback fires even if value doesn't change - p.set(42); + p.SetValue(43); REQUIRE(count == 2); - p.set(43); - REQUIRE(count == 3); } // test behavior of copying a prtyProperty with callbacks TEST_CASE("prtyProperty copy", "[prtyProperty]") { - prtyProperty p("int"); + prtyInt8 p("int"); int count = 0; - p.addCallback([&count](prtyProperty*, bool) { count++; }); + p.AddCallback(new prtyCallbackLambda([&count](prtyProperty*, bool) { count++; })); REQUIRE(count == 0); - p.set(42); + p.SetValue(42); REQUIRE(count == 1); - prtyProperty p2 = p; - REQUIRE(p2.get() == p.get()); - REQUIRE(p2.getName() == p.getName()); + prtyInt8 p2 = p; + REQUIRE(p2.GetValue() == p.GetValue()); + REQUIRE(p2.GetPropertyName() == p.GetPropertyName()); // callback not copied REQUIRE(count == 1); - p2.set(43); + p2.SetValue(43); REQUIRE(count == 1); - p.set(44); + p.SetValue(44); REQUIRE(count == 2); - REQUIRE(p2.get() == 43); - REQUIRE(p.get() == 44); + REQUIRE(p2.GetValue() == 43); + REQUIRE(p.GetValue() == 44); } // test a prtyProperty with a struct type @@ -76,17 +80,38 @@ struct Foo os << "{ " << f.x << ", " << f.y << " }"; return os; } + + friend bool operator==(const Foo& lhs, const Foo& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } + friend bool operator!=(const Foo& lhs, const Foo& rhs) { return !(lhs == rhs); } }; TEST_CASE("prtyProperty struct", "[prtyProperty]") { - prtyProperty p("foo"); + class prtyFoo : public prtyPropertyTemplate + { + public: + prtyFoo(const std::string& i_Name) + : prtyPropertyTemplate(i_Name, { 0, 0 }) + { + } + + virtual const char* GetType() override { return "Foo"; } + virtual void Read(chReader& io_Reader) override + { + // Implement reading from a reader if needed + } + virtual void Write(chWriter& io_Writer) const override + { + // Implement writing to a writer if needed + } + }; + prtyFoo p("foo"); Foo f = { 1, 2 }; - p.set(f); - REQUIRE(p.get().x == 1); - REQUIRE(p.get().y == 2); + p.SetValue(f); + REQUIRE(p.GetValue().x == 1); + REQUIRE(p.GetValue().y == 2); Foo f2 = { 3, 4 }; - p.set(f2); - REQUIRE(p.get().x == 3); - REQUIRE(p.get().y == 4); + p.SetValue(f2); + REQUIRE(p.GetValue().x == 3); + REQUIRE(p.GetValue().y == 4); } From 12e5a7089b6154ab55b2bbfa8173739d1b47f12b Mon Sep 17 00:00:00 2001 From: dmt Date: Thu, 19 Jun 2025 07:06:29 -0700 Subject: [PATCH 20/60] fixing compile errors --- agave_app/agaveGui.cpp | 8 +-- agave_app/qtControls/controlFactory.cpp | 70 ++++++++++++++----------- agave_app/qtControls/controlFactory.h | 24 +++++---- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index c3994e84..e73edd84 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -1326,10 +1326,10 @@ agaveGui::appToViewerState() : Serialize::Projection_PID::ORTHOGRAPHIC; v.camera.orthoScale = m_glView->getCamera().m_OrthoScale; CameraDataObject* cdo = m_glView->getCameraDataObject(); - v.camera.fovY = cdo->FieldOfView.get(); - v.camera.exposure = cdo->Exposure.get(); - v.camera.aperture = cdo->ApertureSize.get(); - v.camera.focalDistance = cdo->FocalDistance.get(); + v.camera.fovY = cdo->FieldOfView.GetValue(); + v.camera.exposure = cdo->Exposure.GetValue(); + v.camera.aperture = cdo->ApertureSize.GetValue(); + v.camera.focalDistance = cdo->FocalDistance.GetValue(); v.density = m_renderSettings.m_RenderSettings.m_DensityScale; v.interpolate = m_renderSettings.m_RenderSettings.m_InterpolatedVolumeSampling; diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index 567af507..11da9a3d 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -3,7 +3,7 @@ #include "Controls.h" QNumericSlider* -create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr> prop) +create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop) { QNumericSlider* slider = new QNumericSlider(); slider->setStatusTip(QString::fromStdString(info->statusTip)); @@ -14,15 +14,16 @@ create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr slider->setNumTickMarks(info->numTickMarks); slider->setSuffix(QString::fromStdString(info->suffix)); - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + slider->setValue(prop->GetValue(), true); + QObject::connect( + slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } QNumericSlider* -create(const IntSliderSpinnerUiInfo* info, std::shared_ptr> prop) +create(const IntSliderSpinnerUiInfo* info, std::shared_ptr prop) { QNumericSlider* slider = new QNumericSlider(); slider->setStatusTip(QString::fromStdString(info->statusTip)); @@ -32,28 +33,29 @@ create(const IntSliderSpinnerUiInfo* info, std::shared_ptr> pr slider->setNumTickMarks(info->numTickMarks); slider->setSuffix(QString::fromStdString(info->suffix)); - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + slider->setValue(prop->GetValue(), true); + QObject::connect( + slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } QCheckBox* -create(const CheckBoxUiInfo* info, std::shared_ptr> prop) +create(const CheckBoxUiInfo* info, std::shared_ptr prop) { QCheckBox* checkBox = new QCheckBox(); checkBox->setStatusTip(QString::fromStdString(info->statusTip)); checkBox->setToolTip(QString::fromStdString(info->toolTip)); // checkBox->setText(QString::fromStdString(info->formLabel)); - checkBox->setCheckState(prop->get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { - prop->set(state == Qt::CheckState::Checked, true); + prop->SetValue(state == Qt::CheckState::Checked, true); }); return checkBox; } QComboBox* -create(const ComboBoxUiInfo* info, std::shared_ptr> prop) +create(const ComboBoxUiInfo* info, std::shared_ptr prop) { QComboBox* comboBox = new QComboBox(); comboBox->setStatusTip(QString::fromStdString(info->statusTip)); @@ -61,13 +63,14 @@ create(const ComboBoxUiInfo* info, std::shared_ptr> prop) for (const auto& item : info->items) { comboBox->addItem(QString::fromStdString(item)); } - comboBox->setCurrentIndex(prop->get()); - QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); + comboBox->setCurrentIndex(prop->GetValue()); + QObject::connect( + comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->SetValue(index, true); }); return comboBox; } QNumericSlider* -addRow(const FloatSliderSpinnerUiInfo& info, prtyProperty* prop) +addRow(const FloatSliderSpinnerUiInfo& info, prtyFloat* prop) { QNumericSlider* slider = new QNumericSlider(); slider->setStatusTip(QString::fromStdString(info.statusTip)); @@ -78,15 +81,16 @@ addRow(const FloatSliderSpinnerUiInfo& info, prtyProperty* prop) slider->setNumTickMarks(info.numTickMarks); slider->setSuffix(QString::fromStdString(info.suffix)); - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + slider->setValue(prop->GetValue(), true); + QObject::connect( + slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } QNumericSlider* -addRow(const IntSliderSpinnerUiInfo& info, prtyProperty* prop) +addRow(const IntSliderSpinnerUiInfo& info, prtyInt32* prop) { QNumericSlider* slider = new QNumericSlider(); slider->setStatusTip(QString::fromStdString(info.statusTip)); @@ -96,16 +100,17 @@ addRow(const IntSliderSpinnerUiInfo& info, prtyProperty* prop) slider->setNumTickMarks(info.numTickMarks); slider->setSuffix(QString::fromStdString(info.suffix)); - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); + slider->setValue(prop->GetValue(), true); + QObject::connect( + slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); + // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } QComboBox* -addRow(const ComboBoxUiInfo& info, prtyProperty* prop) +addRow(const ComboBoxUiInfo& info, prtyInt8* prop) { QComboBox* comboBox = new QComboBox(); comboBox->setStatusTip(QString::fromStdString(info.statusTip)); @@ -113,37 +118,38 @@ addRow(const ComboBoxUiInfo& info, prtyProperty* prop) for (const auto& item : info.items) { comboBox->addItem(QString::fromStdString(item)); } - comboBox->setCurrentIndex(prop->get()); - QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); + comboBox->setCurrentIndex(prop->GetValue()); + QObject::connect( + comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->SetValue(index, true); }); return comboBox; } QCheckBox* -addRow(const CheckBoxUiInfo& info, prtyProperty* prop) +addRow(const CheckBoxUiInfo& info, prtyBoolean* prop) { QCheckBox* checkBox = new QCheckBox(); checkBox->setStatusTip(QString::fromStdString(info.statusTip)); checkBox->setToolTip(QString::fromStdString(info.toolTip)); // checkBox->setText(QString::fromStdString(info.formLabel)); - checkBox->setCheckState(prop->get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { - prop->set(state == Qt::CheckState::Checked, true); + prop->SetValue(state == Qt::CheckState::Checked, true); }); return checkBox; } QColorPushButton* -addRow(const ColorPickerUiInfo& info, prtyProperty* prop) +addRow(const ColorPickerUiInfo& info, prtyColor* prop) { QColorPushButton* colorButton = new QColorPushButton(); colorButton->setStatusTip(QString::fromStdString(info.statusTip)); colorButton->setToolTip(QString::fromStdString(info.toolTip)); - QColor c = QColor::fromRgbF(prop->get().r, prop->get().g, prop->get().b); + QColor c = QColor::fromRgbF(prop->GetValue().r, prop->GetValue().g, prop->GetValue().b); colorButton->SetColor(c, true); QObject::connect(colorButton, &QColorPushButton::currentColorChanged, [colorButton, prop](const QColor& c) { // Convert QColor to glm::vec3 - glm::vec3 color(c.redF(), c.greenF(), c.blueF()); - prop->set(color, true); + glm::vec4 color(c.redF(), c.greenF(), c.blueF(), 1.0f); + prop->SetValue(color, true); }); return colorButton; } \ No newline at end of file diff --git a/agave_app/qtControls/controlFactory.h b/agave_app/qtControls/controlFactory.h index ab1cceb2..1d0f4a7d 100644 --- a/agave_app/qtControls/controlFactory.h +++ b/agave_app/qtControls/controlFactory.h @@ -1,7 +1,11 @@ #pragma once #include "renderlib/uiInfo.hpp" -#include "renderlib/core/prty/prtyProperty.h" +#include "renderlib/core/prty/prtyColor.hpp" +#include "renderlib/core/prty/prtyBoolean.hpp" +#include "renderlib/core/prty/prtyFloat.hpp" +#include "renderlib/core/prty/prtyInt32.hpp" +#include "renderlib/core/prty/prtyInt8.hpp" #include "renderlib/glm.h" #include @@ -12,28 +16,28 @@ class QComboBox; class QColorPushButton; QNumericSlider* -create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr> prop); +create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop); QNumericSlider* -create(const IntSliderSpinnerUiInfo* info, std::shared_ptr> prop); +create(const IntSliderSpinnerUiInfo* info, std::shared_ptr prop); QCheckBox* -create(const CheckBoxUiInfo* info, std::shared_ptr> prop); +create(const CheckBoxUiInfo* info, std::shared_ptr prop); QComboBox* -create(const ComboBoxUiInfo* info, std::shared_ptr> prop); +create(const ComboBoxUiInfo* info, std::shared_ptr prop); QNumericSlider* -addRow(const FloatSliderSpinnerUiInfo& info, prtyProperty* prop); +addRow(const FloatSliderSpinnerUiInfo& info, prtyFloat* prop); QNumericSlider* -addRow(const IntSliderSpinnerUiInfo& info, prtyProperty* prop); +addRow(const IntSliderSpinnerUiInfo& info, prtyInt32* prop); QComboBox* -addRow(const ComboBoxUiInfo& info, prtyProperty* prop); +addRow(const ComboBoxUiInfo& info, prtyInt8* prop); QCheckBox* -addRow(const CheckBoxUiInfo& info, prtyProperty* prop); +addRow(const CheckBoxUiInfo& info, prtyBoolean* prop); QColorPushButton* -addRow(const ColorPickerUiInfo& info, prtyProperty* prop); +addRow(const ColorPickerUiInfo& info, prtyColor* prop); From 2612908e4fa0ce1b7025b0a78ac596525133bb9d Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Fri, 20 Jun 2025 22:06:10 -0700 Subject: [PATCH 21/60] bring back agProperty --- renderlib/CameraDataObject.cpp | 2 +- renderlib/core/prty/CMakeLists.txt | 3 + renderlib/core/prty/agProperty.cpp | 159 +++++++++++++++ renderlib/core/prty/agProperty.h | 223 +++++++++++++++++++++ renderlib/core/prty/agPropertyCallback.hpp | 74 +++++++ renderlib/core/prty/prtyProperty.cpp | 2 +- 6 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 renderlib/core/prty/agProperty.cpp create mode 100644 renderlib/core/prty/agProperty.h create mode 100644 renderlib/core/prty/agPropertyCallback.hpp diff --git a/renderlib/CameraDataObject.cpp b/renderlib/CameraDataObject.cpp index beb42004..01d77e0d 100644 --- a/renderlib/CameraDataObject.cpp +++ b/renderlib/CameraDataObject.cpp @@ -40,7 +40,7 @@ CameraDataObject::updatePropsFromCamera() Exposure.SetValue(1.0f - m_camera->m_Film.m_Exposure); ExposureIterations.SetValue(m_camera->m_Film.m_ExposureIterations); // TODO this is not hooked up to the camera properly - // NoiseReduction.set(m_camera->m_Film.m_NoiseReduction); + // NoiseReduction.SetValue(m_camera->m_Film.m_NoiseReduction); ApertureSize.SetValue(m_camera->m_Aperture.m_Size); FieldOfView.SetValue(m_camera->m_FovV); FocalDistance.SetValue(m_camera->m_Focus.m_FocalDistance); diff --git a/renderlib/core/prty/CMakeLists.txt b/renderlib/core/prty/CMakeLists.txt index 03edfb9b..d220f976 100644 --- a/renderlib/core/prty/CMakeLists.txt +++ b/renderlib/core/prty/CMakeLists.txt @@ -1,4 +1,7 @@ target_sources(renderlib PRIVATE +"${CMAKE_CURRENT_SOURCE_DIR}/agProperty.h" +"${CMAKE_CURRENT_SOURCE_DIR}/agProperty.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/agPropertyCallback.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyColor.cpp" diff --git a/renderlib/core/prty/agProperty.cpp b/renderlib/core/prty/agProperty.cpp new file mode 100644 index 00000000..bbf240c9 --- /dev/null +++ b/renderlib/core/prty/agProperty.cpp @@ -0,0 +1,159 @@ +#include "core/prty/agProperty.h" + +// #include "core/dbg/dbgMsg.hpp" +#include "core/env/envSTLHelpers.hpp" + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +const std::string& +agBaseProperty::GetPropertyName() const +{ + return name; +} + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +agBaseProperty::SetPropertyName(const std::string& i_Name) +{ + name = i_Name; +} + +//-------------------------------------------------------------------- +// Animatable - can this property be animated? +//-------------------------------------------------------------------- +bool +agBaseProperty::IsAnimatable() const +{ + return m_Flags.m_bAnimatable; +} +void +agBaseProperty::SetAnimatable(bool i_bVal) +{ + m_Flags.m_bAnimatable = i_bVal; +} + +//-------------------------------------------------------------------- +// Scripted - Is this property currently being animated? +//-------------------------------------------------------------------- +bool +agBaseProperty::IsScripted() const +{ + return m_Flags.m_bScripted; +} +void +agBaseProperty::SetScripted(bool i_bVal) +{ + m_Flags.m_bScripted = i_bVal; +} + +//-------------------------------------------------------------------- +// ValueVariation - Does the current value vary from the scripted value? +//-------------------------------------------------------------------- +bool +agBaseProperty::HasValueVariation() const +{ + return m_Flags.m_bValueVariation; +} +void +agBaseProperty::SetValueVariation(bool i_bVal) +{ + m_Flags.m_bValueVariation = i_bVal; +} + +//-------------------------------------------------------------------- +// assignment operator - does not copy the callbacks +//-------------------------------------------------------------------- +agBaseProperty& +agBaseProperty::operator=(const agBaseProperty& i_Property) +{ + // m_Type = i_Property.m_Type; + name = i_Property.name; + + // flags should not be copied + // m_Flags = i_Property.m_Flags; + + return *this; +} + +//-------------------------------------------------------------------- +// AddCallback using interface. +// +// NOTE: This property will take ownership of the callback +// pointer and will delete it in its destructor! It should be +// created on the heap and probably should use the +// prtyCallbackWrapper template. +//-------------------------------------------------------------------- +void +agBaseProperty::AddCallback(agPropertyCallback* i_pCallback) +{ + if (i_pCallback != NULL) + m_CallbackObjects.push_back(std::shared_ptr(i_pCallback)); +} + +//-------------------------------------------------------------------- +// AddCallback shared pointer variation for when you want to +// keep a copy of the callback also. +//-------------------------------------------------------------------- +void +agBaseProperty::AddCallback(std::shared_ptr i_pCallback) +{ + if (i_pCallback.get() != NULL) + m_CallbackObjects.push_back(i_pCallback); +} + +//-------------------------------------------------------------------- +// RemoveCallback by shared_ptr. You should be keeping a shared_ptr +// to the callback passed to AddCallback() if you want to remove +// it later. Don't use the direct pointer function when adding +// if you want to keep a copy. +//-------------------------------------------------------------------- +void +agBaseProperty::RemoveCallback(std::shared_ptr i_pCallback) +{ + envSTLHelpers::RemoveOneValue(m_CallbackObjects, i_pCallback); +} + +//-------------------------------------------------------------------- +// call all the callbacks +//-------------------------------------------------------------------- +void +agBaseProperty::NotifyCallbacksPropertyChanged(bool i_bWithUndo) +{ + const int num_callbackobjs = m_CallbackObjects.size(); + for (int i = 0; i < num_callbackobjs; ++i) { + m_CallbackObjects[i]->PropertyChanged(this, i_bWithUndo); + } +} + +//-------------------------------------------------------------------- +// In some cases we want the form builder to check whether or not +// this property should be visible. +//-------------------------------------------------------------------- +void +agBaseProperty::SetVisible(bool i_bVisible) +{ + m_bVisible = i_bVisible; +} + +bool +agBaseProperty::GetVisible() const +{ + return m_bVisible; +} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +// const std::string& agProperty::GetType() +//{ +// return m_Type; +//} + +//-------------------------------------------------------------------- +// The type of property it is +//-------------------------------------------------------------------- +// void agProperty::SetType(const std::string i_Type) +//{ +// m_Type = i_Type; +//} diff --git a/renderlib/core/prty/agProperty.h b/renderlib/core/prty/agProperty.h new file mode 100644 index 00000000..0343ea71 --- /dev/null +++ b/renderlib/core/prty/agProperty.h @@ -0,0 +1,223 @@ +#pragma once + +#include "Logging.h" + +#include "core/prty/agPropertyCallback.hpp" +#include "core/undo/undoUndoOperation.hpp" + +#include +#include +#include +#include +#include +#include + +// only enable this to verbosely dump every single property setter. +// This implies that the value type must be streamable to std::ostream. +#ifndef PRTY_PROPERTY_DEBUG +#define PRTY_PROPERTY_DEBUG 0 +#endif + +class agBaseProperty +{ +public: + // Base class for properties, can be used to store common flags or data. + // This class is not intended to be instantiated directly. + agBaseProperty() + : m_bVisible(true) + { + m_Flags.m_bAnimatable = false; + m_Flags.m_bScripted = false; + m_Flags.m_bValueVariation = false; + } + agBaseProperty(const std::string& i_Name) + : name(i_Name) + , m_bVisible(true) + { + m_Flags.m_bAnimatable = false; + m_Flags.m_bScripted = false; + m_Flags.m_bValueVariation = false; + } + + virtual ~agBaseProperty() {} + + agBaseProperty& operator=(const agBaseProperty& i_Property); + + const std::string& GetPropertyName() const; + void SetPropertyName(const std::string& i_Name); + + //-------------------------------------------------------------------- + // Animatable - can this property be animated? + //-------------------------------------------------------------------- + bool IsAnimatable() const; + void SetAnimatable(bool i_bVal); + + //-------------------------------------------------------------------- + // Scripted - Is this property currently being animated? + //-------------------------------------------------------------------- + bool IsScripted() const; + void SetScripted(bool i_bVal); + + //-------------------------------------------------------------------- + // ValueVariation - Does the current value vary from the scripted value? + //-------------------------------------------------------------------- + bool HasValueVariation() const; + void SetValueVariation(bool i_bVal); + + //-------------------------------------------------------------------- + // AddCallback using interface. + // + // NOTE: This property will take ownership of the callback + // pointer and will delete it in its destructor! It should be + // created on the heap and probably should use the + // prtyCallbackWrapper template. + //-------------------------------------------------------------------- + void AddCallback(agPropertyCallback* i_pCallback); + + //-------------------------------------------------------------------- + // AddCallback shared pointer variation for when you want to + // keep a copy of the callback also. + //-------------------------------------------------------------------- + void AddCallback(std::shared_ptr i_pCallback); + + //-------------------------------------------------------------------- + // RemoveCallback by shared_ptr. You should be keeping a shared_ptr + // to the callback passed to AddCallback() if you want to remove + // it later. Don't use the direct pointer function when adding + // if you want to keep a copy. + //-------------------------------------------------------------------- + void RemoveCallback(std::shared_ptr i_pCallback); + + //-------------------------------------------------------------------- + // Call all the callbacks - + // i_bWithUndo should be set to (i_Undoable != eNoUndo) + // in derived classes SetValue() functions. + //-------------------------------------------------------------------- + void NotifyCallbacksPropertyChanged(bool i_bWithUndo); + + //-------------------------------------------------------------------- + // The type of property it is + //-------------------------------------------------------------------- + virtual const char* GetType() = 0; + + //-------------------------------------------------------------------- + // Create an undo operation of the correct type for this + // property. A reference to this property should be passed in. + // Ownership passes to the caller. + //-------------------------------------------------------------------- + // virtual undoUndoOperation* CreateUndoOperation(std::shared_ptr i_pPropertyRef) = 0; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // virtual void Read(chReader& io_Reader) = 0; + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // virtual void Write(chWriter& io_Writer) const = 0; + + //-------------------------------------------------------------------- + // In some cases we want the form builder to check whether or not + // this property should be visible. + //-------------------------------------------------------------------- + void SetVisible(bool i_bVisible); + bool GetVisible() const; + +protected: + std::string name; + std::vector> m_CallbackObjects; + bool m_bVisible; // is this property visible in the UI? + // Flags for the property + struct + { + bool m_bAnimatable : 1; // can this property be animated? + bool m_bScripted : 1; // Is this property currently being animated? + bool m_bValueVariation : 1; // Does the current value vary from the scripted value? + } m_Flags; +}; + +// a property has a name and a value. +// the init value is default-constructed or passed in. +// The value type must be copyable, assignable, and default-constructible. +// The value must also be streamable to std::ostream. +template && std::is_copy_assignable_v && std::is_default_constructible_v && + std::is_move_constructible_v && std::is_move_assignable_v && + std::is_convertible_v() << std::declval()), std::ostream&>>> +class agProperty : public agBaseProperty +{ +public: + agProperty(std::string name, const T& val) + : agBaseProperty(name) + , value(val) + { + } + + virtual ~agProperty() {} + + void set(const T& val, bool i_bDirty = false) + { + // TODO - check if the value has changed + // TODO - do we notify if value hasn't changed? + +#if PRTY_PROPERTY_DEBUG + LOG_INFO << "Property " << name << " set from " << value << " to " << val; +#endif + if (value != val) { + value = val; + + // call all callbacks + NotifyCallbacksPropertyChanged(i_bDirty); + } + } + + std::string getName() const { return name; } + + // copy???? + T get() const { return value; } + + // non-copy, just use paren operator + T& operator()() const { return value; } + + // set up the rule of 5 + agProperty(const agProperty& other) + : agBaseProperty(other.name) + , value(other.value) + { + } + + agProperty& operator=(const agProperty& other) + { + if (this != &other) { + name = other.name; + set(other.value); // use set to notify callbacks + } + return *this; + } + + // direct assignment from a value + agProperty& operator=(const T& value) + { + set(value); // use set to notify callbacks + return *this; + } + + // TODO should we implement move semantics? + // agProperty(agProperty&& other) + // : name(std::move(other.name)) + // , value(std::move(other.value)) + // { + // } + + // agProperty& operator=(agProperty&& other) + // { + // if (this != &other) { + // name = std::move(other.name); + // set(std::move(other.value)); // use set to notify callbacks + // } + // return *this; + // } + +private: + T value; +}; diff --git a/renderlib/core/prty/agPropertyCallback.hpp b/renderlib/core/prty/agPropertyCallback.hpp new file mode 100644 index 00000000..98a9679e --- /dev/null +++ b/renderlib/core/prty/agPropertyCallback.hpp @@ -0,0 +1,74 @@ +/****************************************************************************\ +** prtyPropertyCallback.hpp +** +** Template and interface for handling property changed callbacks. +** +** You create and register a callback to a member function with this syntax: +** m_Property.AddCallback(new prtyCallbackWrapper(this, &xxxObject::FunctionName)); +** +** +** +\****************************************************************************/ +#pragma once +#include + +//============================================================================ +// forward references +//============================================================================ +class agBaseProperty; + +//============================================================================ +// Interface +//============================================================================ +class agPropertyCallback +{ +public: + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + virtual ~agPropertyCallback() {} + + //-------------------------------------------------------------------- + // PropertyChanged is called when a property's value is changed + // through a "SetValue" function. The boolean flag is true + // if the change is coming from the user interface and therefore + // should mark the document containing the property as dirty. + //-------------------------------------------------------------------- + virtual void PropertyChanged(agBaseProperty* i_pProperty, bool i_bDirty) = 0; +}; + +//============================================================================ +// Wrapper template +//============================================================================ +template +struct agPropertyCallbackWrapper : public agPropertyCallback +{ + agPropertyCallbackWrapper(T* i_this, void (T::*i_memberFunc)(agBaseProperty*, bool)) + : obj_ptr(i_this) + , func_ptr(i_memberFunc) + { + } + + T* obj_ptr; + void (T::*func_ptr)(agBaseProperty*, bool); + + virtual void PropertyChanged(agBaseProperty* i_pProperty, bool i_bWithUndo) + { + (obj_ptr->*func_ptr)(i_pProperty, i_bWithUndo); + } +}; + +class agPropertyCallbackLambda : public agPropertyCallback +{ + std::function m_Callback; + +public: + agPropertyCallbackLambda(std::function i_Callback) + : m_Callback(i_Callback) + { + } + + virtual void PropertyChanged(agBaseProperty* i_pProperty, bool i_bWithUndo) override + { + m_Callback(i_pProperty, i_bWithUndo); + } +}; \ No newline at end of file diff --git a/renderlib/core/prty/prtyProperty.cpp b/renderlib/core/prty/prtyProperty.cpp index 4b123c62..1aa831ff 100644 --- a/renderlib/core/prty/prtyProperty.cpp +++ b/renderlib/core/prty/prtyProperty.cpp @@ -132,7 +132,7 @@ prtyProperty::operator=(const prtyProperty& i_Property) } //-------------------------------------------------------------------- -// AddCallback using interface, used by unmanaged classes. +// AddCallback using interface. // // NOTE: This property will take ownership of the callback // pointer and will delete it in its destructor! It should be From 4ecac31e787e3932ec30ac352b97826777543cc8 Mon Sep 17 00:00:00 2001 From: dmt Date: Sat, 21 Jun 2025 14:55:56 -0700 Subject: [PATCH 22/60] WIP commit --- renderlib/AppearanceUiDescription.hpp | 32 +++++ renderlib/CameraDataObject.hpp | 5 + renderlib/CameraUiDescription.cpp | 99 ++++++++------- renderlib/CameraUiDescription.hpp | 28 ++++- renderlib/core/prty/CMakeLists.txt | 3 - renderlib/core/prty/prtyProperty.hpp | 8 -- renderlib/core/prty/prtyPropertyTemplate.hpp | 56 ++++++--- renderlib/core/prty/prtyPropertyUIInfo.hpp | 18 +++ renderlib/core/undo/undoUndoOperation.hpp | 2 + renderlib/uiInfo.hpp | 126 +++++++++++-------- test/test_prty.cpp | 8 ++ 11 files changed, 265 insertions(+), 120 deletions(-) diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceUiDescription.hpp index 6441c56a..c0169b70 100644 --- a/renderlib/AppearanceUiDescription.hpp +++ b/renderlib/AppearanceUiDescription.hpp @@ -1,5 +1,8 @@ #pragma once +#include "AppearanceDataObject.hpp" +#include "core/prty/prtyObject.hpp" +#include "RenderPrefs.hpp" #include "uiInfo.hpp" struct AppearanceUiDescription @@ -16,3 +19,32 @@ struct AppearanceUiDescription static ColorPickerUiInfo m_boundingBoxColor; static CheckBoxUiInfo m_showScaleBar; }; + +class AppearanceObject : public prtyObject +{ +public: + AppearanceObject(); + + void updatePropsFromObject(); + void updateObjectFromProps(); + +private: + // the properties + AppearanceDataObject m_appearanceDataObject; + + // the actual camera + std::shared_ptr m_RenderPrefs; + + // the ui info + ComboBoxUiInfo* m_rendererType; + ComboBoxUiInfo* m_shadingType; + FloatSliderSpinnerUiInfo* m_densityScale; + FloatSliderSpinnerUiInfo* m_gradientFactor; + FloatSliderSpinnerUiInfo* m_stepSizePrimaryRay; + FloatSliderSpinnerUiInfo* m_stepSizeSecondaryRay; + CheckBoxUiInfo* m_interpolate; + ColorPickerUiInfo* m_backgroundColor; + CheckBoxUiInfo* m_showBoundingBox; + ColorPickerUiInfo* m_boundingBoxColor; + CheckBoxUiInfo* m_showScaleBar; +}; diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index a11924c9..31363078 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -8,6 +8,11 @@ class CameraDataObject { public: + CameraDataObject() + : m_camera(nullptr) + { + // updatePropsFromCamera(); + } CameraDataObject(CCamera* camera); prtyFloat Exposure{ "Exposure", 0.75f }; diff --git a/renderlib/CameraUiDescription.cpp b/renderlib/CameraUiDescription.cpp index 52523f60..92a4d34a 100644 --- a/renderlib/CameraUiDescription.cpp +++ b/renderlib/CameraUiDescription.cpp @@ -1,45 +1,58 @@ #include "CameraUiDescription.hpp" -FloatSliderSpinnerUiInfo CameraUiDescription::m_exposure("Exposure", - "Set Exposure", - "Set camera exposure", - 0.0f, - 1.0f, - 2, // decimals - 0.01, // singleStep - 0 // numTickMarks -); -ComboBoxUiInfo CameraUiDescription::m_exposureIterations("Exposure Time", - "Set Exposure Time", - "Set number of samples to accumulate per viewport update", - { "1", "2", "4", "8" }); -CheckBoxUiInfo CameraUiDescription::m_noiseReduction("Noise Reduction", - "Enable denoising pass", - "Enable denoising pass"); -FloatSliderSpinnerUiInfo CameraUiDescription::m_apertureSize("Aperture Size", - "Set camera aperture size", - "Set camera aperture size", - 0.0f, - 0.1f, - 2, // decimals - 0.01, // singleStep - 0, // numTickMarks - " mm"); -FloatSliderSpinnerUiInfo CameraUiDescription::m_fieldOfView("Field of view", - "Set camera field of view angle", - "Set camera field of view angle", - 10.0f, - 150.0f, - 2, // decimals - 0.01, // singleStep - 0, // numTickMarks - " deg"); -FloatSliderSpinnerUiInfo CameraUiDescription::m_focalDistance("Focal distance", - "Set focal distance", - "Set focal distance", - 0.0f, - 15.0f, - 2, // decimals - 0.01, // singleStep - 0, // numTickMarks - " m"); +// FloatSliderSpinnerUiInfo CameraUiDescription::m_exposure("Exposure", +// "Set Exposure", +// "Set camera exposure", +// 0.0f, +// 1.0f, +// 2, // decimals +// 0.01, // singleStep +// 0 // numTickMarks +// ); +// ComboBoxUiInfo CameraUiDescription::m_exposureIterations("Exposure Time", +// "Set Exposure Time", +// "Set number of samples to accumulate per viewport update", +// { "1", "2", "4", "8" }); +// CheckBoxUiInfo CameraUiDescription::m_noiseReduction("Noise Reduction", +// "Enable denoising pass", +// "Enable denoising pass"); +// FloatSliderSpinnerUiInfo CameraUiDescription::m_apertureSize("Aperture Size", +// "Set camera aperture size", +// "Set camera aperture size", +// 0.0f, +// 0.1f, +// 2, // decimals +// 0.01, // singleStep +// 0, // numTickMarks +// " mm"); +// FloatSliderSpinnerUiInfo CameraUiDescription::m_fieldOfView("Field of view", +// "Set camera field of view angle", +// "Set camera field of view angle", +// 10.0f, +// 150.0f, +// 2, // decimals +// 0.01, // singleStep +// 0, // numTickMarks +// " deg"); +// FloatSliderSpinnerUiInfo CameraUiDescription::m_focalDistance("Focal distance", +// "Set focal distance", +// "Set focal distance", +// 0.0f, +// 15.0f, +// 2, // decimals +// 0.01, // singleStep +// 0, // numTickMarks +// " m"); + +CameraObject::CameraObject() + : prtyObject() +{ + m_Camera = std::make_shared(); + m_ExposureUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.Exposure, "Camera", "Exposure"); + m_ExposureIterationsUIInfo = + new ComboBoxUiInfo(&m_cameraDataObject.ExposureIterations, "Camera", "Exposure Iterations"); + m_NoiseReductionUIInfo = new CheckBoxUiInfo(&m_cameraDataObject.NoiseReduction, "Camera", "Noise Reduction"); + m_ApertureSizeUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.ApertureSize, "Camera", "Aperture Size"); + m_FieldOfViewUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FieldOfView, "Camera", "Field of View"); + m_FocalDistanceUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FocalDistance, "Camera", "Focal Distance"); +} diff --git a/renderlib/CameraUiDescription.hpp b/renderlib/CameraUiDescription.hpp index d7b0a988..f7b95716 100644 --- a/renderlib/CameraUiDescription.hpp +++ b/renderlib/CameraUiDescription.hpp @@ -1,6 +1,8 @@ #pragma once +#include "CameraDataObject.hpp" #include "uiInfo.hpp" +#include "core/prty/prtyObject.hpp" struct CameraUiDescription { @@ -10,4 +12,28 @@ struct CameraUiDescription static FloatSliderSpinnerUiInfo m_apertureSize; static FloatSliderSpinnerUiInfo m_fieldOfView; static FloatSliderSpinnerUiInfo m_focalDistance; -}; \ No newline at end of file +}; + +class CameraObject : public prtyObject +{ +public: + CameraObject(); + + void updatePropsFromObject(); + void updateObjectFromProps(); + +private: + // the properties + CameraDataObject m_cameraDataObject; + + // the actual camera + std::shared_ptr m_Camera; + + // the ui info + FloatSliderSpinnerUiInfo* m_ExposureUIInfo; + ComboBoxUiInfo* m_ExposureIterationsUIInfo; + CheckBoxUiInfo* m_NoiseReductionUIInfo; + FloatSliderSpinnerUiInfo* m_ApertureSizeUIInfo; + FloatSliderSpinnerUiInfo* m_FieldOfViewUIInfo; + FloatSliderSpinnerUiInfo* m_FocalDistanceUIInfo; +}; diff --git a/renderlib/core/prty/CMakeLists.txt b/renderlib/core/prty/CMakeLists.txt index d220f976..03edfb9b 100644 --- a/renderlib/core/prty/CMakeLists.txt +++ b/renderlib/core/prty/CMakeLists.txt @@ -1,7 +1,4 @@ target_sources(renderlib PRIVATE -"${CMAKE_CURRENT_SOURCE_DIR}/agProperty.h" -"${CMAKE_CURRENT_SOURCE_DIR}/agProperty.cpp" -"${CMAKE_CURRENT_SOURCE_DIR}/agPropertyCallback.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyBoolean.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/prtyColor.cpp" diff --git a/renderlib/core/prty/prtyProperty.hpp b/renderlib/core/prty/prtyProperty.hpp index 4577a628..98a740bb 100644 --- a/renderlib/core/prty/prtyProperty.hpp +++ b/renderlib/core/prty/prtyProperty.hpp @@ -52,17 +52,9 @@ ** \****************************************************************************/ #pragma once -#ifdef PRTY_PROPERTY_HPP -#error prtyProperty.hpp multiply included -#endif -#define PRTY_PROPERTY_HPP -#ifndef PRTY_PROPERTYCALLBACK_HPP #include "core/prty/prtyPropertyCallback.hpp" -#endif -#ifndef UNDO_UNDOOPERATION_HPP #include "core/undo/undoUndoOperation.hpp" -#endif #include #include diff --git a/renderlib/core/prty/prtyPropertyTemplate.hpp b/renderlib/core/prty/prtyPropertyTemplate.hpp index 2f1ee775..78d05a7c 100644 --- a/renderlib/core/prty/prtyPropertyTemplate.hpp +++ b/renderlib/core/prty/prtyPropertyTemplate.hpp @@ -7,27 +7,26 @@ ** \****************************************************************************/ #pragma once -#ifdef PRTY_PROPERTYTEMPLATE_HPP -#error prtyPropertyTemplate.hpp multiply included -#endif -#define PRTY_PROPERTYTEMPLATE_HPP -#ifndef PRTY_PROPERTY_HPP #include "core/prty/prtyProperty.hpp" -#endif -#ifndef PRTY_UNDOTEMPLATE_HPP #include "core/prty/prtyUndoTemplate.hpp" -#endif + +#include //============================================================================ //============================================================================ -template +template && std::is_copy_assignable_v && + std::is_default_constructible_v && std::is_move_constructible_v && + std::is_move_assignable_v && + std::is_convertible_v() << std::declval()), std::ostream&>>> class prtyPropertyTemplate : public prtyProperty { public: //-------------------------------------------------------------------- //-------------------------------------------------------------------- - prtyPropertyTemplate(const std::string& i_Name, ConstRefType i_InitialValue) + prtyPropertyTemplate(const std::string& i_Name, const ValueType& i_InitialValue) : prtyProperty(i_Name) , m_Value(i_InitialValue) { @@ -36,15 +35,15 @@ class prtyPropertyTemplate : public prtyProperty //---------------------------------------------------------------------------- // Get value of property //---------------------------------------------------------------------------- - inline ConstRefType GetValue() const { return m_Value; } + inline const ValueType& GetValue() const { return m_Value; } //---------------------------------------------------------------------------- // Set value of property. The boolean flag is true // if the change is coming from the user interface and therefore // should mark the document containing the property as dirty. //---------------------------------------------------------------------------- - // void SetValue(ConstRefType i_Value, UndoFlags i_Undoable = eNoUndo) - void SetValue(ConstRefType i_Value, bool i_bDirty = false) + // void SetValue(const ValueType& i_Value, UndoFlags i_Undoable = eNoUndo) + void SetValue(const ValueType& i_Value, bool i_bDirty = false) { if (m_Value != i_Value) { m_Value = i_Value; @@ -56,7 +55,7 @@ class prtyPropertyTemplate : public prtyProperty //-------------------------------------------------------------------- // Set value of property without notifying the callbacks //-------------------------------------------------------------------- - void SetValueWithoutNotify(ConstRefType i_Value) { m_Value = i_Value; } + void SetValueWithoutNotify(const ValueType& i_Value) { m_Value = i_Value; } //-------------------------------------------------------------------- // Create and return undo operation of correct type for this property. @@ -67,6 +66,35 @@ class prtyPropertyTemplate : public prtyProperty return new prtyUndoTemplate(i_pPropertyRef, this->GetValue()); } + prtyPropertyTemplate& operator=(const prtyPropertyTemplate& i_Property) + { + // copy base data + prtyProperty::operator=(i_Property); + + SetValue(i_Property.GetValue()); + return *this; + } + + prtyPropertyTemplate& operator=(const ValueType& i_Value) + { + SetValue(i_Value); + return *this; + } + + bool operator==(const prtyPropertyTemplate& i_Property) const + { + return GetValue() == i_Property.GetValue(); + } + + bool operator!=(const prtyPropertyTemplate& i_Property) const + { + return GetValue() != i_Property.GetValue(); + } + + bool operator==(const ValueType& i_Value) const { return GetValue() == i_Value; } + + bool operator!=(const ValueType& i_Value) const { return GetValue() != i_Value; } + protected: ValueType m_Value; }; diff --git a/renderlib/core/prty/prtyPropertyUIInfo.hpp b/renderlib/core/prty/prtyPropertyUIInfo.hpp index c832c570..4a928bd1 100644 --- a/renderlib/core/prty/prtyPropertyUIInfo.hpp +++ b/renderlib/core/prty/prtyPropertyUIInfo.hpp @@ -19,6 +19,24 @@ class prtyProperty; class prtyReferenceCreator; +// TODO add statusTip and toolTip to prtyPropertyUIInfo +// struct GenericUIInfo +// { +// std::string type; +// std::string formLabel; +// std::string statusTip; +// std::string toolTip; + +// GenericUIInfo() = default; +// GenericUIInfo(std::string type, std::string formLabel, std::string statusTip, std::string toolTip) +// : type(type) +// , formLabel(formLabel) +// , statusTip(statusTip) +// , toolTip(toolTip) +// { +// } +// }; + //============================================================================ //============================================================================ class prtyPropertyUIInfo diff --git a/renderlib/core/undo/undoUndoOperation.hpp b/renderlib/core/undo/undoUndoOperation.hpp index c2e8fe35..a9aeaae1 100644 --- a/renderlib/core/undo/undoUndoOperation.hpp +++ b/renderlib/core/undo/undoUndoOperation.hpp @@ -7,6 +7,8 @@ ** ** \****************************************************************************/ +#pragma once + #ifdef UNDO_UNDOOPERATION_HPP #error undoUndoOperation.hpp multiply included #endif diff --git a/renderlib/uiInfo.hpp b/renderlib/uiInfo.hpp index 21acacd5..5e344432 100644 --- a/renderlib/uiInfo.hpp +++ b/renderlib/uiInfo.hpp @@ -1,48 +1,62 @@ #pragma once +#include "core/prty/prtyPropertyUIInfo.hpp" + #include #include -struct GenericUIInfo +class CheckBoxUiInfo : public prtyPropertyUIInfo { - std::string type; - std::string formLabel; - std::string statusTip; - std::string toolTip; - - GenericUIInfo() = default; - GenericUIInfo(std::string type, std::string formLabel, std::string statusTip, std::string toolTip) - : type(type) - , formLabel(formLabel) - , statusTip(statusTip) - , toolTip(toolTip) +public: + static constexpr const char* TYPE = "CheckBox"; + CheckBoxUiInfo(prtyProperty* i_pProperty) + : prtyPropertyUIInfo(i_pProperty) { + SetControlName(TYPE); + } + CheckBoxUiInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description) + : prtyPropertyUIInfo(i_pProperty, i_Category, i_Description) + { + SetControlName(TYPE); } }; -struct CheckBoxUiInfo : public GenericUIInfo -{ - static constexpr const char* TYPE = "CheckBox"; - CheckBoxUiInfo() { type = CheckBoxUiInfo::TYPE; } - CheckBoxUiInfo(std::string formLabel, std::string statusTip, std::string toolTip) - : GenericUIInfo(CheckBoxUiInfo::TYPE, formLabel, statusTip, toolTip) +class ColorPickerUiInfo : public prtyPropertyUIInfo +{ +public: + static constexpr const char* TYPE = "ColorPicker"; + ColorPickerUiInfo(prtyProperty* i_pProperty) + : prtyPropertyUIInfo(i_pProperty) { + SetControlName(TYPE); + } + ColorPickerUiInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description) + : prtyPropertyUIInfo(i_pProperty, i_Category, i_Description) + { + SetControlName(TYPE); } }; -struct ComboBoxUiInfo : public GenericUIInfo + +class ComboBoxUiInfo : public prtyPropertyUIInfo { +public: static constexpr const char* TYPE = "ComboBox"; std::vector items; - ComboBoxUiInfo() { type = ComboBoxUiInfo::TYPE; } - ComboBoxUiInfo(std::string formLabel, std::string statusTip, std::string toolTip, std::vector items) - : GenericUIInfo(ComboBoxUiInfo::TYPE, formLabel, statusTip, toolTip) - , items(items) + ComboBoxUiInfo(prtyProperty* i_pProperty) + : prtyPropertyUIInfo(i_pProperty) { + SetControlName(TYPE); + } + ComboBoxUiInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description) + : prtyPropertyUIInfo(i_pProperty, i_Category, i_Description) + { + SetControlName(TYPE); } }; -struct FloatSliderSpinnerUiInfo : public GenericUIInfo +class FloatSliderSpinnerUiInfo : public prtyPropertyUIInfo { +public: static constexpr const char* TYPE = "FloatSliderSpinner"; float min = 0.0f; float max = 0.0f; @@ -51,28 +65,39 @@ struct FloatSliderSpinnerUiInfo : public GenericUIInfo int numTickMarks = 0; std::string suffix; - FloatSliderSpinnerUiInfo() { type = FloatSliderSpinnerUiInfo::TYPE; } - FloatSliderSpinnerUiInfo(std::string formLabel, - std::string statusTip, - std::string toolTip, - float min, - float max, - int decimals, - float singleStep, - int numTickMarks = 0, - std::string suffix = "") - : GenericUIInfo(FloatSliderSpinnerUiInfo::TYPE, formLabel, statusTip, toolTip) - , min(min) - , max(max) - , decimals(decimals) - , singleStep(singleStep) - , numTickMarks(numTickMarks) - , suffix(suffix) + FloatSliderSpinnerUiInfo(prtyProperty* i_pProperty) + : prtyPropertyUIInfo(i_pProperty) + { + SetControlName(TYPE); + } + FloatSliderSpinnerUiInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description) + : prtyPropertyUIInfo(i_pProperty, i_Category, i_Description) { + SetControlName(TYPE); } }; -struct IntSliderSpinnerUiInfo : public GenericUIInfo +// std::string statusTip, +// std::string toolTip, +// float min, +// float max, +// int decimals, +// float singleStep, +// int numTickMarks = 0, +// std::string suffix = "") +// : GenericUIInfo(FloatSliderSpinnerUiInfo::TYPE, formLabel, statusTip, toolTip) +// , min(min) +// , max(max) +// , decimals(decimals) +// , singleStep(singleStep) +// , numTickMarks(numTickMarks) +// , suffix(suffix) +// { +// } +// }; + +class IntSliderSpinnerUiInfo : public prtyPropertyUIInfo { +public: static constexpr const char* TYPE = "IntSliderSpinner"; int min; int max; @@ -80,16 +105,15 @@ struct IntSliderSpinnerUiInfo : public GenericUIInfo int numTickMarks; std::string suffix; - IntSliderSpinnerUiInfo() { type = IntSliderSpinnerUiInfo::TYPE; } -}; - -struct ColorPickerUiInfo : public GenericUIInfo -{ - static constexpr const char* TYPE = "ColorPicker"; + IntSliderSpinnerUiInfo(prtyProperty* i_pProperty) + : prtyPropertyUIInfo(i_pProperty) + { + SetControlName(TYPE); + } - ColorPickerUiInfo() { type = ColorPickerUiInfo::TYPE; } - ColorPickerUiInfo(std::string formLabel, std::string statusTip, std::string toolTip) - : GenericUIInfo(ColorPickerUiInfo::TYPE, formLabel, statusTip, toolTip) + IntSliderSpinnerUiInfo(prtyProperty* i_pProperty, const std::string& i_Category, const std::string& i_Description) + : prtyPropertyUIInfo(i_pProperty, i_Category, i_Description) { + SetControlName(TYPE); } }; diff --git a/test/test_prty.cpp b/test/test_prty.cpp index 6834a057..2e3ce8b2 100644 --- a/test/test_prty.cpp +++ b/test/test_prty.cpp @@ -18,9 +18,17 @@ TEST_CASE("prtyProperty", "[prtyProperty]") // REQUIRE(p.get() == 0); p.SetValue(42); REQUIRE(p.GetValue() == 42); + REQUIRE(p == 42); + REQUIRE(p.GetPropertyName() == "int"); + REQUIRE(p.GetType() == "int8_t"); + REQUIRE(p != 43); prtyText p2("string", "hello"); REQUIRE(p2.GetValue() == "hello"); + REQUIRE(p2.GetPropertyName() == "string"); + REQUIRE(p2.GetType() == "std::string"); + REQUIRE(p2 == "hello"); + REQUIRE(p2 != "world"); p2.SetValue("world"); REQUIRE(p2.GetValue() == "world"); } From 23bb928df5846e11bda09408d2100ccaf668ca27 Mon Sep 17 00:00:00 2001 From: dmt Date: Sat, 21 Jun 2025 17:30:07 -0700 Subject: [PATCH 23/60] WIP --- renderlib/AppearanceDataObject.cpp | 105 +----------- renderlib/AppearanceDataObject.hpp | 12 +- renderlib/AppearanceUiDescription.cpp | 179 ++++++++++++++------- renderlib/AppearanceUiDescription.hpp | 4 +- renderlib/CameraDataObject.cpp | 68 -------- renderlib/CameraDataObject.hpp | 14 +- renderlib/CameraUiDescription.cpp | 42 ++++- renderlib/CameraUiDescription.hpp | 3 +- renderlib/core/prty/prtyPropertyUIInfo.hpp | 5 +- 9 files changed, 174 insertions(+), 258 deletions(-) diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 810085a1..82055d9a 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -3,107 +3,4 @@ #include "Enumerations.h" #include "Logging.h" -AppearanceDataObject::AppearanceDataObject(RenderSettings* renderSettings, Scene* scene) - : m_renderSettings(renderSettings) - , m_scene(scene) -{ - updatePropsFromRenderSettings(); - // hook up properties to update the underlying camera - // RendererType.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // ShadingType.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // DensityScale.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // GradientFactor.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // StepSizePrimaryRay.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // StepSizeSecondaryRay.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // Interpolate.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // BackgroundColor.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // ShowBoundingBox.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // BoundingBoxColor.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // ShowScaleBar.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); -} - -void -AppearanceDataObject::updatePropsFromRenderSettings() -{ - if (m_renderSettings) { - ShadingType.SetValue(m_renderSettings->m_RenderSettings.m_ShadingType); - RendererType.SetValue(m_renderSettings->m_rendererType); - DensityScale.SetValue(m_renderSettings->m_RenderSettings.m_DensityScale); - GradientFactor.SetValue(m_renderSettings->m_RenderSettings.m_GradientFactor); - StepSizePrimaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactor); - StepSizeSecondaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); - Interpolate.SetValue(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); - } - if (m_scene) { - BackgroundColor.SetValue(glm::vec4(m_scene->m_material.m_backgroundColor[0], - m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2], - 1.0f)); - ShowBoundingBox.SetValue(m_scene->m_material.m_showBoundingBox); - BoundingBoxColor.SetValue(glm::vec4(m_scene->m_material.m_boundingBoxColor[0], - m_scene->m_material.m_boundingBoxColor[1], - m_scene->m_material.m_boundingBoxColor[2], - 1.0f)); - ShowScaleBar.SetValue(m_scene->m_showScaleBar); - } -} - -void -AppearanceDataObject::update() -{ - // update low-level object from properties - if (m_renderSettings) { - m_renderSettings->m_RenderSettings.m_ShadingType = ShadingType.GetValue(); - m_renderSettings->m_rendererType = RendererType.GetValue(); - m_renderSettings->m_RenderSettings.m_DensityScale = DensityScale.GetValue(); - m_renderSettings->m_RenderSettings.m_GradientFactor = GradientFactor.GetValue(); - m_renderSettings->m_RenderSettings.m_StepSizeFactor = StepSizePrimaryRay.GetValue(); - m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = StepSizeSecondaryRay.GetValue(); - m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = Interpolate.GetValue(); - m_scene->m_material.m_backgroundColor[0] = BackgroundColor.GetValue().x; - m_scene->m_material.m_backgroundColor[1] = BackgroundColor.GetValue().y; - m_scene->m_material.m_backgroundColor[2] = BackgroundColor.GetValue().z; - m_scene->m_material.m_showBoundingBox = ShowBoundingBox.GetValue(); - m_scene->m_material.m_boundingBoxColor[0] = BoundingBoxColor.GetValue().x; - m_scene->m_material.m_boundingBoxColor[1] = BoundingBoxColor.GetValue().y; - m_scene->m_material.m_boundingBoxColor[2] = BoundingBoxColor.GetValue().z; - m_scene->m_showScaleBar = ShowScaleBar.GetValue(); - - m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); - m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); - m_renderSettings->m_DirtyFlags.SetFlag(LightsDirty); - } -} \ No newline at end of file +AppearanceDataObject::AppearanceDataObject() {} diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index f389517b..35774b7f 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -5,14 +5,12 @@ #include "core/prty/prtyBoolean.hpp" #include "core/prty/prtyVector3d.hpp" #include "core/prty/prtyColor.hpp" -#include "AppScene.h" -#include "RenderSettings.h" #include "glm.h" class AppearanceDataObject { public: - AppearanceDataObject(RenderSettings* rs, Scene* scene); + AppearanceDataObject(); prtyInt8 RendererType{ "RendererType", 0 }; prtyInt8 ShadingType{ "ShadingType", 0 }; @@ -25,12 +23,4 @@ class AppearanceDataObject prtyBoolean ShowBoundingBox{ "ShowBoundingBox", false }; prtyColor BoundingBoxColor{ "BoundingBoxColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) }; prtyBoolean ShowScaleBar{ "ShowScaleBar", false }; - - RenderSettings* m_renderSettings; - Scene* m_scene; - - void updatePropsFromRenderSettings(); - -private: - void update(); }; diff --git a/renderlib/AppearanceUiDescription.cpp b/renderlib/AppearanceUiDescription.cpp index c8925306..ed1fc23e 100644 --- a/renderlib/AppearanceUiDescription.cpp +++ b/renderlib/AppearanceUiDescription.cpp @@ -1,56 +1,127 @@ #include "AppearanceUiDescription.hpp" -ComboBoxUiInfo AppearanceUiDescription::m_rendererType("Renderer Type", - "Select volume rendering type", - "Select volume rendering type", - { "Ray march blending", "Path Traced" }); -ComboBoxUiInfo AppearanceUiDescription::m_shadingType("Shading Type", - "Select volume shading style", - "Select volume shading style", - { "BRDF Only", "Phase Function Only", "Mixed" }); -FloatSliderSpinnerUiInfo AppearanceUiDescription::m_densityScale("Scattering Density", - "Set scattering density for volume", - "Set scattering density for volume", - 0.001f, - 100.0f, - 3, - 0.01f, - 10); -FloatSliderSpinnerUiInfo AppearanceUiDescription::m_gradientFactor("Shading Type Mixture", - "Mix between BRDF and Phase shading", - "Mix between BRDF and Phase shading", - 0.0f, - 1.0f, - 3, - 0.01f, - 10); -FloatSliderSpinnerUiInfo AppearanceUiDescription::m_stepSizePrimaryRay("Primary Ray Step Size", - "Set volume ray march step size for camera rays", - "Set volume ray march step size for camera rays", - 1.0f, - 100.0f, - 3, - 0.01f, - 10); -FloatSliderSpinnerUiInfo AppearanceUiDescription::m_stepSizeSecondaryRay( - "Secondary Ray Step Size", - "Set volume ray march step size for scattered rays", - "Set volume ray march step size for scattered rays", - 1.0f, - 100.0f, - 3, - 0.01f, - 10); -CheckBoxUiInfo AppearanceUiDescription::m_interpolate("Interpolate", - "Interpolated volume sampling", - "Interpolated volume sampling"); -ColorPickerUiInfo AppearanceUiDescription::m_backgroundColor("Background Color", - "Set background color", - "Set background color"); -CheckBoxUiInfo AppearanceUiDescription::m_showBoundingBox("Show Bounding Box", - "Show/hide bounding box", - "Show/hide bounding box"); -ColorPickerUiInfo AppearanceUiDescription::m_boundingBoxColor("Bounding Box Color", - "Set bounding box color", - "Set bounding box color"); -CheckBoxUiInfo AppearanceUiDescription::m_showScaleBar("Show Scale Bar", "Show/hide scale bar", "Show/hide scale bar"); +// ComboBoxUiInfo AppearanceUiDescription::m_rendererType("Renderer Type", +// "Select volume rendering type", +// "Select volume rendering type", +// { "Ray march blending", "Path Traced" }); +// ComboBoxUiInfo AppearanceUiDescription::m_shadingType("Shading Type", +// "Select volume shading style", +// "Select volume shading style", +// { "BRDF Only", "Phase Function Only", "Mixed" }); +// FloatSliderSpinnerUiInfo AppearanceUiDescription::m_densityScale("Scattering Density", +// "Set scattering density for volume", +// "Set scattering density for volume", +// 0.001f, +// 100.0f, +// 3, +// 0.01f, +// 10); +// FloatSliderSpinnerUiInfo AppearanceUiDescription::m_gradientFactor("Shading Type Mixture", +// "Mix between BRDF and Phase shading", +// "Mix between BRDF and Phase shading", +// 0.0f, +// 1.0f, +// 3, +// 0.01f, +// 10); +// FloatSliderSpinnerUiInfo AppearanceUiDescription::m_stepSizePrimaryRay("Primary Ray Step Size", +// "Set volume ray march step size for camera +// rays", "Set volume ray march step size for +// camera rays", 1.0f, 100.0f, 3, 0.01f, 10); +// FloatSliderSpinnerUiInfo AppearanceUiDescription::m_stepSizeSecondaryRay( +// "Secondary Ray Step Size", +// "Set volume ray march step size for scattered rays", +// "Set volume ray march step size for scattered rays", +// 1.0f, +// 100.0f, +// 3, +// 0.01f, +// 10); +// CheckBoxUiInfo AppearanceUiDescription::m_interpolate("Interpolate", +// "Interpolated volume sampling", +// "Interpolated volume sampling"); +// ColorPickerUiInfo AppearanceUiDescription::m_backgroundColor("Background Color", +// "Set background color", +// "Set background color"); +// CheckBoxUiInfo AppearanceUiDescription::m_showBoundingBox("Show Bounding Box", +// "Show/hide bounding box", +// "Show/hide bounding box"); +// ColorPickerUiInfo AppearanceUiDescription::m_boundingBoxColor("Bounding Box Color", +// "Set bounding box color", +// "Set bounding box color"); +// CheckBoxUiInfo AppearanceUiDescription::m_showScaleBar("Show Scale Bar", "Show/hide scale bar", "Show/hide scale +// bar"); + +AppearanceObject::AppearanceObject() + : prtyObject() +{ + m_RenderSettings = std::make_shared(); + m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, "Appearance", "Renderer Type"); + m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, "Appearance", "Shading Type"); + m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, "Appearance", "Density Scale"); + m_gradientFactor = + new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.GradientFactor, "Appearance", "Gradient Factor"); + m_stepSizePrimaryRay = + new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizePrimaryRay, "Appearance", "Step Size Primary Ray"); + m_stepSizeSecondaryRay = + new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizeSecondaryRay, "Appearance", "Step Size Secondary Ray"); + m_interpolate = new CheckBoxUiInfo(&m_appearanceDataObject.Interpolate, "Appearance", "Interpolate"); + m_backgroundColor = new ColorPickerUiInfo(&m_appearanceDataObject.BackgroundColor, "Appearance", "Background Color"); + m_showBoundingBox = new CheckBoxUiInfo(&m_appearanceDataObject.ShowBoundingBox, "Appearance", "Show Bounding Box"); + m_boundingBoxColor = + new ColorPickerUiInfo(&m_appearanceDataObject.BoundingBoxColor, "Appearance", "Bounding Box Color"); + m_showScaleBar = new CheckBoxUiInfo(&m_appearanceDataObject.ShowScaleBar, "Appearance", "Show Scale Bar"); +} + +void +AppearanceObject::updatePropsFromObject() +{ + if (m_renderSettings) { + m_appearanceDataObject.ShadingType.SetValue(m_renderSettings->m_RenderSettings.m_ShadingType); + m_appearanceDataObject.RendererType.SetValue(m_renderSettings->m_rendererType); + m_appearanceDataObject.DensityScale.SetValue(m_renderSettings->m_RenderSettings.m_DensityScale); + m_appearanceDataObject.GradientFactor.SetValue(m_renderSettings->m_RenderSettings.m_GradientFactor); + m_appearanceDataObject.StepSizePrimaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactor); + m_appearanceDataObject.StepSizeSecondaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); + m_appearanceDataObject.Interpolate.SetValue(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); + } + if (m_scene) { + BackgroundColor.SetValue(glm::vec4(m_scene->m_material.m_backgroundColor[0], + m_scene->m_material.m_backgroundColor[1], + m_scene->m_material.m_backgroundColor[2], + 1.0f)); + ShowBoundingBox.SetValue(m_scene->m_material.m_showBoundingBox); + BoundingBoxColor.SetValue(glm::vec4(m_scene->m_material.m_boundingBoxColor[0], + m_scene->m_material.m_boundingBoxColor[1], + m_scene->m_material.m_boundingBoxColor[2], + 1.0f)); + ShowScaleBar.SetValue(m_scene->m_showScaleBar); + } +} + +void +AppearanceObject::updateObjectFromProps() +{ + // update low-level object from properties + if (m_renderSettings) { + m_renderSettings->m_RenderSettings.m_ShadingType = m_appearanceDataObject.ShadingType.GetValue(); + m_renderSettings->m_rendererType = m_appearanceDataObject.RendererType.GetValue(); + m_renderSettings->m_RenderSettings.m_DensityScale = m_appearanceDataObject.DensityScale.GetValue(); + m_renderSettings->m_RenderSettings.m_GradientFactor = m_appearanceDataObject.GradientFactor.GetValue(); + m_renderSettings->m_RenderSettings.m_StepSizeFactor = m_appearanceDataObject.StepSizePrimaryRay.GetValue(); + m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = m_appearanceDataObject.StepSizeSecondaryRay.GetValue(); + m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = m_appearanceDataObject.Interpolate.GetValue(); + m_scene->m_material.m_backgroundColor[0] = m_appearanceDataObject.BackgroundColor.GetValue().x; + m_scene->m_material.m_backgroundColor[1] = m_appearanceDataObject.BackgroundColor.GetValue().y; + m_scene->m_material.m_backgroundColor[2] = m_appearanceDataObject.BackgroundColor.GetValue().z; + m_scene->m_material.m_showBoundingBox = m_appearanceDataObject.ShowBoundingBox.GetValue(); + m_scene->m_material.m_boundingBoxColor[0] = m_appearanceDataObject.BoundingBoxColor.GetValue().x; + m_scene->m_material.m_boundingBoxColor[1] = m_appearanceDataObject.BoundingBoxColor.GetValue().y; + m_scene->m_material.m_boundingBoxColor[2] = m_appearanceDataObject.BoundingBoxColor.GetValue().z; + m_scene->m_showScaleBar = m_appearanceDataObject.ShowScaleBar.GetValue(); + + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); + m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); + m_renderSettings->m_DirtyFlags.SetFlag(LightsDirty); + } +} \ No newline at end of file diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceUiDescription.hpp index c0169b70..831cb25a 100644 --- a/renderlib/AppearanceUiDescription.hpp +++ b/renderlib/AppearanceUiDescription.hpp @@ -2,7 +2,7 @@ #include "AppearanceDataObject.hpp" #include "core/prty/prtyObject.hpp" -#include "RenderPrefs.hpp" +#include "RenderSettings.h" #include "uiInfo.hpp" struct AppearanceUiDescription @@ -33,7 +33,7 @@ class AppearanceObject : public prtyObject AppearanceDataObject m_appearanceDataObject; // the actual camera - std::shared_ptr m_RenderPrefs; + std::shared_ptr m_renderSettings; // the ui info ComboBoxUiInfo* m_rendererType; diff --git a/renderlib/CameraDataObject.cpp b/renderlib/CameraDataObject.cpp index 01d77e0d..461b8a67 100644 --- a/renderlib/CameraDataObject.cpp +++ b/renderlib/CameraDataObject.cpp @@ -1,71 +1,3 @@ #include "CameraDataObject.hpp" #include "Logging.h" - -CameraDataObject::CameraDataObject(CCamera* camera) - : m_camera(camera) -{ - updatePropsFromCamera(); - // hook up properties to update the underlying camera - // Exposure.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // ExposureIterations.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // NoiseReduction.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // ApertureSize.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // FieldOfView.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); - // FocalDistance.addCallback([this](prtyProperty* p, bool fromUi) { - // if (fromUi) - // update(); - // }); -} - -void -CameraDataObject::updatePropsFromCamera() -{ - if (m_camera) { - Exposure.SetValue(1.0f - m_camera->m_Film.m_Exposure); - ExposureIterations.SetValue(m_camera->m_Film.m_ExposureIterations); - // TODO this is not hooked up to the camera properly - // NoiseReduction.SetValue(m_camera->m_Film.m_NoiseReduction); - ApertureSize.SetValue(m_camera->m_Aperture.m_Size); - FieldOfView.SetValue(m_camera->m_FovV); - FocalDistance.SetValue(m_camera->m_Focus.m_FocalDistance); - } -} -void -CameraDataObject::update() -{ - // update low-level camera object from properties - if (m_camera) { - m_camera->m_Film.m_Exposure = 1.0f - Exposure.GetValue(); - m_camera->m_Film.m_ExposureIterations = ExposureIterations.GetValue(); - - // Aperture - m_camera->m_Aperture.m_Size = ApertureSize.GetValue(); - - // Projection - m_camera->m_FovV = FieldOfView.GetValue(); - - // Focus - m_camera->m_Focus.m_FocalDistance = FocalDistance.GetValue(); - - m_camera->Update(); - - // renderer should pick this up and do the right thing (TM) - m_camera->m_Dirty = true; - } -} \ No newline at end of file diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index 31363078..a26c862c 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -3,17 +3,11 @@ #include "core/prty/prtyFloat.hpp" #include "core/prty/prtyInt8.hpp" #include "core/prty/prtyBoolean.hpp" -#include "CCamera.h" class CameraDataObject { public: - CameraDataObject() - : m_camera(nullptr) - { - // updatePropsFromCamera(); - } - CameraDataObject(CCamera* camera); + CameraDataObject() {} prtyFloat Exposure{ "Exposure", 0.75f }; prtyInt8 ExposureIterations{ "ExposureIterations", 1 }; @@ -21,10 +15,4 @@ class CameraDataObject prtyFloat ApertureSize{ "ApertureSize", 0.0f }; prtyFloat FieldOfView{ "FieldOfView", 30.0f }; prtyFloat FocalDistance{ "FocalDistance", 0.0f }; - - CCamera* m_camera; - -private: - void update(); - void updatePropsFromCamera(); }; diff --git a/renderlib/CameraUiDescription.cpp b/renderlib/CameraUiDescription.cpp index 92a4d34a..8faa0131 100644 --- a/renderlib/CameraUiDescription.cpp +++ b/renderlib/CameraUiDescription.cpp @@ -47,7 +47,7 @@ CameraObject::CameraObject() : prtyObject() { - m_Camera = std::make_shared(); + m_camera = std::make_shared(); m_ExposureUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.Exposure, "Camera", "Exposure"); m_ExposureIterationsUIInfo = new ComboBoxUiInfo(&m_cameraDataObject.ExposureIterations, "Camera", "Exposure Iterations"); @@ -56,3 +56,43 @@ CameraObject::CameraObject() m_FieldOfViewUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FieldOfView, "Camera", "Field of View"); m_FocalDistanceUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FocalDistance, "Camera", "Focal Distance"); } + +void +CameraObject::updatePropsFromObject() +{ + if (m_camera) { + m_cameraDataObject.Exposure.SetValue(1.0f - m_camera->m_Film.m_Exposure); + m_cameraDataObject.ExposureIterations.SetValue(m_camera->m_Film.m_ExposureIterations); + // TODO this is not hooked up to the camera properly + // m_cameraDataObject.NoiseReduction.SetValue(m_camera->m_Film.m_NoiseReduction); + m_cameraDataObject.ApertureSize.SetValue(m_camera->m_Aperture.m_Size); + m_cameraDataObject.FieldOfView.SetValue(m_camera->m_FovV); + m_cameraDataObject.FocalDistance.SetValue(m_camera->m_Focus.m_FocalDistance); + } +} +void +CameraObject::updateObjectFromProps() +{ + // update low-level camera object from properties + if (m_camera) { + m_camera->m_Film.m_Exposure = 1.0f - m_cameraDataObject.Exposure.GetValue(); + m_camera->m_Film.m_ExposureIterations = m_cameraDataObject.ExposureIterations.GetValue(); + + // Aperture + m_camera->m_Aperture.m_Size = m_cameraDataObject.ApertureSize.GetValue(); + + // Projection + m_camera->m_FovV = m_cameraDataObject.FieldOfView.GetValue(); + + // Focus + m_camera->m_Focus.m_FocalDistance = m_cameraDataObject.FocalDistance.GetValue(); + + m_camera->Update(); + + // TODO noise reduction!!! + + // TODO how can I hook this up automatically to the RenderSettings dirty flags? + // renderer should pick this up and do the right thing (TM) + m_camera->m_Dirty = true; + } +} \ No newline at end of file diff --git a/renderlib/CameraUiDescription.hpp b/renderlib/CameraUiDescription.hpp index f7b95716..945a2d40 100644 --- a/renderlib/CameraUiDescription.hpp +++ b/renderlib/CameraUiDescription.hpp @@ -3,6 +3,7 @@ #include "CameraDataObject.hpp" #include "uiInfo.hpp" #include "core/prty/prtyObject.hpp" +#include "CCamera.h" struct CameraUiDescription { @@ -27,7 +28,7 @@ class CameraObject : public prtyObject CameraDataObject m_cameraDataObject; // the actual camera - std::shared_ptr m_Camera; + std::shared_ptr m_camera; // the ui info FloatSliderSpinnerUiInfo* m_ExposureUIInfo; diff --git a/renderlib/core/prty/prtyPropertyUIInfo.hpp b/renderlib/core/prty/prtyPropertyUIInfo.hpp index 4a928bd1..5dd48ebd 100644 --- a/renderlib/core/prty/prtyPropertyUIInfo.hpp +++ b/renderlib/core/prty/prtyPropertyUIInfo.hpp @@ -6,10 +6,7 @@ ** ** \****************************************************************************/ -#ifdef PRTY_PROPERTYUIINFO_HPP -#error prtyPropertyUIInfo.hpp multiply included -#endif -#define PRTY_PROPERTYUIINFO_HPP +#pragma once #include #include From 58bbfcf75deeaa0714fef7bd638cdfdcabb3cc4e Mon Sep 17 00:00:00 2001 From: dmt Date: Sat, 21 Jun 2025 18:03:07 -0700 Subject: [PATCH 24/60] fix scene ref --- renderlib/AppearanceUiDescription.cpp | 43 ++++++++++++++------------- renderlib/AppearanceUiDescription.hpp | 4 ++- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/renderlib/AppearanceUiDescription.cpp b/renderlib/AppearanceUiDescription.cpp index ed1fc23e..7d4f1918 100644 --- a/renderlib/AppearanceUiDescription.cpp +++ b/renderlib/AppearanceUiDescription.cpp @@ -55,7 +55,7 @@ AppearanceObject::AppearanceObject() : prtyObject() { - m_RenderSettings = std::make_shared(); + m_renderSettings = std::make_shared(); m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, "Appearance", "Renderer Type"); m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, "Appearance", "Shading Type"); m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, "Appearance", "Density Scale"); @@ -85,17 +85,17 @@ AppearanceObject::updatePropsFromObject() m_appearanceDataObject.StepSizeSecondaryRay.SetValue(m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow); m_appearanceDataObject.Interpolate.SetValue(m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling); } - if (m_scene) { - BackgroundColor.SetValue(glm::vec4(m_scene->m_material.m_backgroundColor[0], - m_scene->m_material.m_backgroundColor[1], - m_scene->m_material.m_backgroundColor[2], - 1.0f)); - ShowBoundingBox.SetValue(m_scene->m_material.m_showBoundingBox); - BoundingBoxColor.SetValue(glm::vec4(m_scene->m_material.m_boundingBoxColor[0], - m_scene->m_material.m_boundingBoxColor[1], - m_scene->m_material.m_boundingBoxColor[2], - 1.0f)); - ShowScaleBar.SetValue(m_scene->m_showScaleBar); + if (auto scene = m_scene.lock()) { + m_appearanceDataObject.BackgroundColor.SetValue(glm::vec4(scene->m_material.m_backgroundColor[0], + scene->m_material.m_backgroundColor[1], + scene->m_material.m_backgroundColor[2], + 1.0f)); + m_appearanceDataObject.ShowBoundingBox.SetValue(scene->m_material.m_showBoundingBox); + m_appearanceDataObject.BoundingBoxColor.SetValue(glm::vec4(scene->m_material.m_boundingBoxColor[0], + scene->m_material.m_boundingBoxColor[1], + scene->m_material.m_boundingBoxColor[2], + 1.0f)); + m_appearanceDataObject.ShowScaleBar.SetValue(scene->m_showScaleBar); } } @@ -111,15 +111,16 @@ AppearanceObject::updateObjectFromProps() m_renderSettings->m_RenderSettings.m_StepSizeFactor = m_appearanceDataObject.StepSizePrimaryRay.GetValue(); m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = m_appearanceDataObject.StepSizeSecondaryRay.GetValue(); m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = m_appearanceDataObject.Interpolate.GetValue(); - m_scene->m_material.m_backgroundColor[0] = m_appearanceDataObject.BackgroundColor.GetValue().x; - m_scene->m_material.m_backgroundColor[1] = m_appearanceDataObject.BackgroundColor.GetValue().y; - m_scene->m_material.m_backgroundColor[2] = m_appearanceDataObject.BackgroundColor.GetValue().z; - m_scene->m_material.m_showBoundingBox = m_appearanceDataObject.ShowBoundingBox.GetValue(); - m_scene->m_material.m_boundingBoxColor[0] = m_appearanceDataObject.BoundingBoxColor.GetValue().x; - m_scene->m_material.m_boundingBoxColor[1] = m_appearanceDataObject.BoundingBoxColor.GetValue().y; - m_scene->m_material.m_boundingBoxColor[2] = m_appearanceDataObject.BoundingBoxColor.GetValue().z; - m_scene->m_showScaleBar = m_appearanceDataObject.ShowScaleBar.GetValue(); - + if (auto scene = m_scene.lock()) { + scene->m_material.m_backgroundColor[0] = m_appearanceDataObject.BackgroundColor.GetValue().x; + scene->m_material.m_backgroundColor[1] = m_appearanceDataObject.BackgroundColor.GetValue().y; + scene->m_material.m_backgroundColor[2] = m_appearanceDataObject.BackgroundColor.GetValue().z; + scene->m_material.m_showBoundingBox = m_appearanceDataObject.ShowBoundingBox.GetValue(); + scene->m_material.m_boundingBoxColor[0] = m_appearanceDataObject.BoundingBoxColor.GetValue().x; + scene->m_material.m_boundingBoxColor[1] = m_appearanceDataObject.BoundingBoxColor.GetValue().y; + scene->m_material.m_boundingBoxColor[2] = m_appearanceDataObject.BoundingBoxColor.GetValue().z; + scene->m_showScaleBar = m_appearanceDataObject.ShowScaleBar.GetValue(); + } m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); m_renderSettings->m_DirtyFlags.SetFlag(LightsDirty); diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceUiDescription.hpp index 831cb25a..8099f0da 100644 --- a/renderlib/AppearanceUiDescription.hpp +++ b/renderlib/AppearanceUiDescription.hpp @@ -3,6 +3,7 @@ #include "AppearanceDataObject.hpp" #include "core/prty/prtyObject.hpp" #include "RenderSettings.h" +#include "AppScene.h" #include "uiInfo.hpp" struct AppearanceUiDescription @@ -32,8 +33,9 @@ class AppearanceObject : public prtyObject // the properties AppearanceDataObject m_appearanceDataObject; - // the actual camera + // the actual settings std::shared_ptr m_renderSettings; + std::weak_ptr m_scene; // the ui info ComboBoxUiInfo* m_rendererType; From f5526f9f2a3ad97760aec2023d93a199cbeb52d9 Mon Sep 17 00:00:00 2001 From: dmt Date: Sat, 21 Jun 2025 22:35:20 -0700 Subject: [PATCH 25/60] fix test, add callbacks --- renderlib/AppearanceUiDescription.cpp | 115 +++++++++++++++++++++++++- renderlib/AppearanceUiDescription.hpp | 12 +++ renderlib/CameraUiDescription.cpp | 53 +++++++++++- renderlib/CameraUiDescription.hpp | 7 ++ test/test_prty.cpp | 2 - 5 files changed, 185 insertions(+), 4 deletions(-) diff --git a/renderlib/AppearanceUiDescription.cpp b/renderlib/AppearanceUiDescription.cpp index 7d4f1918..0b31b872 100644 --- a/renderlib/AppearanceUiDescription.cpp +++ b/renderlib/AppearanceUiDescription.cpp @@ -1,5 +1,6 @@ #include "AppearanceUiDescription.hpp" +#include "Logging.h" // ComboBoxUiInfo AppearanceUiDescription::m_rendererType("Renderer Type", // "Select volume rendering type", // "Select volume rendering type", @@ -57,20 +58,54 @@ AppearanceObject::AppearanceObject() { m_renderSettings = std::make_shared(); m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, "Appearance", "Renderer Type"); + AddProperty(m_rendererType); m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, "Appearance", "Shading Type"); + AddProperty(m_shadingType); m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, "Appearance", "Density Scale"); + AddProperty(m_densityScale); m_gradientFactor = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.GradientFactor, "Appearance", "Gradient Factor"); + AddProperty(m_gradientFactor); m_stepSizePrimaryRay = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizePrimaryRay, "Appearance", "Step Size Primary Ray"); + AddProperty(m_stepSizePrimaryRay); m_stepSizeSecondaryRay = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizeSecondaryRay, "Appearance", "Step Size Secondary Ray"); + AddProperty(m_stepSizeSecondaryRay); m_interpolate = new CheckBoxUiInfo(&m_appearanceDataObject.Interpolate, "Appearance", "Interpolate"); + AddProperty(m_interpolate); m_backgroundColor = new ColorPickerUiInfo(&m_appearanceDataObject.BackgroundColor, "Appearance", "Background Color"); + AddProperty(m_backgroundColor); m_showBoundingBox = new CheckBoxUiInfo(&m_appearanceDataObject.ShowBoundingBox, "Appearance", "Show Bounding Box"); + AddProperty(m_showBoundingBox); m_boundingBoxColor = new ColorPickerUiInfo(&m_appearanceDataObject.BoundingBoxColor, "Appearance", "Bounding Box Color"); + AddProperty(m_boundingBoxColor); m_showScaleBar = new CheckBoxUiInfo(&m_appearanceDataObject.ShowScaleBar, "Appearance", "Show Scale Bar"); + AddProperty(m_showScaleBar); + + m_appearanceDataObject.RendererType.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::RendererTypeChanged)); + m_appearanceDataObject.ShadingType.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::ShadingTypeChanged)); + m_appearanceDataObject.DensityScale.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::DensityScaleChanged)); + m_appearanceDataObject.GradientFactor.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::GradientFactorChanged)); + m_appearanceDataObject.StepSizePrimaryRay.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::StepSizePrimaryRayChanged)); + m_appearanceDataObject.StepSizeSecondaryRay.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::StepSizeSecondaryRayChanged)); + m_appearanceDataObject.Interpolate.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::InterpolateChanged)); + m_appearanceDataObject.BackgroundColor.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::BackgroundColorChanged)); + m_appearanceDataObject.ShowBoundingBox.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::ShowBoundingBoxChanged)); + m_appearanceDataObject.BoundingBoxColor.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::BoundingBoxColorChanged)); + m_appearanceDataObject.ShowScaleBar.AddCallback( + new prtyCallbackWrapper(this, &AppearanceObject::ShowScaleBarChanged)); } void @@ -125,4 +160,82 @@ AppearanceObject::updateObjectFromProps() m_renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); m_renderSettings->m_DirtyFlags.SetFlag(LightsDirty); } -} \ No newline at end of file +} + +void +AppearanceObject::RendererTypeChanged(prtyProperty* i_Property, bool i_bDirty) +{ + LOG_ERROR << "Renderer type changed, but not implemented yet!"; +} +void +AppearanceObject::ShadingTypeChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_renderSettings->m_RenderSettings.m_ShadingType = m_appearanceDataObject.ShadingType.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); +} +void +AppearanceObject::DensityScaleChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_renderSettings->m_RenderSettings.m_DensityScale = m_appearanceDataObject.DensityScale.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); +} +void +AppearanceObject::GradientFactorChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_renderSettings->m_RenderSettings.m_GradientFactor = m_appearanceDataObject.GradientFactor.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); +} +void +AppearanceObject::StepSizePrimaryRayChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_renderSettings->m_RenderSettings.m_StepSizeFactor = m_appearanceDataObject.StepSizePrimaryRay.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); +} +void +AppearanceObject::StepSizeSecondaryRayChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_renderSettings->m_RenderSettings.m_StepSizeFactorShadow = m_appearanceDataObject.StepSizeSecondaryRay.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); +} +void +AppearanceObject::InterpolateChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_renderSettings->m_RenderSettings.m_InterpolatedVolumeSampling = m_appearanceDataObject.Interpolate.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); +} +void +AppearanceObject::BackgroundColorChanged(prtyProperty* i_Property, bool i_bDirty) +{ + if (auto scene = m_scene.lock()) { + scene->m_material.m_backgroundColor[0] = m_appearanceDataObject.BackgroundColor.GetValue().x; + scene->m_material.m_backgroundColor[1] = m_appearanceDataObject.BackgroundColor.GetValue().y; + scene->m_material.m_backgroundColor[2] = m_appearanceDataObject.BackgroundColor.GetValue().z; + m_renderSettings->m_DirtyFlags.SetFlag(EnvironmentDirty); + } +} +void +AppearanceObject::ShowBoundingBoxChanged(prtyProperty* i_Property, bool i_bDirty) +{ + if (auto scene = m_scene.lock()) { + scene->m_material.m_showBoundingBox = m_appearanceDataObject.ShowBoundingBox.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(EnvironmentDirty); + } +} +void +AppearanceObject::BoundingBoxColorChanged(prtyProperty* i_Property, bool i_bDirty) +{ + if (auto scene = m_scene.lock()) { + scene->m_material.m_boundingBoxColor[0] = m_appearanceDataObject.BoundingBoxColor.GetValue().x; + scene->m_material.m_boundingBoxColor[1] = m_appearanceDataObject.BoundingBoxColor.GetValue().y; + scene->m_material.m_boundingBoxColor[2] = m_appearanceDataObject.BoundingBoxColor.GetValue().z; + m_renderSettings->m_DirtyFlags.SetFlag(EnvironmentDirty); + } +} +void +AppearanceObject::ShowScaleBarChanged(prtyProperty* i_Property, bool i_bDirty) +{ + if (auto scene = m_scene.lock()) { + scene->m_showScaleBar = m_appearanceDataObject.ShowScaleBar.GetValue(); + m_renderSettings->m_DirtyFlags.SetFlag(EnvironmentDirty); + } +} diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceUiDescription.hpp index 8099f0da..8b9ef1a2 100644 --- a/renderlib/AppearanceUiDescription.hpp +++ b/renderlib/AppearanceUiDescription.hpp @@ -49,4 +49,16 @@ class AppearanceObject : public prtyObject CheckBoxUiInfo* m_showBoundingBox; ColorPickerUiInfo* m_boundingBoxColor; CheckBoxUiInfo* m_showScaleBar; + + void RendererTypeChanged(prtyProperty* i_Property, bool i_bDirty); + void ShadingTypeChanged(prtyProperty* i_Property, bool i_bDirty); + void DensityScaleChanged(prtyProperty* i_Property, bool i_bDirty); + void GradientFactorChanged(prtyProperty* i_Property, bool i_bDirty); + void StepSizePrimaryRayChanged(prtyProperty* i_Property, bool i_bDirty); + void StepSizeSecondaryRayChanged(prtyProperty* i_Property, bool i_bDirty); + void InterpolateChanged(prtyProperty* i_Property, bool i_bDirty); + void BackgroundColorChanged(prtyProperty* i_Property, bool i_bDirty); + void ShowBoundingBoxChanged(prtyProperty* i_Property, bool i_bDirty); + void BoundingBoxColorChanged(prtyProperty* i_Property, bool i_bDirty); + void ShowScaleBarChanged(prtyProperty* i_Property, bool i_bDirty); }; diff --git a/renderlib/CameraUiDescription.cpp b/renderlib/CameraUiDescription.cpp index 8faa0131..a7f932bb 100644 --- a/renderlib/CameraUiDescription.cpp +++ b/renderlib/CameraUiDescription.cpp @@ -1,5 +1,7 @@ #include "CameraUiDescription.hpp" +#include "Logging.h" + // FloatSliderSpinnerUiInfo CameraUiDescription::m_exposure("Exposure", // "Set Exposure", // "Set camera exposure", @@ -49,12 +51,30 @@ CameraObject::CameraObject() { m_camera = std::make_shared(); m_ExposureUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.Exposure, "Camera", "Exposure"); + AddProperty(m_ExposureUIInfo); m_ExposureIterationsUIInfo = new ComboBoxUiInfo(&m_cameraDataObject.ExposureIterations, "Camera", "Exposure Iterations"); + AddProperty(m_ExposureIterationsUIInfo); m_NoiseReductionUIInfo = new CheckBoxUiInfo(&m_cameraDataObject.NoiseReduction, "Camera", "Noise Reduction"); + AddProperty(m_NoiseReductionUIInfo); m_ApertureSizeUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.ApertureSize, "Camera", "Aperture Size"); + AddProperty(m_ApertureSizeUIInfo); m_FieldOfViewUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FieldOfView, "Camera", "Field of View"); + AddProperty(m_FieldOfViewUIInfo); m_FocalDistanceUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FocalDistance, "Camera", "Focal Distance"); + AddProperty(m_FocalDistanceUIInfo); + + m_cameraDataObject.Exposure.AddCallback(new prtyCallbackWrapper(this, &CameraObject::ExposureChanged)); + m_cameraDataObject.ExposureIterations.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::ExposureIterationsChanged)); + m_cameraDataObject.NoiseReduction.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::NoiseReductionChanged)); + m_cameraDataObject.ApertureSize.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::ApertureSizeChanged)); + m_cameraDataObject.FieldOfView.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::FieldOfViewChanged)); + m_cameraDataObject.FocalDistance.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::FocalDistanceChanged)); } void @@ -95,4 +115,35 @@ CameraObject::updateObjectFromProps() // renderer should pick this up and do the right thing (TM) m_camera->m_Dirty = true; } -} \ No newline at end of file +} + +void +CameraObject::ExposureChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_camera->m_Film.m_Exposure = 1.0f - m_cameraDataObject.Exposure.GetValue(); +} +void +CameraObject::ExposureIterationsChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_camera->m_Film.m_ExposureIterations = m_cameraDataObject.ExposureIterations.GetValue(); +} +void +CameraObject::NoiseReductionChanged(prtyProperty* i_Property, bool i_bDirty) +{ + LOG_ERROR << "Noise reduction is not implemented yet!"; +} +void +CameraObject::ApertureSizeChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_camera->m_Aperture.m_Size = m_cameraDataObject.ApertureSize.GetValue(); +} +void +CameraObject::FieldOfViewChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_camera->m_FovV = m_cameraDataObject.FieldOfView.GetValue(); +} +void +CameraObject::FocalDistanceChanged(prtyProperty* i_Property, bool i_bDirty) +{ + m_camera->m_Focus.m_FocalDistance = m_cameraDataObject.FocalDistance.GetValue(); +} diff --git a/renderlib/CameraUiDescription.hpp b/renderlib/CameraUiDescription.hpp index 945a2d40..9d508a98 100644 --- a/renderlib/CameraUiDescription.hpp +++ b/renderlib/CameraUiDescription.hpp @@ -37,4 +37,11 @@ class CameraObject : public prtyObject FloatSliderSpinnerUiInfo* m_ApertureSizeUIInfo; FloatSliderSpinnerUiInfo* m_FieldOfViewUIInfo; FloatSliderSpinnerUiInfo* m_FocalDistanceUIInfo; + + void ExposureChanged(prtyProperty* i_Property, bool i_bDirty); + void ExposureIterationsChanged(prtyProperty* i_Property, bool i_bDirty); + void NoiseReductionChanged(prtyProperty* i_Property, bool i_bDirty); + void ApertureSizeChanged(prtyProperty* i_Property, bool i_bDirty); + void FieldOfViewChanged(prtyProperty* i_Property, bool i_bDirty); + void FocalDistanceChanged(prtyProperty* i_Property, bool i_bDirty); }; diff --git a/test/test_prty.cpp b/test/test_prty.cpp index 2e3ce8b2..63d0f3b6 100644 --- a/test/test_prty.cpp +++ b/test/test_prty.cpp @@ -20,13 +20,11 @@ TEST_CASE("prtyProperty", "[prtyProperty]") REQUIRE(p.GetValue() == 42); REQUIRE(p == 42); REQUIRE(p.GetPropertyName() == "int"); - REQUIRE(p.GetType() == "int8_t"); REQUIRE(p != 43); prtyText p2("string", "hello"); REQUIRE(p2.GetValue() == "hello"); REQUIRE(p2.GetPropertyName() == "string"); - REQUIRE(p2.GetType() == "std::string"); REQUIRE(p2 == "hello"); REQUIRE(p2 != "world"); p2.SetValue("world"); From 5064ebe77f4d4a62f02b80f49e0490671d40881e Mon Sep 17 00:00:00 2001 From: DMT Date: Sun, 22 Jun 2025 19:59:30 -0700 Subject: [PATCH 26/60] wip --- agave_app/GLView3D.cpp | 8 ++++---- agave_app/GLView3D.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index ff296918..2fadf7c1 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -3,8 +3,8 @@ #include "QRenderSettings.h" #include "ViewerState.h" -#include "renderlib/AppearanceDataObject.hpp" -#include "renderlib/CameraDataObject.hpp" +#include "renderlib/AppearanceUiDescription.hpp" +#include "renderlib/CameraUiDescription.hpp" #include "renderlib/ImageXYZC.h" #include "renderlib/Logging.h" #include "renderlib/MoveTool.h" @@ -43,8 +43,8 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidg m_viewerWindow->gesture.input.setDoubleClickTime((double)QApplication::doubleClickInterval() / 1000.0); // camera is created deep down inside m_viewerWindow. - m_cameraDataObject = new CameraDataObject(&m_viewerWindow->m_CCamera); - m_appearanceDataObject = new AppearanceDataObject(rs, scene); + m_cameraDataObject = new CameraObject(&m_viewerWindow->m_CCamera); + m_appearanceDataObject = new AppearanceObject(rs, scene); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index fd665452..e3cb225e 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -12,8 +12,8 @@ #include #include -class AppearanceDataObject; -class CameraDataObject; +class AppearanceObject; +class CameraObject; class CStatus; class ImageXYZC; class IRenderWindow; @@ -112,8 +112,8 @@ public slots: void wheelEvent(QWheelEvent* event); private: - CameraDataObject* m_cameraDataObject; - AppearanceDataObject* m_appearanceDataObject; + CameraObject* m_cameraDataObject; + AppearanceObject* m_appearanceDataObject; QRenderSettings* m_qrendersettings; /// Rendering timer. From 7eec5ddeb04e7e2df39b012cae4c503b14880538 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 25 Jun 2025 14:49:17 -0700 Subject: [PATCH 27/60] add status tip and tooltip --- renderlib/core/prty/prtyObject.hpp | 1 + renderlib/core/prty/prtyPropertyUIInfo.cpp | 33 ++++++++++++++++++++++ renderlib/core/prty/prtyPropertyUIInfo.hpp | 8 ++++++ 3 files changed, 42 insertions(+) diff --git a/renderlib/core/prty/prtyObject.hpp b/renderlib/core/prty/prtyObject.hpp index 0257919f..e27732f2 100644 --- a/renderlib/core/prty/prtyObject.hpp +++ b/renderlib/core/prty/prtyObject.hpp @@ -6,6 +6,7 @@ ** ** \****************************************************************************/ +#pragma once #ifdef PRTY_OBJECT_HPP #error prtyObject.hpp multiply included #endif diff --git a/renderlib/core/prty/prtyPropertyUIInfo.cpp b/renderlib/core/prty/prtyPropertyUIInfo.cpp index 111d76bd..c8744484 100644 --- a/renderlib/core/prty/prtyPropertyUIInfo.cpp +++ b/renderlib/core/prty/prtyPropertyUIInfo.cpp @@ -204,3 +204,36 @@ prtyPropertyUIInfo::SetControlName(const std::string i_ControlName) { m_ControlName = i_ControlName; } + +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetStatusTip(const std::string& i_StatusTip) +{ + m_StatusTip = i_StatusTip; +} +const std::string& +prtyPropertyUIInfo::GetStatusTip() const +{ + if (m_StatusTip.empty()) { + // If no status tip is set, use the description as a fallback + return m_Description; + } + return m_StatusTip; +} +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +void +prtyPropertyUIInfo::SetToolTip(const std::string& i_ToolTip) +{ + m_ToolTip = i_ToolTip; +} +const std::string& +prtyPropertyUIInfo::GetToolTip() const +{ + if (m_ToolTip.empty()) { + // If no tooltip is set, use the description as a fallback + return m_Description; + } + return m_ToolTip; +} \ No newline at end of file diff --git a/renderlib/core/prty/prtyPropertyUIInfo.hpp b/renderlib/core/prty/prtyPropertyUIInfo.hpp index 5dd48ebd..ae3cab43 100644 --- a/renderlib/core/prty/prtyPropertyUIInfo.hpp +++ b/renderlib/core/prty/prtyPropertyUIInfo.hpp @@ -117,6 +117,11 @@ class prtyPropertyUIInfo //-------------------------------------------------------------------- void UpdateControl(); + void SetStatusTip(const std::string& i_StatusTip); + const std::string& GetStatusTip() const; + void SetToolTip(const std::string& i_ToolTip); + const std::string& GetToolTip() const; + protected: //-------------------------------------------------------------------- //-------------------------------------------------------------------- @@ -131,4 +136,7 @@ class prtyPropertyUIInfo std::string m_Description; bool m_bReadOnly; std::string m_ConfirmationString; + + std::string m_StatusTip; + std::string m_ToolTip; }; From bd5b1a60f6fb0ecfc0c552c75a1460c07c9313ac Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 25 Jun 2025 14:49:52 -0700 Subject: [PATCH 28/60] add simple getters for now (todo: iterate more generically factory-style) --- renderlib/AppearanceUiDescription.hpp | 17 +++++++++++++++++ renderlib/CameraUiDescription.hpp | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceUiDescription.hpp index 8b9ef1a2..c5173dfa 100644 --- a/renderlib/AppearanceUiDescription.hpp +++ b/renderlib/AppearanceUiDescription.hpp @@ -29,6 +29,23 @@ class AppearanceObject : public prtyObject void updatePropsFromObject(); void updateObjectFromProps(); + // Getter for appearance data object + // AppearanceDataObject& getAppearanceDataObject() { return m_appearanceDataObject; } + const AppearanceDataObject& getAppearanceDataObject() const { return m_appearanceDataObject; } + + // Getters for UI info objects + ComboBoxUiInfo* getRendererTypeUiInfo() { return m_rendererType; } + ComboBoxUiInfo* getShadingTypeUiInfo() { return m_shadingType; } + FloatSliderSpinnerUiInfo* getDensityScaleUiInfo() { return m_densityScale; } + FloatSliderSpinnerUiInfo* getGradientFactorUiInfo() { return m_gradientFactor; } + FloatSliderSpinnerUiInfo* getStepSizePrimaryRayUiInfo() { return m_stepSizePrimaryRay; } + FloatSliderSpinnerUiInfo* getStepSizeSecondaryRayUiInfo() { return m_stepSizeSecondaryRay; } + CheckBoxUiInfo* getInterpolateUiInfo() { return m_interpolate; } + ColorPickerUiInfo* getBackgroundColorUiInfo() { return m_backgroundColor; } + CheckBoxUiInfo* getShowBoundingBoxUiInfo() { return m_showBoundingBox; } + ColorPickerUiInfo* getBoundingBoxColorUiInfo() { return m_boundingBoxColor; } + CheckBoxUiInfo* getShowScaleBarUiInfo() { return m_showScaleBar; } + private: // the properties AppearanceDataObject m_appearanceDataObject; diff --git a/renderlib/CameraUiDescription.hpp b/renderlib/CameraUiDescription.hpp index 9d508a98..e34a16b1 100644 --- a/renderlib/CameraUiDescription.hpp +++ b/renderlib/CameraUiDescription.hpp @@ -23,6 +23,18 @@ class CameraObject : public prtyObject void updatePropsFromObject(); void updateObjectFromProps(); + // Getter for camera data object + // CameraDataObject& getCameraDataObject() { return m_cameraDataObject; } + const CameraDataObject& getCameraDataObject() const { return m_cameraDataObject; } + + // Getters for UI info objects + FloatSliderSpinnerUiInfo* getExposureUIInfo() { return m_ExposureUIInfo; } + ComboBoxUiInfo* getExposureIterationsUIInfo() { return m_ExposureIterationsUIInfo; } + CheckBoxUiInfo* getNoiseReductionUIInfo() { return m_NoiseReductionUIInfo; } + FloatSliderSpinnerUiInfo* getApertureSizeUIInfo() { return m_ApertureSizeUIInfo; } + FloatSliderSpinnerUiInfo* getFieldOfViewUIInfo() { return m_FieldOfViewUIInfo; } + FloatSliderSpinnerUiInfo* getFocalDistanceUIInfo() { return m_FocalDistanceUIInfo; } + private: // the properties CameraDataObject m_cameraDataObject; From b01e7036448c69df9c7717e788c9ae0dc9ac25d0 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 25 Jun 2025 14:51:41 -0700 Subject: [PATCH 29/60] camera and appearance compiles but completely detached from the renderer --- agave_app/AppearanceDockWidget2.cpp | 2 +- agave_app/AppearanceDockWidget2.h | 2 +- agave_app/AppearanceWidget.cpp | 34 ++--- agave_app/AppearanceWidget.h | 6 +- agave_app/CameraDockWidget.cpp | 2 +- agave_app/CameraDockWidget.h | 5 +- agave_app/CameraWidget.cpp | 167 ++---------------------- agave_app/CameraWidget.h | 9 +- agave_app/GLView3D.cpp | 11 +- agave_app/GLView3D.h | 4 +- agave_app/agaveGui.cpp | 14 +- agave_app/agaveGui.h | 6 +- agave_app/qtControls/controlFactory.cpp | 51 ++++---- agave_app/qtControls/controlFactory.h | 10 +- 14 files changed, 81 insertions(+), 242 deletions(-) diff --git a/agave_app/AppearanceDockWidget2.cpp b/agave_app/AppearanceDockWidget2.cpp index 1b5403f3..1c25f68c 100644 --- a/agave_app/AppearanceDockWidget2.cpp +++ b/agave_app/AppearanceDockWidget2.cpp @@ -3,7 +3,7 @@ QAppearanceDockWidget2::QAppearanceDockWidget2(QWidget* pParent, RenderSettings* rs, ViewerWindow* vw, - AppearanceDataObject* ado) + AppearanceObject* ado) : QDockWidget(pParent) , m_AppearanceWidget(nullptr, rs, vw, ado) { diff --git a/agave_app/AppearanceDockWidget2.h b/agave_app/AppearanceDockWidget2.h index 1ca4653f..babb984e 100644 --- a/agave_app/AppearanceDockWidget2.h +++ b/agave_app/AppearanceDockWidget2.h @@ -12,7 +12,7 @@ class QAppearanceDockWidget2 : public QDockWidget QAppearanceDockWidget2(QWidget* pParent = NULL, RenderSettings* rs = NULL, ViewerWindow* vw = NULL, - AppearanceDataObject* cdo = NULL); + AppearanceObject* cdo = NULL); private: QAppearanceWidget2 m_AppearanceWidget; diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index 59033ccf..b0d48002 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -9,10 +9,7 @@ #include -QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, - RenderSettings* rs, - ViewerWindow* vw, - AppearanceDataObject* cdo) +QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, RenderSettings* rs, ViewerWindow* vw, AppearanceObject* cdo) : QWidget(pParent) , m_MainLayout() , m_renderSettings(rs) @@ -21,34 +18,27 @@ QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, Controls::initFormLayout(m_MainLayout); setLayout(&m_MainLayout); - QComboBox* rendererType = addRow(AppearanceUiDescription::m_rendererType, &m_appearanceDataObject->RendererType); + QComboBox* rendererType = addRow(*m_appearanceDataObject->getRendererTypeUiInfo()); m_MainLayout.addRow("Renderer", rendererType); - QComboBox* shadingType = addRow(AppearanceUiDescription::m_shadingType, &m_appearanceDataObject->ShadingType); + QComboBox* shadingType = addRow(*m_appearanceDataObject->getShadingTypeUiInfo()); m_MainLayout.addRow("Shading Type", shadingType); - QNumericSlider* densityScale = addRow(AppearanceUiDescription::m_densityScale, &m_appearanceDataObject->DensityScale); + QNumericSlider* densityScale = addRow(*m_appearanceDataObject->getDensityScaleUiInfo()); m_MainLayout.addRow("Scattering Density", densityScale); - QNumericSlider* gradientFactor = - addRow(AppearanceUiDescription::m_gradientFactor, &m_appearanceDataObject->GradientFactor); + QNumericSlider* gradientFactor = addRow(*m_appearanceDataObject->getGradientFactorUiInfo()); m_MainLayout.addRow("Shading Type Mixture", gradientFactor); - QNumericSlider* stepSizePrimaryRay = - addRow(AppearanceUiDescription::m_stepSizePrimaryRay, &m_appearanceDataObject->StepSizePrimaryRay); + QNumericSlider* stepSizePrimaryRay = addRow(*m_appearanceDataObject->getStepSizePrimaryRayUiInfo()); m_MainLayout.addRow("Step Size Primary Ray", stepSizePrimaryRay); - QNumericSlider* stepSizeSecondaryRay = - addRow(AppearanceUiDescription::m_stepSizeSecondaryRay, &m_appearanceDataObject->StepSizeSecondaryRay); + QNumericSlider* stepSizeSecondaryRay = addRow(*m_appearanceDataObject->getStepSizeSecondaryRayUiInfo()); m_MainLayout.addRow("Step Size Secondary Ray", stepSizeSecondaryRay); - QCheckBox* interpolateCheckBox = addRow(AppearanceUiDescription::m_interpolate, &m_appearanceDataObject->Interpolate); + QCheckBox* interpolateCheckBox = addRow(*m_appearanceDataObject->getInterpolateUiInfo()); m_MainLayout.addRow("Interpolate", interpolateCheckBox); - QColorPushButton* backgroundColorButton = - addRow(AppearanceUiDescription::m_backgroundColor, &m_appearanceDataObject->BackgroundColor); + QColorPushButton* backgroundColorButton = addRow(*m_appearanceDataObject->getBackgroundColorUiInfo()); m_MainLayout.addRow("Background Color", backgroundColorButton); - QCheckBox* showBoundingBoxCheckBox = - addRow(AppearanceUiDescription::m_showBoundingBox, &m_appearanceDataObject->ShowBoundingBox); + QCheckBox* showBoundingBoxCheckBox = addRow(*m_appearanceDataObject->getShowBoundingBoxUiInfo()); m_MainLayout.addRow("Show Bounding Box", showBoundingBoxCheckBox); - QColorPushButton* boundingBoxColorButton = - addRow(AppearanceUiDescription::m_boundingBoxColor, &m_appearanceDataObject->BoundingBoxColor); + QColorPushButton* boundingBoxColorButton = addRow(*m_appearanceDataObject->getBoundingBoxColorUiInfo()); m_MainLayout.addRow("Bounding Box Color", boundingBoxColorButton); - QCheckBox* showScaleBarCheckBox = - addRow(AppearanceUiDescription::m_showScaleBar, &m_appearanceDataObject->ShowScaleBar); + QCheckBox* showScaleBarCheckBox = addRow(*m_appearanceDataObject->getShowScaleBarUiInfo()); m_MainLayout.addRow("Show Scale Bar", showScaleBarCheckBox); QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, vw](int index) { vw->setRenderer(index); }); diff --git a/agave_app/AppearanceWidget.h b/agave_app/AppearanceWidget.h index 4ef78ab5..c059424b 100644 --- a/agave_app/AppearanceWidget.h +++ b/agave_app/AppearanceWidget.h @@ -3,7 +3,7 @@ #include "qtControls/Controls.h" // #include "renderlib/core/prty/prtyProperty.h" -#include "renderlib/AppearanceDataObject.hpp" +#include "renderlib/AppearanceUiDescription.hpp" #include "renderlib/Logging.h" #include @@ -22,7 +22,7 @@ class QAppearanceWidget2 : public QWidget QAppearanceWidget2(QWidget* pParent = NULL, RenderSettings* rs = nullptr, ViewerWindow* vw = nullptr, - AppearanceDataObject* cdo = nullptr); + AppearanceObject* cdo = nullptr); virtual QSize sizeHint() const; @@ -32,5 +32,5 @@ class QAppearanceWidget2 : public QWidget RenderSettings* m_renderSettings; private: - AppearanceDataObject* m_appearanceDataObject; + AppearanceObject* m_appearanceDataObject; }; diff --git a/agave_app/CameraDockWidget.cpp b/agave_app/CameraDockWidget.cpp index 5e213175..28a7eb77 100644 --- a/agave_app/CameraDockWidget.cpp +++ b/agave_app/CameraDockWidget.cpp @@ -1,6 +1,6 @@ #include "CameraDockWidget.h" -QCameraDockWidget::QCameraDockWidget(QWidget* pParent, QCamera* cam, RenderSettings* rs, CameraDataObject* cdo) +QCameraDockWidget::QCameraDockWidget(QWidget* pParent, RenderSettings* rs, CameraObject* cdo) : QDockWidget(pParent) , m_CameraWidget(nullptr, cam, rs, cdo) { diff --git a/agave_app/CameraDockWidget.h b/agave_app/CameraDockWidget.h index e2ac83fe..debb462f 100644 --- a/agave_app/CameraDockWidget.h +++ b/agave_app/CameraDockWidget.h @@ -9,10 +9,7 @@ class QCameraDockWidget : public QDockWidget Q_OBJECT public: - QCameraDockWidget(QWidget* pParent = NULL, - QCamera* cam = NULL, - RenderSettings* rs = NULL, - CameraDataObject* cdo = NULL); + QCameraDockWidget(QWidget* pParent = NULL, RenderSettings* rs = NULL, CameraObject* cdo = NULL); private: QCameraWidget m_CameraWidget; diff --git a/agave_app/CameraWidget.cpp b/agave_app/CameraWidget.cpp index cb382834..2c087dbb 100644 --- a/agave_app/CameraWidget.cpp +++ b/agave_app/CameraWidget.cpp @@ -5,177 +5,26 @@ #include -QNumericSlider* -create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr> prop) -{ - QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info->statusTip)); - slider->setToolTip(QString::fromStdString(info->toolTip)); - slider->setRange(info->min, info->max); - slider->setDecimals(info->decimals); - slider->setSingleStep(info->singleStep); - slider->setNumTickMarks(info->numTickMarks); - slider->setSuffix(QString::fromStdString(info->suffix)); - - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); - // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); - - return slider; -} -QNumericSlider* -create(const IntSliderSpinnerUiInfo* info, std::shared_ptr> prop) -{ - QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info->statusTip)); - slider->setToolTip(QString::fromStdString(info->toolTip)); - slider->setRange(info->min, info->max); - slider->setSingleStep(info->singleStep); - slider->setNumTickMarks(info->numTickMarks); - slider->setSuffix(QString::fromStdString(info->suffix)); - - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); - // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); - - return slider; -} -QCheckBox* -create(const CheckBoxUiInfo* info, std::shared_ptr> prop) -{ - QCheckBox* checkBox = new QCheckBox(); - checkBox->setStatusTip(QString::fromStdString(info->statusTip)); - checkBox->setToolTip(QString::fromStdString(info->toolTip)); - // checkBox->setText(QString::fromStdString(info->formLabel)); - checkBox->setCheckState(prop->get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { - prop->set(state == Qt::CheckState::Checked, true); - }); - return checkBox; -} -QComboBox* -create(const ComboBoxUiInfo* info, std::shared_ptr> prop) -{ - QComboBox* comboBox = new QComboBox(); - comboBox->setStatusTip(QString::fromStdString(info->statusTip)); - comboBox->setToolTip(QString::fromStdString(info->toolTip)); - for (const auto& item : info->items) { - comboBox->addItem(QString::fromStdString(item)); - } - comboBox->setCurrentIndex(prop->get()); - QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); - return comboBox; -} - -QNumericSlider* -addRow(const FloatSliderSpinnerUiInfo& info, prtyProperty* prop) -{ - QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info.statusTip)); - slider->setToolTip(QString::fromStdString(info.toolTip)); - slider->setRange(info.min, info.max); - slider->setDecimals(info.decimals); - slider->setSingleStep(info.singleStep); - slider->setNumTickMarks(info.numTickMarks); - slider->setSuffix(QString::fromStdString(info.suffix)); - - slider->setValue(prop->get(), true); - QObject::connect(slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->set(value, true); }); - // TODO how would this capture the "previous" value, for undo? - QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->notifyAll(true); }); - - return slider; -} -QComboBox* -addRow(const ComboBoxUiInfo& info, prtyProperty* prop) -{ - QComboBox* comboBox = new QComboBox(); - comboBox->setStatusTip(QString::fromStdString(info.statusTip)); - comboBox->setToolTip(QString::fromStdString(info.toolTip)); - for (const auto& item : info.items) { - comboBox->addItem(QString::fromStdString(item)); - } - comboBox->setCurrentIndex(prop->get()); - QObject::connect(comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->set(index, true); }); - return comboBox; -} -QCheckBox* -addRow(const CheckBoxUiInfo& info, prtyProperty* prop) -{ - QCheckBox* checkBox = new QCheckBox(); - checkBox->setStatusTip(QString::fromStdString(info.statusTip)); - checkBox->setToolTip(QString::fromStdString(info.toolTip)); - // checkBox->setText(QString::fromStdString(info.formLabel)); - checkBox->setCheckState(prop->get() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { - prop->set(state == Qt::CheckState::Checked, true); - }); - return checkBox; -} - -QCameraWidget::QCameraWidget(QWidget* pParent, QCamera* cam, RenderSettings* rs, CameraDataObject* cdo) +QCameraWidget::QCameraWidget(QWidget* pParent, RenderSettings* rs, CameraObject* cameraObject) : QWidget(pParent) , m_MainLayout() , m_renderSettings(rs) - , m_cameraDataObject(cdo) + , m_cameraObject(cameraObject) { Controls::initFormLayout(m_MainLayout); setLayout(&m_MainLayout); - QNumericSlider* slider = addRow(FloatSliderSpinnerUiInfo("Exposure", - "Set Exposure", - "Set camera exposure", - 0.0f, - 1.0f, - 2, // decimals - 0.01, // singleStep - 0 // numTickMarks - ), - &m_cameraDataObject->Exposure); + QNumericSlider* slider = addRow(*m_cameraObject->getExposureUIInfo()); m_MainLayout.addRow("Exposure", slider); - QComboBox* comboBox = addRow(ComboBoxUiInfo("Exposure Time", - "Set Exposure Time", - "Set number of samples to accumulate per viewport update", - { "1", "2", "4", "8" }), - &m_cameraDataObject->ExposureIterations); + QComboBox* comboBox = addRow(*m_cameraObject->getExposureIterationsUIInfo()); m_MainLayout.addRow("Exposure Time", comboBox); - QCheckBox* checkBox = addRow(CheckBoxUiInfo("Noise Reduction", "Enable denoising pass", "Enable denoising pass"), - &m_cameraDataObject->NoiseReduction); + QCheckBox* checkBox = addRow(*m_cameraObject->getNoiseReductionUIInfo()); m_MainLayout.addRow("Noise Reduction", checkBox); - QNumericSlider* slider2 = addRow(FloatSliderSpinnerUiInfo("Aperture Size", - "Set camera aperture size", - "Set camera aperture size", - 0.0f, - 0.1f, - 2, // decimals - 0.01, // singleStep - 0, // numTickMarks - " mm"), - &m_cameraDataObject->ApertureSize); + QNumericSlider* slider2 = addRow(*m_cameraObject->getApertureSizeUIInfo()); m_MainLayout.addRow("Aperture Size", slider2); - QNumericSlider* slider3 = addRow(FloatSliderSpinnerUiInfo("Field of view", - "Set camera field of view angle", - "Set camera field of view angle", - 10.0f, - 150.0f, - 2, // decimals - 0.01, // singleStep - 0, // numTickMarks - " deg."), - &m_cameraDataObject->FieldOfView); + QNumericSlider* slider3 = addRow(*m_cameraObject->getFieldOfViewUIInfo()); m_MainLayout.addRow("Field of view", slider3); - QNumericSlider* slider4 = addRow(FloatSliderSpinnerUiInfo("Focal distance", - "Set focal distance", - "Set focal distance", - 0.0f, - 15.0f, - 2, // decimals - 0.01, // singleStep - 0, // numTickMarks - " m"), - &m_cameraDataObject->FocalDistance); + QNumericSlider* slider4 = addRow(*m_cameraObject->getFocalDistanceUIInfo()); m_MainLayout.addRow("Focal distance", slider4); #if 0 diff --git a/agave_app/CameraWidget.h b/agave_app/CameraWidget.h index c372b7ab..5592afb0 100644 --- a/agave_app/CameraWidget.h +++ b/agave_app/CameraWidget.h @@ -4,7 +4,7 @@ #include "qtControls/Controls.h" // #include "renderlib/core/prty/prtyProperty.h" -#include "renderlib/CameraDataObject.hpp" +#include "renderlib/CameraUiDescription.hpp" #include "renderlib/Logging.h" #include @@ -19,10 +19,7 @@ class QCameraWidget : public QWidget Q_OBJECT public: - QCameraWidget(QWidget* pParent = NULL, - QCamera* cam = nullptr, - RenderSettings* rs = nullptr, - CameraDataObject* cdo = nullptr); + QCameraWidget(QWidget* pParent = NULL, RenderSettings* rs = nullptr, CameraObject* cameraObject = nullptr); virtual QSize sizeHint() const; @@ -32,5 +29,5 @@ class QCameraWidget : public QWidget RenderSettings* m_renderSettings; private: - CameraDataObject* m_cameraDataObject; + CameraObject* m_cameraObject; }; diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 2fadf7c1..65b07e67 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -43,8 +43,9 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidg m_viewerWindow->gesture.input.setDoubleClickTime((double)QApplication::doubleClickInterval() / 1000.0); // camera is created deep down inside m_viewerWindow. - m_cameraDataObject = new CameraObject(&m_viewerWindow->m_CCamera); - m_appearanceDataObject = new AppearanceObject(rs, scene); + m_cameraDataObject = new CameraObject(); + // m_cameraDataObject->setExternalCamera(&m_viewerWindow->m_CCamera); + m_appearanceDataObject = new AppearanceObject(); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); @@ -123,7 +124,7 @@ GLView3D::onNewImage(Scene* scene) // would be better to preserve renderer and just change the scene data to include the new image. // how tightly coupled is renderer and scene???? - m_appearanceDataObject->updatePropsFromRenderSettings(); + m_appearanceDataObject->updatePropsFromObject(); } GLView3D::~GLView3D() @@ -480,9 +481,9 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) camera.m_Focus.m_FocalDistance = s.camera.focalDistance; // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! - m_cameraDataObject->updatePropsFromCamera(); + m_cameraDataObject->updatePropsFromObject(); - m_appearanceDataObject->updatePropsFromRenderSettings(); + m_appearanceDataObject->updatePropsFromObject(); } QPixmap diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index e3cb225e..4de114a4 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -68,8 +68,8 @@ class GLView3D : public QOpenGLWidget const CCamera& getCamera() { return m_viewerWindow->m_CCamera; } // tied to the above camera. CCamera must outlive this: - CameraDataObject* getCameraDataObject() { return m_cameraDataObject; } - AppearanceDataObject* getAppearanceDataObject() { return m_appearanceDataObject; } + CameraObject* getCameraDataObject() { return m_cameraDataObject; } + AppearanceObject* getAppearanceDataObject() { return m_appearanceDataObject; } void fromViewerState(const Serialize::ViewerState& s); diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index e73edd84..36164112 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -351,7 +351,7 @@ agaveGui::createToolbars() } void -agaveGui::setupCameraDock(CameraDataObject* cdo) +agaveGui::setupCameraDock(CameraObject* cdo) { // TODO enable changing/resetting the camera data object shown in this dock? m_cameradock = new QCameraDockWidget(this, &m_qcamera, &m_renderSettings, cdo); @@ -364,7 +364,7 @@ agaveGui::setupCameraDock(CameraDataObject* cdo) } void -agaveGui::setupAppearanceDock(AppearanceDataObject* ado) +agaveGui::setupAppearanceDock(AppearanceObject* ado) { // DANGER see borrowRenderer call m_appearanceDockWidget2 = new QAppearanceDockWidget2(this, &m_renderSettings, m_glView->borrowRenderer(), ado); @@ -1325,11 +1325,11 @@ agaveGui::appToViewerState() v.camera.projection = m_glView->getCamera().m_Projection == PERSPECTIVE ? Serialize::Projection_PID::PERSPECTIVE : Serialize::Projection_PID::ORTHOGRAPHIC; v.camera.orthoScale = m_glView->getCamera().m_OrthoScale; - CameraDataObject* cdo = m_glView->getCameraDataObject(); - v.camera.fovY = cdo->FieldOfView.GetValue(); - v.camera.exposure = cdo->Exposure.GetValue(); - v.camera.aperture = cdo->ApertureSize.GetValue(); - v.camera.focalDistance = cdo->FocalDistance.GetValue(); + CameraObject* cdo = m_glView->getCameraDataObject(); + v.camera.fovY = cdo->getCameraDataObject().FieldOfView.GetValue(); + v.camera.exposure = cdo->getCameraDataObject().Exposure.GetValue(); + v.camera.aperture = cdo->getCameraDataObject().ApertureSize.GetValue(); + v.camera.focalDistance = cdo->getCameraDataObject().FocalDistance.GetValue(); v.density = m_renderSettings.m_RenderSettings.m_DensityScale; v.interpolate = m_renderSettings.m_RenderSettings.m_InterpolatedVolumeSampling; diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h index a32d9516..fa8dba50 100644 --- a/agave_app/agaveGui.h +++ b/agave_app/agaveGui.h @@ -94,10 +94,10 @@ private slots: void createActions(); void createMenus(); void createToolbars(); - void createDockWindows(); - void setupCameraDock(CameraDataObject* cdo); + void addDockItemsToViewMenu(); + void setupCameraDock(CameraObject* cdo); void setupTimelineDock(); - void setupAppearanceDock(AppearanceDataObject* ado); + void setupAppearanceDock(AppearanceObject* ado); void setupStatisticsDock(); void showOpenFailedMessageBox(QString path); diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index 11da9a3d..f7bfada4 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -6,8 +6,8 @@ QNumericSlider* create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop) { QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info->statusTip)); - slider->setToolTip(QString::fromStdString(info->toolTip)); + slider->setStatusTip(QString::fromStdString(info->GetStatusTip())); + slider->setToolTip(QString::fromStdString(info->GetToolTip())); slider->setRange(info->min, info->max); slider->setDecimals(info->decimals); slider->setSingleStep(info->singleStep); @@ -26,8 +26,8 @@ QNumericSlider* create(const IntSliderSpinnerUiInfo* info, std::shared_ptr prop) { QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info->statusTip)); - slider->setToolTip(QString::fromStdString(info->toolTip)); + slider->setStatusTip(QString::fromStdString(info->GetStatusTip())); + slider->setToolTip(QString::fromStdString(info->GetToolTip())); slider->setRange(info->min, info->max); slider->setSingleStep(info->singleStep); slider->setNumTickMarks(info->numTickMarks); @@ -45,8 +45,8 @@ QCheckBox* create(const CheckBoxUiInfo* info, std::shared_ptr prop) { QCheckBox* checkBox = new QCheckBox(); - checkBox->setStatusTip(QString::fromStdString(info->statusTip)); - checkBox->setToolTip(QString::fromStdString(info->toolTip)); + checkBox->setStatusTip(QString::fromStdString(info->GetStatusTip())); + checkBox->setToolTip(QString::fromStdString(info->GetToolTip())); // checkBox->setText(QString::fromStdString(info->formLabel)); checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { @@ -58,8 +58,8 @@ QComboBox* create(const ComboBoxUiInfo* info, std::shared_ptr prop) { QComboBox* comboBox = new QComboBox(); - comboBox->setStatusTip(QString::fromStdString(info->statusTip)); - comboBox->setToolTip(QString::fromStdString(info->toolTip)); + comboBox->setStatusTip(QString::fromStdString(info->GetStatusTip())); + comboBox->setToolTip(QString::fromStdString(info->GetToolTip())); for (const auto& item : info->items) { comboBox->addItem(QString::fromStdString(item)); } @@ -70,17 +70,18 @@ create(const ComboBoxUiInfo* info, std::shared_ptr prop) } QNumericSlider* -addRow(const FloatSliderSpinnerUiInfo& info, prtyFloat* prop) +addRow(const FloatSliderSpinnerUiInfo& info) { QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info.statusTip)); - slider->setToolTip(QString::fromStdString(info.toolTip)); + slider->setStatusTip(QString::fromStdString(info.GetStatusTip())); + slider->setToolTip(QString::fromStdString(info.GetToolTip())); slider->setRange(info.min, info.max); slider->setDecimals(info.decimals); slider->setSingleStep(info.singleStep); slider->setNumTickMarks(info.numTickMarks); slider->setSuffix(QString::fromStdString(info.suffix)); + auto* prop = static_cast(info.GetProperty(0)); slider->setValue(prop->GetValue(), true); QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); @@ -90,16 +91,17 @@ addRow(const FloatSliderSpinnerUiInfo& info, prtyFloat* prop) return slider; } QNumericSlider* -addRow(const IntSliderSpinnerUiInfo& info, prtyInt32* prop) +addRow(const IntSliderSpinnerUiInfo& info) { QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info.statusTip)); - slider->setToolTip(QString::fromStdString(info.toolTip)); + slider->setStatusTip(QString::fromStdString(info.GetStatusTip())); + slider->setToolTip(QString::fromStdString(info.GetToolTip())); slider->setRange(info.min, info.max); slider->setSingleStep(info.singleStep); slider->setNumTickMarks(info.numTickMarks); slider->setSuffix(QString::fromStdString(info.suffix)); + auto* prop = static_cast(info.GetProperty(0)); slider->setValue(prop->GetValue(), true); QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); @@ -110,14 +112,15 @@ addRow(const IntSliderSpinnerUiInfo& info, prtyInt32* prop) } QComboBox* -addRow(const ComboBoxUiInfo& info, prtyInt8* prop) +addRow(const ComboBoxUiInfo& info) { QComboBox* comboBox = new QComboBox(); - comboBox->setStatusTip(QString::fromStdString(info.statusTip)); - comboBox->setToolTip(QString::fromStdString(info.toolTip)); + comboBox->setStatusTip(QString::fromStdString(info.GetStatusTip())); + comboBox->setToolTip(QString::fromStdString(info.GetToolTip())); for (const auto& item : info.items) { comboBox->addItem(QString::fromStdString(item)); } + auto* prop = static_cast(info.GetProperty(0)); comboBox->setCurrentIndex(prop->GetValue()); QObject::connect( comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->SetValue(index, true); }); @@ -125,12 +128,13 @@ addRow(const ComboBoxUiInfo& info, prtyInt8* prop) } QCheckBox* -addRow(const CheckBoxUiInfo& info, prtyBoolean* prop) +addRow(const CheckBoxUiInfo& info) { QCheckBox* checkBox = new QCheckBox(); - checkBox->setStatusTip(QString::fromStdString(info.statusTip)); - checkBox->setToolTip(QString::fromStdString(info.toolTip)); + checkBox->setStatusTip(QString::fromStdString(info.GetStatusTip())); + checkBox->setToolTip(QString::fromStdString(info.GetToolTip())); // checkBox->setText(QString::fromStdString(info.formLabel)); + auto* prop = static_cast(info.GetProperty(0)); checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { prop->SetValue(state == Qt::CheckState::Checked, true); @@ -139,11 +143,12 @@ addRow(const CheckBoxUiInfo& info, prtyBoolean* prop) } QColorPushButton* -addRow(const ColorPickerUiInfo& info, prtyColor* prop) +addRow(const ColorPickerUiInfo& info) { QColorPushButton* colorButton = new QColorPushButton(); - colorButton->setStatusTip(QString::fromStdString(info.statusTip)); - colorButton->setToolTip(QString::fromStdString(info.toolTip)); + colorButton->setStatusTip(QString::fromStdString(info.GetStatusTip())); + colorButton->setToolTip(QString::fromStdString(info.GetToolTip())); + auto* prop = static_cast(info.GetProperty(0)); QColor c = QColor::fromRgbF(prop->GetValue().r, prop->GetValue().g, prop->GetValue().b); colorButton->SetColor(c, true); QObject::connect(colorButton, &QColorPushButton::currentColorChanged, [colorButton, prop](const QColor& c) { diff --git a/agave_app/qtControls/controlFactory.h b/agave_app/qtControls/controlFactory.h index 1d0f4a7d..6bccb8c2 100644 --- a/agave_app/qtControls/controlFactory.h +++ b/agave_app/qtControls/controlFactory.h @@ -28,16 +28,16 @@ QComboBox* create(const ComboBoxUiInfo* info, std::shared_ptr prop); QNumericSlider* -addRow(const FloatSliderSpinnerUiInfo& info, prtyFloat* prop); +addRow(const FloatSliderSpinnerUiInfo& info); QNumericSlider* -addRow(const IntSliderSpinnerUiInfo& info, prtyInt32* prop); +addRow(const IntSliderSpinnerUiInfo& info); QComboBox* -addRow(const ComboBoxUiInfo& info, prtyInt8* prop); +addRow(const ComboBoxUiInfo& info); QCheckBox* -addRow(const CheckBoxUiInfo& info, prtyBoolean* prop); +addRow(const CheckBoxUiInfo& info); QColorPushButton* -addRow(const ColorPickerUiInfo& info, prtyColor* prop); +addRow(const ColorPickerUiInfo& info); From a9b19408dcd33127d82d1e80e84131fd773d350f Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Wed, 25 Jun 2025 15:47:02 -0700 Subject: [PATCH 30/60] make control creation more generic --- agave_app/CameraWidget.cpp | 124 ++---------------------- agave_app/qtControls/controlFactory.cpp | 85 +++++++++++++++- agave_app/qtControls/controlFactory.h | 12 +++ 3 files changed, 104 insertions(+), 117 deletions(-) diff --git a/agave_app/CameraWidget.cpp b/agave_app/CameraWidget.cpp index 2c087dbb..d413cf87 100644 --- a/agave_app/CameraWidget.cpp +++ b/agave_app/CameraWidget.cpp @@ -1,9 +1,14 @@ #include "CameraWidget.h" #include "RenderSettings.h" +#include "qtControls/controlFactory.h" +#include "qtControls/Section.h" + #include "renderlib/uiInfo.hpp" #include +#include +#include QCameraWidget::QCameraWidget(QWidget* pParent, RenderSettings* rs, CameraObject* cameraObject) : QWidget(pParent) @@ -14,122 +19,9 @@ QCameraWidget::QCameraWidget(QWidget* pParent, RenderSettings* rs, CameraObject* Controls::initFormLayout(m_MainLayout); setLayout(&m_MainLayout); - QNumericSlider* slider = addRow(*m_cameraObject->getExposureUIInfo()); - m_MainLayout.addRow("Exposure", slider); - QComboBox* comboBox = addRow(*m_cameraObject->getExposureIterationsUIInfo()); - m_MainLayout.addRow("Exposure Time", comboBox); - QCheckBox* checkBox = addRow(*m_cameraObject->getNoiseReductionUIInfo()); - m_MainLayout.addRow("Noise Reduction", checkBox); - QNumericSlider* slider2 = addRow(*m_cameraObject->getApertureSizeUIInfo()); - m_MainLayout.addRow("Aperture Size", slider2); - QNumericSlider* slider3 = addRow(*m_cameraObject->getFieldOfViewUIInfo()); - m_MainLayout.addRow("Field of view", slider3); - QNumericSlider* slider4 = addRow(*m_cameraObject->getFocalDistanceUIInfo()); - m_MainLayout.addRow("Focal distance", slider4); - -#if 0 - // Exposure, controls how bright or dim overall scene is - m_ExposureSlider.setStatusTip(tr("Set Exposure")); - m_ExposureSlider.setToolTip(tr("Set camera exposure")); - m_ExposureSlider.setRange(0.0f, 1.0f); - m_ExposureSlider.setValue(cam->GetFilm().GetExposure()); - m_ExposureSlider.setDecimals(2); - m_ExposureSlider.setSingleStep(0.01); - - m_MainLayout.addRow("Exposure", &m_ExposureSlider); - - connect(&m_ExposureSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetExposure); - - // Number of render iterations per viewport update - m_ExposureIterationsSpinner.setStatusTip(tr("Set Exposure Time")); - m_ExposureIterationsSpinner.setToolTip(tr("Set number of samples to accumulate per viewport update")); - m_ExposureIterationsSpinner.addItem("1", 1); - m_ExposureIterationsSpinner.addItem("2", 2); - m_ExposureIterationsSpinner.addItem("4", 4); - m_ExposureIterationsSpinner.addItem("8", 8); - m_ExposureIterationsSpinner.setCurrentIndex( - m_ExposureIterationsSpinner.findData(cam->GetFilm().GetExposureIterations())); - m_MainLayout.addRow("Exposure Time", &m_ExposureIterationsSpinner); - connect(&m_ExposureIterationsSpinner, &QComboBox::currentIndexChanged, this, &QCameraWidget::SetExposureIterations); - - m_NoiseReduction.setStatusTip(tr("Enable denoising pass")); - m_NoiseReduction.setToolTip(tr("Enable denoising pass")); - m_NoiseReduction.setCheckState(rs->m_DenoiseParams.m_Enabled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - m_MainLayout.addRow("Noise Reduction", &m_NoiseReduction); - - connect(&m_NoiseReduction, &QCheckBox::stateChanged, this, &QCameraWidget::OnNoiseReduction); - - m_ApertureSizeSlider.setStatusTip(tr("Set camera aperture size")); - m_ApertureSizeSlider.setToolTip(tr("Set camera aperture size")); - m_ApertureSizeSlider.setRange(0.0, 0.1); - m_ApertureSizeSlider.setSuffix(" mm"); - m_ApertureSizeSlider.setDecimals(2); - m_ApertureSizeSlider.setValue(0.0); - m_ApertureSizeSlider.setSingleStep(0.01); - m_MainLayout.addRow("Aperture Size", &m_ApertureSizeSlider); - - connect(&m_ApertureSizeSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetAperture); - - m_FieldOfViewSlider.setStatusTip(tr("Set camera field of view angle")); - m_FieldOfViewSlider.setToolTip(tr("Set camera field of view angle")); - m_FieldOfViewSlider.setRange(10.0, 150.0); - m_FieldOfViewSlider.setDecimals(2); - m_FieldOfViewSlider.setValue(cam->GetProjection().GetFieldOfView()); - m_FieldOfViewSlider.setSuffix(" deg."); - m_MainLayout.addRow("Field of view", &m_FieldOfViewSlider); - - connect(&m_FieldOfViewSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetFieldOfView); - - // Focal distance - m_FocalDistanceSlider.setStatusTip(tr("Set focal distance")); - m_FocalDistanceSlider.setToolTip(tr("Set focal distance")); - m_FocalDistanceSlider.setRange(0.0, 15.0); - m_FocalDistanceSlider.setDecimals(2); - m_FocalDistanceSlider.setValue(0.0); - m_FocalDistanceSlider.setSuffix(" m"); - - m_MainLayout.addRow("Focal distance", &m_FocalDistanceSlider); - - connect(&m_FocalDistanceSlider, &QNumericSlider::valueChanged, this, &QCameraWidget::SetFocalDistance); - - QObject::connect(&cam->GetFilm(), SIGNAL(Changed(const QFilm&)), this, SLOT(OnFilmChanged())); - QObject::connect(&cam->GetAperture(), SIGNAL(Changed(const QAperture&)), this, SLOT(OnApertureChanged())); - QObject::connect(&cam->GetProjection(), SIGNAL(Changed(const QProjection&)), this, SLOT(OnProjectionChanged())); - QObject::connect(&cam->GetFocus(), SIGNAL(Changed(const QFocus&)), this, SLOT(OnFocusChanged())); -#endif -} - -void -QCameraWidget::OnFilmChanged() -{ - m_ExposureSlider.setValue(m_qcamera->GetFilm().GetExposure(), true); - m_ExposureIterationsSpinner.blockSignals(true); - m_ExposureIterationsSpinner.setCurrentIndex( - m_ExposureIterationsSpinner.findData(m_qcamera->GetFilm().GetExposureIterations())); - m_ExposureIterationsSpinner.blockSignals(false); - m_NoiseReduction.blockSignals(true); - m_NoiseReduction.setCheckState(m_renderSettings->m_DenoiseParams.m_Enabled ? Qt::CheckState::Checked - : Qt::CheckState::Unchecked); - m_NoiseReduction.blockSignals(false); - emit m_qcamera->Changed(); -} -void -QCameraWidget::OnApertureChanged() -{ - m_ApertureSizeSlider.setValue(m_qcamera->GetAperture().GetSize(), true); - emit m_qcamera->Changed(); -} -void -QCameraWidget::OnProjectionChanged() -{ - m_FieldOfViewSlider.setValue(m_qcamera->GetProjection().GetFieldOfView(), true); - emit m_qcamera->Changed(); -} -void -QCameraWidget::OnFocusChanged() -{ - m_FocalDistanceSlider.setValue(m_qcamera->GetFocus().GetFocalDistance(), true); - emit m_qcamera->Changed(); + if (m_cameraObject) { + createFlatList(&m_MainLayout, m_cameraObject); + } } QSize diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index f7bfada4..c25d3175 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -1,6 +1,11 @@ #include "controlFactory.h" #include "Controls.h" +#include "Section.h" + +#include "renderlib/core/prty/prtyObject.hpp" + +#include QNumericSlider* create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop) @@ -157,4 +162,82 @@ addRow(const ColorPickerUiInfo& info) prop->SetValue(color, true); }); return colorButton; -} \ No newline at end of file +} + +QWidget* +addGenericRow(const prtyPropertyUIInfo& info) +{ + // TODO: consider checking info.GetControlName() to determine the type, + // but using dynamic_cast is more type-safe and extensible. + // If a new type is added, it will require a new dynamic_cast case here. + if (const auto* floatInfo = dynamic_cast(&info)) { + return addRow(*floatInfo); + } else if (const auto* intInfo = dynamic_cast(&info)) { + return addRow(*intInfo); + } else if (const auto* comboBoxInfo = dynamic_cast(&info)) { + return addRow(*comboBoxInfo); + } else if (const auto* checkBoxInfo = dynamic_cast(&info)) { + return addRow(*checkBoxInfo); + } else if (const auto* colorPickerInfo = dynamic_cast(&info)) { + return addRow(*colorPickerInfo); + } + return nullptr; // or throw an exception +} + +void +createCategorizedSections(QFormLayout* mainLayout, prtyObject* object) +{ + // Map to organize properties by category + std::map>> categorizedProperties; + + // Group properties by category + const auto& propertyList = object->GetList(); + for (const auto& propertyInfo : propertyList) { + if (propertyInfo) { + std::string category = propertyInfo->GetCategory(); + categorizedProperties[category].push_back(propertyInfo); + } + } + + // Create sections for each category (automatically sorted by std::map) + for (const auto& [category, properties] : categorizedProperties) { + if (!properties.empty()) { + // Create section + Section* section = new Section(QString::fromStdString(category)); + + // Create form layout for this section's content + QFormLayout* sectionLayout = new QFormLayout(); + + // Add controls for each property in this category + for (const auto& propertyInfo : properties) { + QWidget* control = addGenericRow(*propertyInfo); + if (control) { + QString label = QString::fromStdString(propertyInfo->GetDescription()); + sectionLayout->addRow(label, control); + } + } + + // Set the section's content layout + section->setContentLayout(*sectionLayout); + + // Add section to main layout + mainLayout->addRow(section); + } + } +} + +void +createFlatList(QFormLayout* mainLayout, prtyObject* object) +{ + // Simple flat list of all properties + const auto& propertyList = object->GetList(); + for (const auto& propertyInfo : propertyList) { + if (propertyInfo) { + QWidget* control = addGenericRow(*propertyInfo); + if (control) { + QString label = QString::fromStdString(propertyInfo->GetDescription()); + mainLayout->addRow(label, control); + } + } + } +} diff --git a/agave_app/qtControls/controlFactory.h b/agave_app/qtControls/controlFactory.h index 6bccb8c2..36ca0151 100644 --- a/agave_app/qtControls/controlFactory.h +++ b/agave_app/qtControls/controlFactory.h @@ -6,6 +6,7 @@ #include "renderlib/core/prty/prtyFloat.hpp" #include "renderlib/core/prty/prtyInt32.hpp" #include "renderlib/core/prty/prtyInt8.hpp" +#include "renderlib/core/prty/prtyObject.hpp" #include "renderlib/glm.h" #include @@ -14,6 +15,8 @@ class QNumericSlider; class QCheckBox; class QComboBox; class QColorPushButton; +class QFormLayout; +class QWidget; QNumericSlider* create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop); @@ -41,3 +44,12 @@ addRow(const CheckBoxUiInfo& info); QColorPushButton* addRow(const ColorPickerUiInfo& info); + +QWidget* +addGenericRow(const prtyPropertyUIInfo& info); + +void +createFlatList(QFormLayout* mainLayout, prtyObject* object); + +void +createCategorizedSections(QFormLayout* mainLayout, prtyObject* object); \ No newline at end of file From 221c0999e56a4ac81d64c85a4c873586ef3275a8 Mon Sep 17 00:00:00 2001 From: DMT Date: Sat, 28 Jun 2025 17:17:10 -0700 Subject: [PATCH 31/60] add ui info details --- renderlib/AppearanceDataObject.hpp | 10 +++--- renderlib/AppearanceUiDescription.cpp | 48 +++++++++++++++++++++++++++ renderlib/CameraUiDescription.cpp | 36 ++++++++++++++++++++ 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index 35774b7f..d456af83 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -12,15 +12,15 @@ class AppearanceDataObject public: AppearanceDataObject(); - prtyInt8 RendererType{ "RendererType", 0 }; + prtyInt8 RendererType{ "RendererType", 1 }; prtyInt8 ShadingType{ "ShadingType", 0 }; prtyFloat DensityScale{ "DensityScale", 1.0f }; prtyFloat GradientFactor{ "GradientFactor", 0.5f }; - prtyFloat StepSizePrimaryRay{ "StepSizePrimaryRay", 1.0f }; - prtyFloat StepSizeSecondaryRay{ "StepSizeSecondaryRay", 1.0f }; - prtyBoolean Interpolate{ "Interpolate", false }; + prtyFloat StepSizePrimaryRay{ "StepSizePrimaryRay", 4.0f }; + prtyFloat StepSizeSecondaryRay{ "StepSizeSecondaryRay", 4.0f }; + prtyBoolean Interpolate{ "Interpolate", true }; prtyColor BackgroundColor{ "BackgroundColor", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f) }; - prtyBoolean ShowBoundingBox{ "ShowBoundingBox", false }; + prtyBoolean ShowBoundingBox{ "ShowBoundingBox", true }; prtyColor BoundingBoxColor{ "BoundingBoxColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) }; prtyBoolean ShowScaleBar{ "ShowScaleBar", false }; }; diff --git a/renderlib/AppearanceUiDescription.cpp b/renderlib/AppearanceUiDescription.cpp index 0b31b872..7fe499f7 100644 --- a/renderlib/AppearanceUiDescription.cpp +++ b/renderlib/AppearanceUiDescription.cpp @@ -58,30 +58,78 @@ AppearanceObject::AppearanceObject() { m_renderSettings = std::make_shared(); m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, "Appearance", "Renderer Type"); + m_rendererType->SetToolTip("Select volume rendering type"); + m_rendererType->SetStatusTip("Select volume rendering type"); + m_rendererType->items = { "Ray march blending", "Path Traced" }; AddProperty(m_rendererType); m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, "Appearance", "Shading Type"); + m_shadingType->SetToolTip("Select volume shading style"); + m_shadingType->SetStatusTip("Select volume shading style"); + m_shadingType->items = { "BRDF Only", "Phase Function Only", "Mixed" }; AddProperty(m_shadingType); m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, "Appearance", "Density Scale"); + m_densityScale->SetToolTip("Set scattering density for volume"); + m_densityScale->SetStatusTip("Set scattering density for volume"); + m_densityScale->min = 0.001f; + m_densityScale->max = 100.0f; + m_densityScale->decimals = 3; // decimals + m_densityScale->singleStep = 0.01f; // singleStep + m_densityScale->numTickMarks = 10; // numTickMarks + m_densityScale->suffix = ""; // suffix AddProperty(m_densityScale); m_gradientFactor = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.GradientFactor, "Appearance", "Gradient Factor"); + m_gradientFactor->SetToolTip("Mix between BRDF and Phase shading"); + m_gradientFactor->SetStatusTip("Mix between BRDF and Phase shading"); + m_gradientFactor->min = 0.0f; + m_gradientFactor->max = 1.0f; + m_gradientFactor->decimals = 3; // decimals + m_gradientFactor->singleStep = 0.01f; // singleStep + m_gradientFactor->numTickMarks = 10; // numTickMarks + m_gradientFactor->suffix = ""; // suffix AddProperty(m_gradientFactor); m_stepSizePrimaryRay = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizePrimaryRay, "Appearance", "Step Size Primary Ray"); + m_stepSizePrimaryRay->SetToolTip("Set volume ray march step size for camera rays"); + m_stepSizePrimaryRay->SetStatusTip("Set volume ray march step size for camera rays"); + m_stepSizePrimaryRay->min = 1.0f; + m_stepSizePrimaryRay->max = 100.0f; + m_stepSizePrimaryRay->decimals = 3; // decimals + m_stepSizePrimaryRay->singleStep = 0.01f; // singleStep + m_stepSizePrimaryRay->numTickMarks = 10; // numTickMarks + m_stepSizePrimaryRay->suffix = ""; // suffix AddProperty(m_stepSizePrimaryRay); m_stepSizeSecondaryRay = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizeSecondaryRay, "Appearance", "Step Size Secondary Ray"); + m_stepSizeSecondaryRay->SetToolTip("Set volume ray march step size for scattered rays"); + m_stepSizeSecondaryRay->SetStatusTip("Set volume ray march step size for scattered rays"); + m_stepSizeSecondaryRay->min = 1.0f; + m_stepSizeSecondaryRay->max = 100.0f; + m_stepSizeSecondaryRay->decimals = 3; // decimals + m_stepSizeSecondaryRay->singleStep = 0.01f; // singleStep + m_stepSizeSecondaryRay->numTickMarks = 10; // numTickMarks + m_stepSizeSecondaryRay->suffix = ""; // suffix AddProperty(m_stepSizeSecondaryRay); m_interpolate = new CheckBoxUiInfo(&m_appearanceDataObject.Interpolate, "Appearance", "Interpolate"); + m_interpolate->SetToolTip("Interpolated volume sampling"); + m_interpolate->SetStatusTip("Interpolated volume sampling"); AddProperty(m_interpolate); m_backgroundColor = new ColorPickerUiInfo(&m_appearanceDataObject.BackgroundColor, "Appearance", "Background Color"); + m_backgroundColor->SetToolTip("Set background color"); + m_backgroundColor->SetStatusTip("Set background color"); AddProperty(m_backgroundColor); m_showBoundingBox = new CheckBoxUiInfo(&m_appearanceDataObject.ShowBoundingBox, "Appearance", "Show Bounding Box"); + m_showBoundingBox->SetToolTip("Show/hide bounding box"); + m_showBoundingBox->SetStatusTip("Show/hide bounding box"); AddProperty(m_showBoundingBox); m_boundingBoxColor = new ColorPickerUiInfo(&m_appearanceDataObject.BoundingBoxColor, "Appearance", "Bounding Box Color"); + m_boundingBoxColor->SetToolTip("Set bounding box color"); + m_boundingBoxColor->SetStatusTip("Set bounding box color"); AddProperty(m_boundingBoxColor); m_showScaleBar = new CheckBoxUiInfo(&m_appearanceDataObject.ShowScaleBar, "Appearance", "Show Scale Bar"); + m_showScaleBar->SetToolTip("Show/hide scale bar"); + m_showScaleBar->SetStatusTip("Show/hide scale bar"); AddProperty(m_showScaleBar); m_appearanceDataObject.RendererType.AddCallback( diff --git a/renderlib/CameraUiDescription.cpp b/renderlib/CameraUiDescription.cpp index a7f932bb..fb22ca64 100644 --- a/renderlib/CameraUiDescription.cpp +++ b/renderlib/CameraUiDescription.cpp @@ -51,17 +51,53 @@ CameraObject::CameraObject() { m_camera = std::make_shared(); m_ExposureUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.Exposure, "Camera", "Exposure"); + m_ExposureUIInfo->SetToolTip("Set Exposure"); + m_ExposureUIInfo->SetStatusTip("Set camera exposure"); + m_ExposureUIInfo->min = 0.0f; + m_ExposureUIInfo->max = 1.0f; + m_ExposureUIInfo->decimals = 2; // decimals + m_ExposureUIInfo->singleStep = 0.01f; // singleStep + m_ExposureUIInfo->numTickMarks = 0; // numTickMarks AddProperty(m_ExposureUIInfo); m_ExposureIterationsUIInfo = new ComboBoxUiInfo(&m_cameraDataObject.ExposureIterations, "Camera", "Exposure Iterations"); + m_ExposureIterationsUIInfo->SetToolTip("Set Exposure Iterations"); + m_ExposureIterationsUIInfo->SetStatusTip("Set number of samples to accumulate per viewport update"); + m_ExposureIterationsUIInfo->items = { "1", "2", "4", "8" }; AddProperty(m_ExposureIterationsUIInfo); m_NoiseReductionUIInfo = new CheckBoxUiInfo(&m_cameraDataObject.NoiseReduction, "Camera", "Noise Reduction"); + m_NoiseReductionUIInfo->SetToolTip("Enable Noise Reduction"); + m_NoiseReductionUIInfo->SetStatusTip("Enable denoising pass"); AddProperty(m_NoiseReductionUIInfo); m_ApertureSizeUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.ApertureSize, "Camera", "Aperture Size"); + m_ApertureSizeUIInfo->SetToolTip("Set Aperture Size"); + m_ApertureSizeUIInfo->SetStatusTip("Set camera aperture size"); + m_ApertureSizeUIInfo->min = 0.0f; + m_ApertureSizeUIInfo->max = 0.1f; + m_ApertureSizeUIInfo->decimals = 2; // decimals + m_ApertureSizeUIInfo->singleStep = 0.01f; // + m_ApertureSizeUIInfo->numTickMarks = 0; // numTickMarks + m_ApertureSizeUIInfo->suffix = " mm"; // suffix AddProperty(m_ApertureSizeUIInfo); m_FieldOfViewUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FieldOfView, "Camera", "Field of View"); + m_FieldOfViewUIInfo->SetToolTip("Set Field of View"); + m_FieldOfViewUIInfo->SetStatusTip("Set camera field of view angle"); + m_FieldOfViewUIInfo->min = 10.0f; + m_FieldOfViewUIInfo->max = 150.0f; + m_FieldOfViewUIInfo->decimals = 2; // decimals + m_FieldOfViewUIInfo->singleStep = 0.01f; // single + m_FieldOfViewUIInfo->numTickMarks = 0; // numTickMarks + m_FieldOfViewUIInfo->suffix = " deg"; // suffix AddProperty(m_FieldOfViewUIInfo); m_FocalDistanceUIInfo = new FloatSliderSpinnerUiInfo(&m_cameraDataObject.FocalDistance, "Camera", "Focal Distance"); + m_FocalDistanceUIInfo->SetToolTip("Set Focal Distance"); + m_FocalDistanceUIInfo->SetStatusTip("Set focal distance"); + m_FocalDistanceUIInfo->min = 0.0f; + m_FocalDistanceUIInfo->max = 15.0f; + m_FocalDistanceUIInfo->decimals = 2; // decimals + m_FocalDistanceUIInfo->singleStep = 0.01f; // single + m_FocalDistanceUIInfo->numTickMarks = 0; // numTickMarks + m_FocalDistanceUIInfo->suffix = " m"; // suffix AddProperty(m_FocalDistanceUIInfo); m_cameraDataObject.Exposure.AddCallback(new prtyCallbackWrapper(this, &CameraObject::ExposureChanged)); From 2f31703bdb67ab90bd74f327dee9eddb2c114eea Mon Sep 17 00:00:00 2001 From: DMT Date: Sat, 28 Jun 2025 18:48:53 -0700 Subject: [PATCH 32/60] tiny cleanup --- agave_app/qtControls/controlFactory.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index c25d3175..8c61dbb7 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -22,8 +22,6 @@ create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop) slider->setValue(prop->GetValue(), true); QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - // TODO how would this capture the "previous" value, for undo? - // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } @@ -41,8 +39,6 @@ create(const IntSliderSpinnerUiInfo* info, std::shared_ptr prop) slider->setValue(prop->GetValue(), true); QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - // TODO how would this capture the "previous" value, for undo? - // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } @@ -52,7 +48,6 @@ create(const CheckBoxUiInfo* info, std::shared_ptr prop) QCheckBox* checkBox = new QCheckBox(); checkBox->setStatusTip(QString::fromStdString(info->GetStatusTip())); checkBox->setToolTip(QString::fromStdString(info->GetToolTip())); - // checkBox->setText(QString::fromStdString(info->formLabel)); checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { prop->SetValue(state == Qt::CheckState::Checked, true); @@ -90,8 +85,6 @@ addRow(const FloatSliderSpinnerUiInfo& info) slider->setValue(prop->GetValue(), true); QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - // TODO how would this capture the "previous" value, for undo? - // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } @@ -110,8 +103,6 @@ addRow(const IntSliderSpinnerUiInfo& info) slider->setValue(prop->GetValue(), true); QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - // TODO how would this capture the "previous" value, for undo? - // QObject::connect(slider, &QNumericSlider::valueChangeCommit, [slider, prop]() { prop->NotifyAll(true); }); return slider; } @@ -138,7 +129,6 @@ addRow(const CheckBoxUiInfo& info) QCheckBox* checkBox = new QCheckBox(); checkBox->setStatusTip(QString::fromStdString(info.GetStatusTip())); checkBox->setToolTip(QString::fromStdString(info.GetToolTip())); - // checkBox->setText(QString::fromStdString(info.formLabel)); auto* prop = static_cast(info.GetProperty(0)); checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { From 7eb9ad9cdc4236b77ad668f165e1c75c5a19bc36 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Thu, 3 Jul 2025 16:58:19 -0700 Subject: [PATCH 33/60] wip on camera creation / lifetime --- agave_app/CameraWidget.cpp | 11 +++++++ agave_app/GLView3D.cpp | 50 ++++++++++++++++--------------- agave_app/GLView3D.h | 2 +- agave_app/agaveGui.cpp | 12 ++++---- renderlib/CameraUiDescription.cpp | 5 ++++ renderlib/CameraUiDescription.hpp | 3 ++ renderlib/ViewerWindow.cpp | 19 ++++++------ renderlib/ViewerWindow.h | 3 +- 8 files changed, 64 insertions(+), 41 deletions(-) diff --git a/agave_app/CameraWidget.cpp b/agave_app/CameraWidget.cpp index d413cf87..56aea443 100644 --- a/agave_app/CameraWidget.cpp +++ b/agave_app/CameraWidget.cpp @@ -22,6 +22,17 @@ QCameraWidget::QCameraWidget(QWidget* pParent, RenderSettings* rs, CameraObject* if (m_cameraObject) { createFlatList(&m_MainLayout, m_cameraObject); } + // // loop over all properties in cameraobject. for each property, add a callback that updates the rendersetttings + // // cameradirty flags + // for (const auto& prop : m_cameraObject->GetList()) { + // if (prop) { + // prop->GetProperty(0)->AddCallback(new prtyCallbackLambda([this](prtyProperty* i_Property, bool i_bDirty) { + // if (i_bDirty) { + // m_renderSettings->m_DirtyFlags.SetFlag(CameraDirty); + // } + // })); + // } + // } } QSize diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 65b07e67..9355504d 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -44,6 +44,8 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidg // camera is created deep down inside m_viewerWindow. m_cameraDataObject = new CameraObject(); + m_viewerWindow->m_CCamera = m_cameraDataObject->getCamera(); + // m_cameraDataObject->setExternalCamera(&m_viewerWindow->m_CCamera); m_appearanceDataObject = new AppearanceObject(); @@ -78,10 +80,10 @@ void GLView3D::initCameraFromImage(Scene* scene) { // Tell the camera about the volume's bounding box - m_viewerWindow->m_CCamera.m_SceneBoundingBox.m_MinP = scene->m_boundingBox.GetMinP(); - m_viewerWindow->m_CCamera.m_SceneBoundingBox.m_MaxP = scene->m_boundingBox.GetMaxP(); + m_viewerWindow->m_CCamera->m_SceneBoundingBox.m_MinP = scene->m_boundingBox.GetMinP(); + m_viewerWindow->m_CCamera->m_SceneBoundingBox.m_MaxP = scene->m_boundingBox.GetMaxP(); // reposition to face image - m_viewerWindow->m_CCamera.SetViewMode(ViewModeFront); + m_viewerWindow->m_CCamera->SetViewMode(ViewModeFront); RenderSettings* rs = m_viewerWindow->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); @@ -92,14 +94,14 @@ GLView3D::retargetCameraForNewVolume(Scene* scene) { // ASSUMPTION camera's sceneboundingbox has not yet been updated! - glm::vec3 oldctr = m_viewerWindow->m_CCamera.m_SceneBoundingBox.GetCenter(); + glm::vec3 oldctr = m_viewerWindow->m_CCamera->m_SceneBoundingBox.GetCenter(); // Tell the camera about the volume's bounding box - m_viewerWindow->m_CCamera.m_SceneBoundingBox.m_MinP = scene->m_boundingBox.GetMinP(); - m_viewerWindow->m_CCamera.m_SceneBoundingBox.m_MaxP = scene->m_boundingBox.GetMaxP(); + m_viewerWindow->m_CCamera->m_SceneBoundingBox.m_MinP = scene->m_boundingBox.GetMinP(); + m_viewerWindow->m_CCamera->m_SceneBoundingBox.m_MaxP = scene->m_boundingBox.GetMaxP(); // reposition target to center of image - glm::vec3 ctr = m_viewerWindow->m_CCamera.m_SceneBoundingBox.GetCenter(); + glm::vec3 ctr = m_viewerWindow->m_CCamera->m_SceneBoundingBox.GetCenter(); // offset target by delta of prev bounds and new bounds. - m_viewerWindow->m_CCamera.m_Target += (ctr - oldctr); + m_viewerWindow->m_CCamera->m_Target += (ctr - oldctr); RenderSettings* rs = m_viewerWindow->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); @@ -108,8 +110,8 @@ GLView3D::retargetCameraForNewVolume(Scene* scene) void GLView3D::toggleCameraProjection() { - ProjectionMode p = m_viewerWindow->m_CCamera.m_Projection; - m_viewerWindow->m_CCamera.SetProjectionMode((p == PERSPECTIVE) ? ORTHOGRAPHIC : PERSPECTIVE); + ProjectionMode p = m_viewerWindow->m_CCamera->m_Projection; + m_viewerWindow->m_CCamera->SetProjectionMode((p == PERSPECTIVE) ? ORTHOGRAPHIC : PERSPECTIVE); RenderSettings* rs = m_viewerWindow->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); @@ -305,11 +307,11 @@ GLView3D::FitToScene(float transitionDurationSeconds) } glm::vec3 newPosition, newTarget; - m_viewerWindow->m_CCamera.ComputeFitToBounds(sc->m_boundingBox, newPosition, newTarget); + m_viewerWindow->m_CCamera->ComputeFitToBounds(sc->m_boundingBox, newPosition, newTarget); CameraAnimation anim = {}; anim.duration = transitionDurationSeconds; - anim.mod.position = newPosition - m_viewerWindow->m_CCamera.m_From; - anim.mod.target = newTarget - m_viewerWindow->m_CCamera.m_Target; + anim.mod.position = newPosition - m_viewerWindow->m_CCamera->m_From; + anim.mod.target = newTarget - m_viewerWindow->m_CCamera->m_Target; m_viewerWindow->m_cameraAnim.push_back(anim); } @@ -467,18 +469,18 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) m_qrendersettings->SetRendererType(s.rendererType == Serialize::RendererType_PID::PATHTRACE ? 1 : 0); // syntactic sugar - CCamera& camera = m_viewerWindow->m_CCamera; + std::shared_ptr& camera = m_viewerWindow->m_CCamera; - camera.m_From = glm::vec3(s.camera.eye[0], s.camera.eye[1], s.camera.eye[2]); - camera.m_Target = glm::vec3(s.camera.target[0], s.camera.target[1], s.camera.target[2]); - camera.m_Up = glm::vec3(s.camera.up[0], s.camera.up[1], s.camera.up[2]); - camera.m_FovV = s.camera.fovY; - camera.SetProjectionMode(s.camera.projection == Serialize::Projection_PID::PERSPECTIVE ? PERSPECTIVE : ORTHOGRAPHIC); - camera.m_OrthoScale = s.camera.orthoScale; + camera->m_From = glm::vec3(s.camera.eye[0], s.camera.eye[1], s.camera.eye[2]); + camera->m_Target = glm::vec3(s.camera.target[0], s.camera.target[1], s.camera.target[2]); + camera->m_Up = glm::vec3(s.camera.up[0], s.camera.up[1], s.camera.up[2]); + camera->m_FovV = s.camera.fovY; + camera->SetProjectionMode(s.camera.projection == Serialize::Projection_PID::PERSPECTIVE ? PERSPECTIVE : ORTHOGRAPHIC); + camera->m_OrthoScale = s.camera.orthoScale; - camera.m_Film.m_Exposure = s.camera.exposure; - camera.m_Aperture.m_Size = s.camera.aperture; - camera.m_Focus.m_FocalDistance = s.camera.focalDistance; + camera->m_Film.m_Exposure = s.camera.exposure; + camera->m_Aperture.m_Size = s.camera.aperture; + camera->m_Focus.m_FocalDistance = s.camera.focalDistance; // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! m_cameraDataObject->updatePropsFromObject(); @@ -535,7 +537,7 @@ GLView3D::captureQimage() // fill gesture graphics with draw commands m_viewerWindow->update(m_viewerWindow->sceneView.viewport, m_viewerWindow->m_clock, m_viewerWindow->gesture); - m_viewerWindow->m_renderer->render(m_viewerWindow->m_CCamera); + m_viewerWindow->m_renderer->render(*m_viewerWindow->m_CCamera); // render and then clear out draw commands from gesture graphics m_viewerWindow->m_gestureRenderer->draw( m_viewerWindow->sceneView, &m_viewerWindow->m_selection, m_viewerWindow->gesture.graphics); diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index 4de114a4..47addab0 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -66,7 +66,7 @@ class GLView3D : public QOpenGLWidget void onNewImage(Scene* scene); - const CCamera& getCamera() { return m_viewerWindow->m_CCamera; } + const CCamera& getCamera() { return *m_viewerWindow->m_CCamera; } // tied to the above camera. CCamera must outlive this: CameraObject* getCameraDataObject() { return m_cameraDataObject; } AppearanceObject* getAppearanceDataObject() { return m_appearanceDataObject; } diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 36164112..54887fbc 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -939,14 +939,14 @@ agaveGui::view_frame() void agaveGui::view_top() { - m_glView->borrowRenderer()->m_CCamera.SetViewMode(ViewModeTop); + m_glView->borrowRenderer()->m_CCamera->SetViewMode(ViewModeTop); RenderSettings* rs = m_glView->borrowRenderer()->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); } void agaveGui::view_bottom() { - m_glView->borrowRenderer()->m_CCamera.SetViewMode(ViewModeBottom); + m_glView->borrowRenderer()->m_CCamera->SetViewMode(ViewModeBottom); RenderSettings* rs = m_glView->borrowRenderer()->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); } @@ -954,7 +954,7 @@ agaveGui::view_bottom() void agaveGui::view_front() { - m_glView->borrowRenderer()->m_CCamera.SetViewMode(ViewModeFront); + m_glView->borrowRenderer()->m_CCamera->SetViewMode(ViewModeFront); RenderSettings* rs = m_glView->borrowRenderer()->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); } @@ -962,7 +962,7 @@ agaveGui::view_front() void agaveGui::view_back() { - m_glView->borrowRenderer()->m_CCamera.SetViewMode(ViewModeBack); + m_glView->borrowRenderer()->m_CCamera->SetViewMode(ViewModeBack); RenderSettings* rs = m_glView->borrowRenderer()->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); } @@ -970,7 +970,7 @@ agaveGui::view_back() void agaveGui::view_left() { - m_glView->borrowRenderer()->m_CCamera.SetViewMode(ViewModeLeft); + m_glView->borrowRenderer()->m_CCamera->SetViewMode(ViewModeLeft); RenderSettings* rs = m_glView->borrowRenderer()->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); } @@ -978,7 +978,7 @@ agaveGui::view_left() void agaveGui::view_right() { - m_glView->borrowRenderer()->m_CCamera.SetViewMode(ViewModeRight); + m_glView->borrowRenderer()->m_CCamera->SetViewMode(ViewModeRight); RenderSettings* rs = m_glView->borrowRenderer()->m_renderSettings; rs->m_DirtyFlags.SetFlag(CameraDirty); } diff --git a/renderlib/CameraUiDescription.cpp b/renderlib/CameraUiDescription.cpp index fb22ca64..2bcc7793 100644 --- a/renderlib/CameraUiDescription.cpp +++ b/renderlib/CameraUiDescription.cpp @@ -157,11 +157,13 @@ void CameraObject::ExposureChanged(prtyProperty* i_Property, bool i_bDirty) { m_camera->m_Film.m_Exposure = 1.0f - m_cameraDataObject.Exposure.GetValue(); + m_camera->m_Dirty = true; } void CameraObject::ExposureIterationsChanged(prtyProperty* i_Property, bool i_bDirty) { m_camera->m_Film.m_ExposureIterations = m_cameraDataObject.ExposureIterations.GetValue(); + m_camera->m_Dirty = true; } void CameraObject::NoiseReductionChanged(prtyProperty* i_Property, bool i_bDirty) @@ -172,14 +174,17 @@ void CameraObject::ApertureSizeChanged(prtyProperty* i_Property, bool i_bDirty) { m_camera->m_Aperture.m_Size = m_cameraDataObject.ApertureSize.GetValue(); + m_camera->m_Dirty = true; } void CameraObject::FieldOfViewChanged(prtyProperty* i_Property, bool i_bDirty) { m_camera->m_FovV = m_cameraDataObject.FieldOfView.GetValue(); + m_camera->m_Dirty = true; } void CameraObject::FocalDistanceChanged(prtyProperty* i_Property, bool i_bDirty) { m_camera->m_Focus.m_FocalDistance = m_cameraDataObject.FocalDistance.GetValue(); + m_camera->m_Dirty = true; } diff --git a/renderlib/CameraUiDescription.hpp b/renderlib/CameraUiDescription.hpp index e34a16b1..f61eedb8 100644 --- a/renderlib/CameraUiDescription.hpp +++ b/renderlib/CameraUiDescription.hpp @@ -35,6 +35,9 @@ class CameraObject : public prtyObject FloatSliderSpinnerUiInfo* getFieldOfViewUIInfo() { return m_FieldOfViewUIInfo; } FloatSliderSpinnerUiInfo* getFocalDistanceUIInfo() { return m_FocalDistanceUIInfo; } + // Getter for the camera + std::shared_ptr getCamera() const { return m_camera; } + private: // the properties CameraDataObject m_cameraDataObject; diff --git a/renderlib/ViewerWindow.cpp b/renderlib/ViewerWindow.cpp index 044c986a..4968cd23 100644 --- a/renderlib/ViewerWindow.cpp +++ b/renderlib/ViewerWindow.cpp @@ -17,6 +17,7 @@ ViewerWindow::ViewerWindow(RenderSettings* rs) : m_renderSettings(rs) , m_renderer(new RenderGLPT(rs)) , m_gestureRenderer(new GestureRendererGL()) + , m_CCamera(std::make_shared()) { gesture.input.reset(); @@ -88,7 +89,7 @@ ViewerWindow::updateCamera() bool cameraEdit = cameraManipulation(glm::vec2(width(), height()), // m_clock, gesture, - m_CCamera, + *m_CCamera, cameraMod); // Apply camera animation transitions if we have any if (!m_cameraAnim.empty()) { @@ -104,7 +105,7 @@ ViewerWindow::updateCamera() ++it; } else { // Completed animation is applied to the camera instead - m_CCamera = m_CCamera + anim.mod; + *m_CCamera = *m_CCamera + anim.mod; it = m_cameraAnim.erase(it); } @@ -122,14 +123,14 @@ ViewerWindow::updateCamera() // to set the renderSettings dirty flag. This could be a bit more direct // if the CameraDataObject had access to the renderSettings object. // (or a dirtyflags global interface) - if (m_CCamera.m_Dirty) { + if (m_CCamera->m_Dirty) { m_renderSettings->m_DirtyFlags.SetFlag(CameraDirty); - m_CCamera.m_Dirty = false; + m_CCamera->m_Dirty = false; } - CCamera renderCamera = m_CCamera; + CCamera renderCamera = *m_CCamera; if (cameraEdit) { - renderCamera = m_CCamera + cameraMod; + renderCamera = *m_CCamera + cameraMod; } // renderCamera.Update(); if (cameraEdit) { @@ -272,12 +273,12 @@ ViewerWindow::redraw() if (width() != oldpickbuffersize.x || height() != oldpickbuffersize.y || width() != oldrendererwidth || height() != oldrendererheight) { m_renderer->resize(width(), height()); - m_CCamera.m_Film.m_Resolution.SetResX(width()); - m_CCamera.m_Film.m_Resolution.SetResY(height()); + m_CCamera->m_Film.m_Resolution.SetResX(width()); + m_CCamera->m_Film.m_Resolution.SetResY(height()); } sceneView.viewport.region = { { 0, 0 }, { width(), height() } }; - sceneView.camera = m_CCamera; + sceneView.camera = *m_CCamera; sceneView.scene = m_renderer->scene(); sceneView.renderSettings = m_renderSettings; diff --git a/renderlib/ViewerWindow.h b/renderlib/ViewerWindow.h index 1aa23f97..cd8b0a54 100644 --- a/renderlib/ViewerWindow.h +++ b/renderlib/ViewerWindow.h @@ -7,6 +7,7 @@ #include "gesture/gesture.h" #include +#include class RenderSettings; class IRenderWindow; @@ -59,7 +60,7 @@ class ViewerWindow void updateCamera(); - CCamera m_CCamera; + std::shared_ptr m_CCamera; std::vector m_cameraAnim; Gesture gesture; From 08be5ef1f7f2685322ddb3f5596c036e33bedbf9 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Thu, 3 Jul 2025 16:58:38 -0700 Subject: [PATCH 34/60] try to disconnect properties on control deletion --- agave_app/qtControls/controlFactory.cpp | 102 +++++++----------------- agave_app/qtControls/controlFactory.h | 12 --- 2 files changed, 30 insertions(+), 84 deletions(-) diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index 8c61dbb7..4f2ac621 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -7,68 +7,6 @@ #include -QNumericSlider* -create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop) -{ - QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info->GetStatusTip())); - slider->setToolTip(QString::fromStdString(info->GetToolTip())); - slider->setRange(info->min, info->max); - slider->setDecimals(info->decimals); - slider->setSingleStep(info->singleStep); - slider->setNumTickMarks(info->numTickMarks); - slider->setSuffix(QString::fromStdString(info->suffix)); - - slider->setValue(prop->GetValue(), true); - QObject::connect( - slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - - return slider; -} -QNumericSlider* -create(const IntSliderSpinnerUiInfo* info, std::shared_ptr prop) -{ - QNumericSlider* slider = new QNumericSlider(); - slider->setStatusTip(QString::fromStdString(info->GetStatusTip())); - slider->setToolTip(QString::fromStdString(info->GetToolTip())); - slider->setRange(info->min, info->max); - slider->setSingleStep(info->singleStep); - slider->setNumTickMarks(info->numTickMarks); - slider->setSuffix(QString::fromStdString(info->suffix)); - - slider->setValue(prop->GetValue(), true); - QObject::connect( - slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - - return slider; -} -QCheckBox* -create(const CheckBoxUiInfo* info, std::shared_ptr prop) -{ - QCheckBox* checkBox = new QCheckBox(); - checkBox->setStatusTip(QString::fromStdString(info->GetStatusTip())); - checkBox->setToolTip(QString::fromStdString(info->GetToolTip())); - checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { - prop->SetValue(state == Qt::CheckState::Checked, true); - }); - return checkBox; -} -QComboBox* -create(const ComboBoxUiInfo* info, std::shared_ptr prop) -{ - QComboBox* comboBox = new QComboBox(); - comboBox->setStatusTip(QString::fromStdString(info->GetStatusTip())); - comboBox->setToolTip(QString::fromStdString(info->GetToolTip())); - for (const auto& item : info->items) { - comboBox->addItem(QString::fromStdString(item)); - } - comboBox->setCurrentIndex(prop->GetValue()); - QObject::connect( - comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->SetValue(index, true); }); - return comboBox; -} - QNumericSlider* addRow(const FloatSliderSpinnerUiInfo& info) { @@ -83,9 +21,12 @@ addRow(const FloatSliderSpinnerUiInfo& info) auto* prop = static_cast(info.GetProperty(0)); slider->setValue(prop->GetValue(), true); - QObject::connect( + auto conn = QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - + QObject::connect(slider, &QNumericSlider::destroyed, [conn]() { + // Disconnect the signal when the slider is destroyed + QObject::disconnect(conn); + }); return slider; } QNumericSlider* @@ -101,9 +42,12 @@ addRow(const IntSliderSpinnerUiInfo& info) auto* prop = static_cast(info.GetProperty(0)); slider->setValue(prop->GetValue(), true); - QObject::connect( + auto conn = QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); - + QObject::connect(slider, &QNumericSlider::destroyed, [conn]() { + // Disconnect the signal when the slider is destroyed + QObject::disconnect(conn); + }); return slider; } @@ -118,8 +62,12 @@ addRow(const ComboBoxUiInfo& info) } auto* prop = static_cast(info.GetProperty(0)); comboBox->setCurrentIndex(prop->GetValue()); - QObject::connect( + auto conn = QObject::connect( comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->SetValue(index, true); }); + QObject::connect(comboBox, &QComboBox::destroyed, [conn]() { + // Disconnect the signal when the combobox is destroyed + QObject::disconnect(conn); + }); return comboBox; } @@ -131,9 +79,13 @@ addRow(const CheckBoxUiInfo& info) checkBox->setToolTip(QString::fromStdString(info.GetToolTip())); auto* prop = static_cast(info.GetProperty(0)); checkBox->setCheckState(prop->GetValue() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { + auto conn = QObject::connect(checkBox, &QCheckBox::stateChanged, [checkBox, prop](int state) { prop->SetValue(state == Qt::CheckState::Checked, true); }); + QObject::connect(checkBox, &QCheckBox::destroyed, [conn]() { + // Disconnect the signal when the checkbox is destroyed + QObject::disconnect(conn); + }); return checkBox; } @@ -146,10 +98,15 @@ addRow(const ColorPickerUiInfo& info) auto* prop = static_cast(info.GetProperty(0)); QColor c = QColor::fromRgbF(prop->GetValue().r, prop->GetValue().g, prop->GetValue().b); colorButton->SetColor(c, true); - QObject::connect(colorButton, &QColorPushButton::currentColorChanged, [colorButton, prop](const QColor& c) { - // Convert QColor to glm::vec3 - glm::vec4 color(c.redF(), c.greenF(), c.blueF(), 1.0f); - prop->SetValue(color, true); + auto conn = + QObject::connect(colorButton, &QColorPushButton::currentColorChanged, [colorButton, prop](const QColor& c) { + // Convert QColor to glm::vec3 + glm::vec4 color(c.redF(), c.greenF(), c.blueF(), 1.0f); + prop->SetValue(color, true); + }); + QObject::connect(colorButton, &QColorPushButton::destroyed, [conn]() { + // Disconnect the signal when the button is destroyed + QObject::disconnect(conn); }); return colorButton; } @@ -171,6 +128,7 @@ addGenericRow(const prtyPropertyUIInfo& info) } else if (const auto* colorPickerInfo = dynamic_cast(&info)) { return addRow(*colorPickerInfo); } + return nullptr; // or throw an exception } diff --git a/agave_app/qtControls/controlFactory.h b/agave_app/qtControls/controlFactory.h index 36ca0151..5d8b8ea3 100644 --- a/agave_app/qtControls/controlFactory.h +++ b/agave_app/qtControls/controlFactory.h @@ -18,18 +18,6 @@ class QColorPushButton; class QFormLayout; class QWidget; -QNumericSlider* -create(const FloatSliderSpinnerUiInfo* info, std::shared_ptr prop); - -QNumericSlider* -create(const IntSliderSpinnerUiInfo* info, std::shared_ptr prop); - -QCheckBox* -create(const CheckBoxUiInfo* info, std::shared_ptr prop); - -QComboBox* -create(const ComboBoxUiInfo* info, std::shared_ptr prop); - QNumericSlider* addRow(const FloatSliderSpinnerUiInfo& info); From 67ad37f179c3545e997eba2d425f65003c59e503 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Thu, 3 Jul 2025 17:09:11 -0700 Subject: [PATCH 35/60] clean up gui --- agave_app/agaveGui.h | 2 ++ agave_app/main.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h index fa8dba50..839ea113 100644 --- a/agave_app/agaveGui.h +++ b/agave_app/agaveGui.h @@ -88,6 +88,8 @@ private slots: MaxRecentFiles = 8 }; + // there is a concept of a serializable document and it can be captured from current app state, + // or loaded from a file and then applied to the app state. Serialize::ViewerState appToViewerState(); void viewerStateToApp(const Serialize::ViewerState& s); diff --git a/agave_app/main.cpp b/agave_app/main.cpp index 4f52cfe1..fe1ec953 100644 --- a/agave_app/main.cpp +++ b/agave_app/main.cpp @@ -259,6 +259,7 @@ main(int argc, char* argv[]) MainWindow* _ = new MainWindow(server); _->resize(512, 512); _->show(); + delete _; } LOG_INFO << "Created server at working directory:" << QDir::currentPath().toStdString(); @@ -280,6 +281,7 @@ main(int argc, char* argv[]) w->open(fileToLoad); } result = a.exec(); + delete w; } } catch (const std::exception& exc) { LOG_ERROR << "Exception caught in main: " << exc.what(); From 9ed558034e986e4a7464f6bbca7d21d9ba22359c Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 08:39:08 -0700 Subject: [PATCH 36/60] more object lifetime work with camera --- agave_app/GLView3D.cpp | 24 +++++++++++++++++------- agave_app/GLView3D.h | 5 +++-- agave_app/agaveGui.cpp | 17 +++++++++++++---- agave_app/agaveGui.h | 20 ++++++++++++++------ 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 9355504d..fa4ec8a8 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -42,11 +42,6 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidg m_viewerWindow = new ViewerWindow(rs); m_viewerWindow->gesture.input.setDoubleClickTime((double)QApplication::doubleClickInterval() / 1000.0); - // camera is created deep down inside m_viewerWindow. - m_cameraDataObject = new CameraObject(); - m_viewerWindow->m_CCamera = m_cameraDataObject->getCamera(); - - // m_cameraDataObject->setExternalCamera(&m_viewerWindow->m_CCamera); m_appearanceDataObject = new AppearanceObject(); setFocusPolicy(Qt::StrongFocus); @@ -117,6 +112,22 @@ GLView3D::toggleCameraProjection() rs->m_DirtyFlags.SetFlag(CameraDirty); } +void +GLView3D::setCameraObject(CameraObject* cameraObject) +{ + if (cameraObject != nullptr) { + // Set the new camera object (don't delete the old one as we don't own it) + m_cameraObject = cameraObject; + + // Update the internal camera reference + m_viewerWindow->m_CCamera = m_cameraObject->getCamera(); + + // Mark camera as dirty to trigger updates + RenderSettings* rs = m_viewerWindow->m_renderSettings; + rs->m_DirtyFlags.SetFlag(CameraDirty); + } +} + void GLView3D::onNewImage(Scene* scene) { @@ -131,7 +142,6 @@ GLView3D::onNewImage(Scene* scene) GLView3D::~GLView3D() { - delete m_cameraDataObject; delete m_appearanceDataObject; makeCurrent(); @@ -483,7 +493,7 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) camera->m_Focus.m_FocalDistance = s.camera.focalDistance; // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! - m_cameraDataObject->updatePropsFromObject(); + m_cameraObject->updatePropsFromObject(); m_appearanceDataObject->updatePropsFromObject(); } diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index 47addab0..d1480c17 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -68,7 +68,8 @@ class GLView3D : public QOpenGLWidget const CCamera& getCamera() { return *m_viewerWindow->m_CCamera; } // tied to the above camera. CCamera must outlive this: - CameraObject* getCameraDataObject() { return m_cameraDataObject; } + // CameraObject* getCameraDataObject() { return m_cameraObject; } + void setCameraObject(CameraObject* cameraObject); AppearanceObject* getAppearanceDataObject() { return m_appearanceDataObject; } void fromViewerState(const Serialize::ViewerState& s); @@ -112,7 +113,7 @@ public slots: void wheelEvent(QWheelEvent* event); private: - CameraObject* m_cameraDataObject; + CameraObject* m_cameraObject; AppearanceObject* m_appearanceDataObject; QRenderSettings* m_qrendersettings; diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 54887fbc..b8742cb6 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -12,6 +12,8 @@ #include "renderlib/VolumeDimensions.h" #include "renderlib/io/FileReader.h" #include "renderlib/version.hpp" +#include "renderlib/CameraUiDescription.hpp" +#include "renderlib/AppearanceUiDescription.hpp" #include "AppearanceDockWidget.h" #include "AppearanceDockWidget2.h" @@ -82,6 +84,10 @@ QMenu#quickViewsMenu {border-radius: 2px;} agaveGui::agaveGui(QWidget* parent) : QMainWindow(parent) { + // create our two document objects + m_cameraObject = std::make_unique(); + m_appearanceObject = std::make_unique(); + m_ui.setupUi(this); setDockOptions(AllowTabbedDocks); @@ -118,11 +124,10 @@ agaveGui::agaveGui(QWidget* parent) // We need a minimum size or else the size defaults to zero. m_glView->setMinimumSize(256, 512); m_glView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - // create camera ui window now that there is an actual camera. - setupCameraDock(m_glView->getCameraDataObject()); + m_glView->setCameraObject(m_cameraObject.get()); // create camera ui window now that there is an actual camera. - setupCameraDock(m_glView->getCameraDataObject()); + setupCameraDock(m_cameraObject.get()); setupTimelineDock(); setupStatisticsDock(); setupAppearanceDock(m_glView->getAppearanceDataObject()); @@ -166,6 +171,10 @@ agaveGui::agaveGui(QWidget* parent) resize(width * 0.8, height * 0.8); // consider resizeDocks to widen the appearance dock } +agaveGui::~agaveGui() +{ + // Clean up any allocated resources +} void agaveGui::OnUpdateRenderer() @@ -1325,7 +1334,7 @@ agaveGui::appToViewerState() v.camera.projection = m_glView->getCamera().m_Projection == PERSPECTIVE ? Serialize::Projection_PID::PERSPECTIVE : Serialize::Projection_PID::ORTHOGRAPHIC; v.camera.orthoScale = m_glView->getCamera().m_OrthoScale; - CameraObject* cdo = m_glView->getCameraDataObject(); + CameraObject* cdo = m_cameraObject.get(); v.camera.fovY = cdo->getCameraDataObject().FieldOfView.GetValue(); v.camera.exposure = cdo->getCameraDataObject().Exposure.GetValue(); v.camera.aperture = cdo->getCameraDataObject().ApertureSize.GetValue(); diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h index 839ea113..66716c96 100644 --- a/agave_app/agaveGui.h +++ b/agave_app/agaveGui.h @@ -30,6 +30,7 @@ class agaveGui : public QMainWindow public: agaveGui(QWidget* parent = Q_NULLPTR); + ~agaveGui(); bool open(const std::string& file, const Serialize::ViewerState* vs = nullptr, bool isImageSequence = false); @@ -149,6 +150,7 @@ private slots: QTimelineDockWidget* m_timelinedock; QRenderSettings m_qrendersettings; + QAppearanceDockWidget* m_appearanceDockWidget; QAppearanceDockWidget2* m_appearanceDockWidget2; @@ -159,6 +161,16 @@ private slots: ViewToolbar* m_viewToolbar; QWidget* m_viewWithToolbar; + QAction* m_recentFileActs[MaxRecentFiles]; + QAction* m_recentFileSeparator; + QAction* m_recentFileSubMenuAct; + + Qt::ColorScheme m_colorScheme; + + /////////////////////// + // Objects related to the app state + /////////////////////// + // THE underlying render settings container. // There is only one of these. The app owns it and hands refs to the ui widgets and the renderer. // if renderer is on a separate thread, then this will need a mutex guard @@ -172,14 +184,10 @@ private slots: // scene gets sent down to the renderer. Scene m_appScene; int m_currentScene = 0; - - QAction* m_recentFileActs[MaxRecentFiles]; - QAction* m_recentFileSeparator; - QAction* m_recentFileSubMenuAct; + std::unique_ptr m_cameraObject; + std::unique_ptr m_appearanceObject; std::string m_currentFilePath; // TODO remove the above m_currentFilePath and use this instead LoadSpec m_loadSpec; - - Qt::ColorScheme m_colorScheme; }; From d1a78be6250acea37cb1116b35e194e7c6d9f590 Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 09:55:23 -0700 Subject: [PATCH 37/60] rename --- agave_app/AppearanceWidget.cpp | 2 +- agave_app/AppearanceWidget.h | 2 +- agave_app/CameraWidget.cpp | 1 + agave_app/CameraWidget.h | 2 +- agave_app/GLView3D.cpp | 4 ++-- agave_app/agaveGui.cpp | 4 ++-- .../{AppearanceUiDescription.cpp => AppearanceObject.cpp} | 0 .../{AppearanceUiDescription.hpp => AppearanceObject.hpp} | 0 renderlib/CMakeLists.txt | 6 ++++-- renderlib/{CameraUiDescription.cpp => CameraObject.cpp} | 0 renderlib/{CameraUiDescription.hpp => CameraObject.hpp} | 0 11 files changed, 12 insertions(+), 9 deletions(-) rename renderlib/{AppearanceUiDescription.cpp => AppearanceObject.cpp} (100%) rename renderlib/{AppearanceUiDescription.hpp => AppearanceObject.hpp} (100%) rename renderlib/{CameraUiDescription.cpp => CameraObject.cpp} (100%) rename renderlib/{CameraUiDescription.hpp => CameraObject.hpp} (100%) diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index b0d48002..7d816763 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -4,7 +4,7 @@ #include "qtControls/controlFactory.h" #include "renderlib/uiInfo.hpp" -#include "renderlib/AppearanceUiDescription.hpp" +#include "renderlib/AppearanceObject.hpp" #include "renderlib/ViewerWindow.h" #include diff --git a/agave_app/AppearanceWidget.h b/agave_app/AppearanceWidget.h index c059424b..6e943119 100644 --- a/agave_app/AppearanceWidget.h +++ b/agave_app/AppearanceWidget.h @@ -3,7 +3,7 @@ #include "qtControls/Controls.h" // #include "renderlib/core/prty/prtyProperty.h" -#include "renderlib/AppearanceUiDescription.hpp" +#include "renderlib/AppearanceObject.hpp" #include "renderlib/Logging.h" #include diff --git a/agave_app/CameraWidget.cpp b/agave_app/CameraWidget.cpp index 56aea443..6078af46 100644 --- a/agave_app/CameraWidget.cpp +++ b/agave_app/CameraWidget.cpp @@ -5,6 +5,7 @@ #include "qtControls/Section.h" #include "renderlib/uiInfo.hpp" +#include "renderlib/CameraObject.hpp" #include #include diff --git a/agave_app/CameraWidget.h b/agave_app/CameraWidget.h index 5592afb0..35ed6fdb 100644 --- a/agave_app/CameraWidget.h +++ b/agave_app/CameraWidget.h @@ -4,7 +4,7 @@ #include "qtControls/Controls.h" // #include "renderlib/core/prty/prtyProperty.h" -#include "renderlib/CameraUiDescription.hpp" +#include "renderlib/CameraObject.hpp" #include "renderlib/Logging.h" #include diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index fa4ec8a8..2eb80b9e 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -3,8 +3,8 @@ #include "QRenderSettings.h" #include "ViewerState.h" -#include "renderlib/AppearanceUiDescription.hpp" -#include "renderlib/CameraUiDescription.hpp" +#include "renderlib/AppearanceObject.hpp" +#include "renderlib/CameraObject.hpp" #include "renderlib/ImageXYZC.h" #include "renderlib/Logging.h" #include "renderlib/MoveTool.h" diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index b8742cb6..c1211f6c 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -12,8 +12,8 @@ #include "renderlib/VolumeDimensions.h" #include "renderlib/io/FileReader.h" #include "renderlib/version.hpp" -#include "renderlib/CameraUiDescription.hpp" -#include "renderlib/AppearanceUiDescription.hpp" +#include "renderlib/CameraObject.hpp" +#include "renderlib/AppearanceObject.hpp" #include "AppearanceDockWidget.h" #include "AppearanceDockWidget2.h" diff --git a/renderlib/AppearanceUiDescription.cpp b/renderlib/AppearanceObject.cpp similarity index 100% rename from renderlib/AppearanceUiDescription.cpp rename to renderlib/AppearanceObject.cpp diff --git a/renderlib/AppearanceUiDescription.hpp b/renderlib/AppearanceObject.hpp similarity index 100% rename from renderlib/AppearanceUiDescription.hpp rename to renderlib/AppearanceObject.hpp diff --git a/renderlib/CMakeLists.txt b/renderlib/CMakeLists.txt index d005e867..38180589 100644 --- a/renderlib/CMakeLists.txt +++ b/renderlib/CMakeLists.txt @@ -16,8 +16,8 @@ target_include_directories(renderlib PUBLIC target_sources(renderlib PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDataObject.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceDataObject.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceUiDescription.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceUiDescription.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceObject.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/AppearanceObject.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppScene.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AppScene.h" "${CMAKE_CURRENT_SOURCE_DIR}/AreaLightTool.cpp" @@ -32,6 +32,8 @@ target_sources(renderlib PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/CCamera.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/CameraDataObject.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/CameraDataObject.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/CameraObject.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/CameraObject.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/ClipPlaneTool.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ClipPlaneTool.h" "${CMAKE_CURRENT_SOURCE_DIR}/Colormap.cpp" diff --git a/renderlib/CameraUiDescription.cpp b/renderlib/CameraObject.cpp similarity index 100% rename from renderlib/CameraUiDescription.cpp rename to renderlib/CameraObject.cpp diff --git a/renderlib/CameraUiDescription.hpp b/renderlib/CameraObject.hpp similarity index 100% rename from renderlib/CameraUiDescription.hpp rename to renderlib/CameraObject.hpp From f0fc52a8a0e524308e82dacfab760ea9b906391c Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 09:56:07 -0700 Subject: [PATCH 38/60] renaming --- renderlib/AppearanceObject.cpp | 2 +- renderlib/CameraObject.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/renderlib/AppearanceObject.cpp b/renderlib/AppearanceObject.cpp index 7fe499f7..5488fdab 100644 --- a/renderlib/AppearanceObject.cpp +++ b/renderlib/AppearanceObject.cpp @@ -1,4 +1,4 @@ -#include "AppearanceUiDescription.hpp" +#include "AppearanceObject.hpp" #include "Logging.h" // ComboBoxUiInfo AppearanceUiDescription::m_rendererType("Renderer Type", diff --git a/renderlib/CameraObject.cpp b/renderlib/CameraObject.cpp index 2bcc7793..05712b7e 100644 --- a/renderlib/CameraObject.cpp +++ b/renderlib/CameraObject.cpp @@ -1,4 +1,4 @@ -#include "CameraUiDescription.hpp" +#include "CameraObject.hpp" #include "Logging.h" From 62881f8274ccc5e0c35e3a54a536f5131314a876 Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 09:56:25 -0700 Subject: [PATCH 39/60] wip --- agave_app/GLView3D.cpp | 8 ++++---- agave_app/GLView3D.h | 2 -- agave_app/agaveGui.cpp | 5 ++++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 2eb80b9e..f26a1a99 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -42,8 +42,6 @@ GLView3D::GLView3D(QRenderSettings* qrs, RenderSettings* rs, Scene* scene, QWidg m_viewerWindow = new ViewerWindow(rs); m_viewerWindow->gesture.input.setDoubleClickTime((double)QApplication::doubleClickInterval() / 1000.0); - m_appearanceDataObject = new AppearanceObject(); - setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); @@ -142,8 +140,6 @@ GLView3D::onNewImage(Scene* scene) GLView3D::~GLView3D() { - delete m_appearanceDataObject; - makeCurrent(); check_gl("view dtor makecurrent"); // doneCurrent(); @@ -481,6 +477,10 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) // syntactic sugar std::shared_ptr& camera = m_viewerWindow->m_CCamera; + /////////////////// + // TODO do all of this through the camera object's properties!!!!!!!!! + /////////////////// + camera->m_From = glm::vec3(s.camera.eye[0], s.camera.eye[1], s.camera.eye[2]); camera->m_Target = glm::vec3(s.camera.target[0], s.camera.target[1], s.camera.target[2]); camera->m_Up = glm::vec3(s.camera.up[0], s.camera.up[1], s.camera.up[2]); diff --git a/agave_app/GLView3D.h b/agave_app/GLView3D.h index d1480c17..91b7b0c3 100644 --- a/agave_app/GLView3D.h +++ b/agave_app/GLView3D.h @@ -70,7 +70,6 @@ class GLView3D : public QOpenGLWidget // tied to the above camera. CCamera must outlive this: // CameraObject* getCameraDataObject() { return m_cameraObject; } void setCameraObject(CameraObject* cameraObject); - AppearanceObject* getAppearanceDataObject() { return m_appearanceDataObject; } void fromViewerState(const Serialize::ViewerState& s); @@ -114,7 +113,6 @@ public slots: private: CameraObject* m_cameraObject; - AppearanceObject* m_appearanceDataObject; QRenderSettings* m_qrendersettings; /// Rendering timer. diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index c1211f6c..65412861 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -130,7 +130,7 @@ agaveGui::agaveGui(QWidget* parent) setupCameraDock(m_cameraObject.get()); setupTimelineDock(); setupStatisticsDock(); - setupAppearanceDock(m_glView->getAppearanceDataObject()); + setupAppearanceDock(m_appearanceObject.get()); addDockItemsToViewMenu(); @@ -1171,6 +1171,8 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v) { // ASSUME THAT IMAGE IS LOADED AND APPSCENE INITIALIZED + m_appearanceObject->updatePropsFromObject(); + // position camera m_glView->fromViewerState(v); m_viewToolbar->initFromCamera(m_glView->getCamera()); @@ -1210,6 +1212,7 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v) m_appScene.m_material.m_showBoundingBox = v.showBoundingBox; m_appScene.m_showScaleBar = v.showScaleBar; + /////////////// TODO set these through props in the AppearanceObject m_renderSettings.m_RenderSettings.m_DensityScale = v.density; m_renderSettings.m_RenderSettings.m_StepSizeFactor = v.pathTracer.primaryStepSize; m_renderSettings.m_RenderSettings.m_StepSizeFactorShadow = v.pathTracer.secondaryStepSize; From cb9310c2488b5ffb7a4652e8e0a376458c83b387 Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 09:58:22 -0700 Subject: [PATCH 40/60] fix compile --- agave_app/GLView3D.cpp | 4 ---- agave_app/agaveGui.cpp | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index f26a1a99..1f520aaf 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -134,8 +134,6 @@ GLView3D::onNewImage(Scene* scene) this->OnUpdateRenderer(m_viewerWindow->m_renderSettings->m_rendererType); // would be better to preserve renderer and just change the scene data to include the new image. // how tightly coupled is renderer and scene???? - - m_appearanceDataObject->updatePropsFromObject(); } GLView3D::~GLView3D() @@ -494,8 +492,6 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! m_cameraObject->updatePropsFromObject(); - - m_appearanceDataObject->updatePropsFromObject(); } QPixmap diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 65412861..92e8cab4 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -763,6 +763,7 @@ agaveGui::onImageLoaded(std::shared_ptr image, std::string filename = loadSpec.getFilename(); m_tabs->setTabText(0, QString::fromStdString(filename)); + m_appearanceObject->updatePropsFromObject(); m_appearanceDockWidget->onNewImage(&m_appScene); m_timelinedock->onNewImage(&m_appScene, loadSpec, reader); From f9673e8bea762f15f48f50c4f5b385a53b5ccdbc Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 16:09:47 -0700 Subject: [PATCH 41/60] add a callback for updating ui via property updates --- agave_app/qtControls/controlFactory.cpp | 26 ++++++++++++++++++++ renderlib/core/prty/prtyPropertyCallback.hpp | 6 +++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index 4f2ac621..7a3f19d5 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -23,12 +23,38 @@ addRow(const FloatSliderSpinnerUiInfo& info) slider->setValue(prop->GetValue(), true); auto conn = QObject::connect( slider, &QNumericSlider::valueChanged, [slider, prop](double value) { prop->SetValue(value, true); }); + // now add a callback to the property to update the control when the property changes + + // Note: right now, this will not create a circular update because + // of the m_bLocalChangeNoUpdate flag. This IS NOT true the other way + // around. If a control calls its "ValueChanged" then the property will + // call all of its callback controls and one of them could have been the one + // that originally updated the property value(s). By checking the diff of + // the values we can avoid a repetitive setting of the control's values. + prop->AddCallback(new prtyCallbackLambda([slider](prtyProperty* i_pProperty, bool i_bDirty) { + // this is equivalent to QWidget::blockSignals(true); + // if (m_bLocalChangeNoUpdate) + // return; + const float newvalue = (static_cast(i_pProperty))->GetValue(); + // m_bLocalChangeNoUpdate = true; + slider->blockSignals(true); + if ((float)slider->value() != newvalue) { + // Prevent recursive updates + // slider->setLocalChangeNoUpdate(true); + slider->setValue(newvalue, false); + // slider->setLocalChangeNoUpdate(false); + } + // m_bLocalChangeNoUpdate = false; + slider->blockSignals(false); + })); + QObject::connect(slider, &QNumericSlider::destroyed, [conn]() { // Disconnect the signal when the slider is destroyed QObject::disconnect(conn); }); return slider; } + QNumericSlider* addRow(const IntSliderSpinnerUiInfo& info) { diff --git a/renderlib/core/prty/prtyPropertyCallback.hpp b/renderlib/core/prty/prtyPropertyCallback.hpp index 3ddd849f..d2c88f9d 100644 --- a/renderlib/core/prty/prtyPropertyCallback.hpp +++ b/renderlib/core/prty/prtyPropertyCallback.hpp @@ -21,6 +21,8 @@ //============================================================================ class prtyProperty; +typedef std::function prtyPropertyCallbackFunc; + //============================================================================ // Interface //============================================================================ @@ -63,10 +65,10 @@ struct prtyCallbackWrapper : public prtyPropertyCallback class prtyCallbackLambda : public prtyPropertyCallback { - std::function m_Callback; + prtyPropertyCallbackFunc m_Callback; public: - prtyCallbackLambda(std::function i_Callback) + prtyCallbackLambda(prtyPropertyCallbackFunc i_Callback) : m_Callback(i_Callback) { } From 2ec822c41006932af4083c6d8959dc0d0456aa49 Mon Sep 17 00:00:00 2001 From: dmt Date: Mon, 30 Jun 2025 17:12:32 -0700 Subject: [PATCH 42/60] remove dead code --- renderlib/core/prty/agProperty.cpp | 159 --------------- renderlib/core/prty/agProperty.h | 223 --------------------- renderlib/core/prty/agPropertyCallback.hpp | 74 ------- 3 files changed, 456 deletions(-) delete mode 100644 renderlib/core/prty/agProperty.cpp delete mode 100644 renderlib/core/prty/agProperty.h delete mode 100644 renderlib/core/prty/agPropertyCallback.hpp diff --git a/renderlib/core/prty/agProperty.cpp b/renderlib/core/prty/agProperty.cpp deleted file mode 100644 index bbf240c9..00000000 --- a/renderlib/core/prty/agProperty.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "core/prty/agProperty.h" - -// #include "core/dbg/dbgMsg.hpp" -#include "core/env/envSTLHelpers.hpp" - -//-------------------------------------------------------------------- -//-------------------------------------------------------------------- -const std::string& -agBaseProperty::GetPropertyName() const -{ - return name; -} - -//-------------------------------------------------------------------- -//-------------------------------------------------------------------- -void -agBaseProperty::SetPropertyName(const std::string& i_Name) -{ - name = i_Name; -} - -//-------------------------------------------------------------------- -// Animatable - can this property be animated? -//-------------------------------------------------------------------- -bool -agBaseProperty::IsAnimatable() const -{ - return m_Flags.m_bAnimatable; -} -void -agBaseProperty::SetAnimatable(bool i_bVal) -{ - m_Flags.m_bAnimatable = i_bVal; -} - -//-------------------------------------------------------------------- -// Scripted - Is this property currently being animated? -//-------------------------------------------------------------------- -bool -agBaseProperty::IsScripted() const -{ - return m_Flags.m_bScripted; -} -void -agBaseProperty::SetScripted(bool i_bVal) -{ - m_Flags.m_bScripted = i_bVal; -} - -//-------------------------------------------------------------------- -// ValueVariation - Does the current value vary from the scripted value? -//-------------------------------------------------------------------- -bool -agBaseProperty::HasValueVariation() const -{ - return m_Flags.m_bValueVariation; -} -void -agBaseProperty::SetValueVariation(bool i_bVal) -{ - m_Flags.m_bValueVariation = i_bVal; -} - -//-------------------------------------------------------------------- -// assignment operator - does not copy the callbacks -//-------------------------------------------------------------------- -agBaseProperty& -agBaseProperty::operator=(const agBaseProperty& i_Property) -{ - // m_Type = i_Property.m_Type; - name = i_Property.name; - - // flags should not be copied - // m_Flags = i_Property.m_Flags; - - return *this; -} - -//-------------------------------------------------------------------- -// AddCallback using interface. -// -// NOTE: This property will take ownership of the callback -// pointer and will delete it in its destructor! It should be -// created on the heap and probably should use the -// prtyCallbackWrapper template. -//-------------------------------------------------------------------- -void -agBaseProperty::AddCallback(agPropertyCallback* i_pCallback) -{ - if (i_pCallback != NULL) - m_CallbackObjects.push_back(std::shared_ptr(i_pCallback)); -} - -//-------------------------------------------------------------------- -// AddCallback shared pointer variation for when you want to -// keep a copy of the callback also. -//-------------------------------------------------------------------- -void -agBaseProperty::AddCallback(std::shared_ptr i_pCallback) -{ - if (i_pCallback.get() != NULL) - m_CallbackObjects.push_back(i_pCallback); -} - -//-------------------------------------------------------------------- -// RemoveCallback by shared_ptr. You should be keeping a shared_ptr -// to the callback passed to AddCallback() if you want to remove -// it later. Don't use the direct pointer function when adding -// if you want to keep a copy. -//-------------------------------------------------------------------- -void -agBaseProperty::RemoveCallback(std::shared_ptr i_pCallback) -{ - envSTLHelpers::RemoveOneValue(m_CallbackObjects, i_pCallback); -} - -//-------------------------------------------------------------------- -// call all the callbacks -//-------------------------------------------------------------------- -void -agBaseProperty::NotifyCallbacksPropertyChanged(bool i_bWithUndo) -{ - const int num_callbackobjs = m_CallbackObjects.size(); - for (int i = 0; i < num_callbackobjs; ++i) { - m_CallbackObjects[i]->PropertyChanged(this, i_bWithUndo); - } -} - -//-------------------------------------------------------------------- -// In some cases we want the form builder to check whether or not -// this property should be visible. -//-------------------------------------------------------------------- -void -agBaseProperty::SetVisible(bool i_bVisible) -{ - m_bVisible = i_bVisible; -} - -bool -agBaseProperty::GetVisible() const -{ - return m_bVisible; -} - -//-------------------------------------------------------------------- -// The type of property it is -//-------------------------------------------------------------------- -// const std::string& agProperty::GetType() -//{ -// return m_Type; -//} - -//-------------------------------------------------------------------- -// The type of property it is -//-------------------------------------------------------------------- -// void agProperty::SetType(const std::string i_Type) -//{ -// m_Type = i_Type; -//} diff --git a/renderlib/core/prty/agProperty.h b/renderlib/core/prty/agProperty.h deleted file mode 100644 index 0343ea71..00000000 --- a/renderlib/core/prty/agProperty.h +++ /dev/null @@ -1,223 +0,0 @@ -#pragma once - -#include "Logging.h" - -#include "core/prty/agPropertyCallback.hpp" -#include "core/undo/undoUndoOperation.hpp" - -#include -#include -#include -#include -#include -#include - -// only enable this to verbosely dump every single property setter. -// This implies that the value type must be streamable to std::ostream. -#ifndef PRTY_PROPERTY_DEBUG -#define PRTY_PROPERTY_DEBUG 0 -#endif - -class agBaseProperty -{ -public: - // Base class for properties, can be used to store common flags or data. - // This class is not intended to be instantiated directly. - agBaseProperty() - : m_bVisible(true) - { - m_Flags.m_bAnimatable = false; - m_Flags.m_bScripted = false; - m_Flags.m_bValueVariation = false; - } - agBaseProperty(const std::string& i_Name) - : name(i_Name) - , m_bVisible(true) - { - m_Flags.m_bAnimatable = false; - m_Flags.m_bScripted = false; - m_Flags.m_bValueVariation = false; - } - - virtual ~agBaseProperty() {} - - agBaseProperty& operator=(const agBaseProperty& i_Property); - - const std::string& GetPropertyName() const; - void SetPropertyName(const std::string& i_Name); - - //-------------------------------------------------------------------- - // Animatable - can this property be animated? - //-------------------------------------------------------------------- - bool IsAnimatable() const; - void SetAnimatable(bool i_bVal); - - //-------------------------------------------------------------------- - // Scripted - Is this property currently being animated? - //-------------------------------------------------------------------- - bool IsScripted() const; - void SetScripted(bool i_bVal); - - //-------------------------------------------------------------------- - // ValueVariation - Does the current value vary from the scripted value? - //-------------------------------------------------------------------- - bool HasValueVariation() const; - void SetValueVariation(bool i_bVal); - - //-------------------------------------------------------------------- - // AddCallback using interface. - // - // NOTE: This property will take ownership of the callback - // pointer and will delete it in its destructor! It should be - // created on the heap and probably should use the - // prtyCallbackWrapper template. - //-------------------------------------------------------------------- - void AddCallback(agPropertyCallback* i_pCallback); - - //-------------------------------------------------------------------- - // AddCallback shared pointer variation for when you want to - // keep a copy of the callback also. - //-------------------------------------------------------------------- - void AddCallback(std::shared_ptr i_pCallback); - - //-------------------------------------------------------------------- - // RemoveCallback by shared_ptr. You should be keeping a shared_ptr - // to the callback passed to AddCallback() if you want to remove - // it later. Don't use the direct pointer function when adding - // if you want to keep a copy. - //-------------------------------------------------------------------- - void RemoveCallback(std::shared_ptr i_pCallback); - - //-------------------------------------------------------------------- - // Call all the callbacks - - // i_bWithUndo should be set to (i_Undoable != eNoUndo) - // in derived classes SetValue() functions. - //-------------------------------------------------------------------- - void NotifyCallbacksPropertyChanged(bool i_bWithUndo); - - //-------------------------------------------------------------------- - // The type of property it is - //-------------------------------------------------------------------- - virtual const char* GetType() = 0; - - //-------------------------------------------------------------------- - // Create an undo operation of the correct type for this - // property. A reference to this property should be passed in. - // Ownership passes to the caller. - //-------------------------------------------------------------------- - // virtual undoUndoOperation* CreateUndoOperation(std::shared_ptr i_pPropertyRef) = 0; - - //-------------------------------------------------------------------- - //-------------------------------------------------------------------- - // virtual void Read(chReader& io_Reader) = 0; - - //-------------------------------------------------------------------- - //-------------------------------------------------------------------- - // virtual void Write(chWriter& io_Writer) const = 0; - - //-------------------------------------------------------------------- - // In some cases we want the form builder to check whether or not - // this property should be visible. - //-------------------------------------------------------------------- - void SetVisible(bool i_bVisible); - bool GetVisible() const; - -protected: - std::string name; - std::vector> m_CallbackObjects; - bool m_bVisible; // is this property visible in the UI? - // Flags for the property - struct - { - bool m_bAnimatable : 1; // can this property be animated? - bool m_bScripted : 1; // Is this property currently being animated? - bool m_bValueVariation : 1; // Does the current value vary from the scripted value? - } m_Flags; -}; - -// a property has a name and a value. -// the init value is default-constructed or passed in. -// The value type must be copyable, assignable, and default-constructible. -// The value must also be streamable to std::ostream. -template && std::is_copy_assignable_v && std::is_default_constructible_v && - std::is_move_constructible_v && std::is_move_assignable_v && - std::is_convertible_v() << std::declval()), std::ostream&>>> -class agProperty : public agBaseProperty -{ -public: - agProperty(std::string name, const T& val) - : agBaseProperty(name) - , value(val) - { - } - - virtual ~agProperty() {} - - void set(const T& val, bool i_bDirty = false) - { - // TODO - check if the value has changed - // TODO - do we notify if value hasn't changed? - -#if PRTY_PROPERTY_DEBUG - LOG_INFO << "Property " << name << " set from " << value << " to " << val; -#endif - if (value != val) { - value = val; - - // call all callbacks - NotifyCallbacksPropertyChanged(i_bDirty); - } - } - - std::string getName() const { return name; } - - // copy???? - T get() const { return value; } - - // non-copy, just use paren operator - T& operator()() const { return value; } - - // set up the rule of 5 - agProperty(const agProperty& other) - : agBaseProperty(other.name) - , value(other.value) - { - } - - agProperty& operator=(const agProperty& other) - { - if (this != &other) { - name = other.name; - set(other.value); // use set to notify callbacks - } - return *this; - } - - // direct assignment from a value - agProperty& operator=(const T& value) - { - set(value); // use set to notify callbacks - return *this; - } - - // TODO should we implement move semantics? - // agProperty(agProperty&& other) - // : name(std::move(other.name)) - // , value(std::move(other.value)) - // { - // } - - // agProperty& operator=(agProperty&& other) - // { - // if (this != &other) { - // name = std::move(other.name); - // set(std::move(other.value)); // use set to notify callbacks - // } - // return *this; - // } - -private: - T value; -}; diff --git a/renderlib/core/prty/agPropertyCallback.hpp b/renderlib/core/prty/agPropertyCallback.hpp deleted file mode 100644 index 98a9679e..00000000 --- a/renderlib/core/prty/agPropertyCallback.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************\ -** prtyPropertyCallback.hpp -** -** Template and interface for handling property changed callbacks. -** -** You create and register a callback to a member function with this syntax: -** m_Property.AddCallback(new prtyCallbackWrapper(this, &xxxObject::FunctionName)); -** -** -** -\****************************************************************************/ -#pragma once -#include - -//============================================================================ -// forward references -//============================================================================ -class agBaseProperty; - -//============================================================================ -// Interface -//============================================================================ -class agPropertyCallback -{ -public: - //-------------------------------------------------------------------- - //-------------------------------------------------------------------- - virtual ~agPropertyCallback() {} - - //-------------------------------------------------------------------- - // PropertyChanged is called when a property's value is changed - // through a "SetValue" function. The boolean flag is true - // if the change is coming from the user interface and therefore - // should mark the document containing the property as dirty. - //-------------------------------------------------------------------- - virtual void PropertyChanged(agBaseProperty* i_pProperty, bool i_bDirty) = 0; -}; - -//============================================================================ -// Wrapper template -//============================================================================ -template -struct agPropertyCallbackWrapper : public agPropertyCallback -{ - agPropertyCallbackWrapper(T* i_this, void (T::*i_memberFunc)(agBaseProperty*, bool)) - : obj_ptr(i_this) - , func_ptr(i_memberFunc) - { - } - - T* obj_ptr; - void (T::*func_ptr)(agBaseProperty*, bool); - - virtual void PropertyChanged(agBaseProperty* i_pProperty, bool i_bWithUndo) - { - (obj_ptr->*func_ptr)(i_pProperty, i_bWithUndo); - } -}; - -class agPropertyCallbackLambda : public agPropertyCallback -{ - std::function m_Callback; - -public: - agPropertyCallbackLambda(std::function i_Callback) - : m_Callback(i_Callback) - { - } - - virtual void PropertyChanged(agBaseProperty* i_pProperty, bool i_bWithUndo) override - { - m_Callback(i_pProperty, i_bWithUndo); - } -}; \ No newline at end of file From 06ec6fd8a9f361a195bfd2b5f8daadb53cd1c34e Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 20:34:46 -0700 Subject: [PATCH 43/60] wip --- agave_app/AppearanceWidget.cpp | 68 ++++++++++++++++++++-------------- agave_app/AppearanceWidget.h | 2 +- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index 7d816763..1babe2fa 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -13,38 +13,52 @@ QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, RenderSettings* rs, Vie : QWidget(pParent) , m_MainLayout() , m_renderSettings(rs) - , m_appearanceDataObject(cdo) + , m_appearanceObject(cdo) { Controls::initFormLayout(m_MainLayout); setLayout(&m_MainLayout); + if (m_appearanceObject) { + createFlatList(&m_MainLayout, m_appearanceObject); + } + // // loop over all properties in cameraobject. for each property, add a callback that updates the rendersetttings + // // cameradirty flags + // for (const auto& prop : m_cameraObject->GetList()) { + // if (prop) { + // prop->GetProperty(0)->AddCallback(new prtyCallbackLambda([this](prtyProperty* i_Property, bool i_bDirty) { + // if (i_bDirty) { + // m_renderSettings->m_DirtyFlags.SetFlag(CameraDirty); + // } + // })); + // } + // } - QComboBox* rendererType = addRow(*m_appearanceDataObject->getRendererTypeUiInfo()); - m_MainLayout.addRow("Renderer", rendererType); - QComboBox* shadingType = addRow(*m_appearanceDataObject->getShadingTypeUiInfo()); - m_MainLayout.addRow("Shading Type", shadingType); - QNumericSlider* densityScale = addRow(*m_appearanceDataObject->getDensityScaleUiInfo()); - m_MainLayout.addRow("Scattering Density", densityScale); - QNumericSlider* gradientFactor = addRow(*m_appearanceDataObject->getGradientFactorUiInfo()); - m_MainLayout.addRow("Shading Type Mixture", gradientFactor); - QNumericSlider* stepSizePrimaryRay = addRow(*m_appearanceDataObject->getStepSizePrimaryRayUiInfo()); - m_MainLayout.addRow("Step Size Primary Ray", stepSizePrimaryRay); - QNumericSlider* stepSizeSecondaryRay = addRow(*m_appearanceDataObject->getStepSizeSecondaryRayUiInfo()); - m_MainLayout.addRow("Step Size Secondary Ray", stepSizeSecondaryRay); - QCheckBox* interpolateCheckBox = addRow(*m_appearanceDataObject->getInterpolateUiInfo()); - m_MainLayout.addRow("Interpolate", interpolateCheckBox); - QColorPushButton* backgroundColorButton = addRow(*m_appearanceDataObject->getBackgroundColorUiInfo()); - m_MainLayout.addRow("Background Color", backgroundColorButton); - QCheckBox* showBoundingBoxCheckBox = addRow(*m_appearanceDataObject->getShowBoundingBoxUiInfo()); - m_MainLayout.addRow("Show Bounding Box", showBoundingBoxCheckBox); - QColorPushButton* boundingBoxColorButton = addRow(*m_appearanceDataObject->getBoundingBoxColorUiInfo()); - m_MainLayout.addRow("Bounding Box Color", boundingBoxColorButton); - QCheckBox* showScaleBarCheckBox = addRow(*m_appearanceDataObject->getShowScaleBarUiInfo()); - m_MainLayout.addRow("Show Scale Bar", showScaleBarCheckBox); + // QComboBox* rendererType = addRow(*m_appearanceDataObject->getRendererTypeUiInfo()); + // m_MainLayout.addRow("Renderer", rendererType); + // QComboBox* shadingType = addRow(*m_appearanceDataObject->getShadingTypeUiInfo()); + // m_MainLayout.addRow("Shading Type", shadingType); + // QNumericSlider* densityScale = addRow(*m_appearanceDataObject->getDensityScaleUiInfo()); + // m_MainLayout.addRow("Scattering Density", densityScale); + // QNumericSlider* gradientFactor = addRow(*m_appearanceDataObject->getGradientFactorUiInfo()); + // m_MainLayout.addRow("Shading Type Mixture", gradientFactor); + // QNumericSlider* stepSizePrimaryRay = addRow(*m_appearanceDataObject->getStepSizePrimaryRayUiInfo()); + // m_MainLayout.addRow("Step Size Primary Ray", stepSizePrimaryRay); + // QNumericSlider* stepSizeSecondaryRay = addRow(*m_appearanceDataObject->getStepSizeSecondaryRayUiInfo()); + // m_MainLayout.addRow("Step Size Secondary Ray", stepSizeSecondaryRay); + // QCheckBox* interpolateCheckBox = addRow(*m_appearanceDataObject->getInterpolateUiInfo()); + // m_MainLayout.addRow("Interpolate", interpolateCheckBox); + // QColorPushButton* backgroundColorButton = addRow(*m_appearanceDataObject->getBackgroundColorUiInfo()); + // m_MainLayout.addRow("Background Color", backgroundColorButton); + // QCheckBox* showBoundingBoxCheckBox = addRow(*m_appearanceDataObject->getShowBoundingBoxUiInfo()); + // m_MainLayout.addRow("Show Bounding Box", showBoundingBoxCheckBox); + // QColorPushButton* boundingBoxColorButton = addRow(*m_appearanceDataObject->getBoundingBoxColorUiInfo()); + // m_MainLayout.addRow("Bounding Box Color", boundingBoxColorButton); + // QCheckBox* showScaleBarCheckBox = addRow(*m_appearanceDataObject->getShowScaleBarUiInfo()); + // m_MainLayout.addRow("Show Scale Bar", showScaleBarCheckBox); - QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, vw](int index) { vw->setRenderer(index); }); - QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, gradientFactor](int index) { - gradientFactor->setEnabled(index == 2); - }); + // QObject::connect(rendererType, &QComboBox::currentIndexChanged, [this, vw](int index) { vw->setRenderer(index); }); + // QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, gradientFactor](int index) { + // gradientFactor->setEnabled(index == 2); + // }); } QSize diff --git a/agave_app/AppearanceWidget.h b/agave_app/AppearanceWidget.h index 6e943119..a0fa71ac 100644 --- a/agave_app/AppearanceWidget.h +++ b/agave_app/AppearanceWidget.h @@ -32,5 +32,5 @@ class QAppearanceWidget2 : public QWidget RenderSettings* m_renderSettings; private: - AppearanceObject* m_appearanceDataObject; + AppearanceObject* m_appearanceObject; }; From cb243dad3433a7eafc95ed71c16975549cf8ec40 Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 21:32:26 -0700 Subject: [PATCH 44/60] hook up render settings --- agave_app/agaveGui.cpp | 53 +++++++++++++++++++--------------- agave_app/agaveGui.h | 3 +- agave_app/renderDialog.cpp | 2 +- agave_app/renderDialog.h | 6 ++-- agave_app/renderer.cpp | 4 +-- agave_app/renderer.h | 2 +- agave_app/streamserver.cpp | 6 ++-- renderlib/AppearanceObject.hpp | 3 ++ 8 files changed, 46 insertions(+), 33 deletions(-) diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 92e8cab4..98688d05 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -118,7 +118,7 @@ agaveGui::agaveGui(QWidget* parent) connect(m_tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); // add the single gl view as a tab - m_glView = new GLView3D(&m_qrendersettings, &m_renderSettings, &m_appScene, this); + m_glView = new GLView3D(&m_qrendersettings, m_appearanceObject->getRenderSettings().get(), &m_appScene, this); QObject::connect(m_glView, SIGNAL(ChangedRenderer()), this, SLOT(OnUpdateRenderer())); m_glView->setObjectName("glcontainer"); // We need a minimum size or else the size defaults to zero. @@ -363,7 +363,7 @@ void agaveGui::setupCameraDock(CameraObject* cdo) { // TODO enable changing/resetting the camera data object shown in this dock? - m_cameradock = new QCameraDockWidget(this, &m_qcamera, &m_renderSettings, cdo); + m_cameradock = new QCameraDockWidget(this, m_appearanceObject->getRenderSettings().get(), cdo); m_cameradock->setAllowedAreas(Qt::AllDockWidgetAreas); addDockWidget(Qt::RightDockWidgetArea, m_cameradock); } @@ -376,14 +376,18 @@ void agaveGui::setupAppearanceDock(AppearanceObject* ado) { // DANGER see borrowRenderer call - m_appearanceDockWidget2 = new QAppearanceDockWidget2(this, &m_renderSettings, m_glView->borrowRenderer(), ado); + m_appearanceDockWidget2 = + new QAppearanceDockWidget2(this, m_appearanceObject->getRenderSettings().get(), m_glView->borrowRenderer(), ado); m_appearanceDockWidget2->setAllowedAreas(Qt::AllDockWidgetAreas); addDockWidget(Qt::LeftDockWidgetArea, m_appearanceDockWidget2); // original appearance dock widget - m_appearanceDockWidget = new QAppearanceDockWidget( - this, &m_qrendersettings, &m_renderSettings, m_toggleRotateControlsAction, m_toggleTranslateControlsAction); + m_appearanceDockWidget = new QAppearanceDockWidget(this, + &m_qrendersettings, + m_appearanceObject->getRenderSettings().get(), + m_toggleRotateControlsAction, + m_toggleTranslateControlsAction); m_appearanceDockWidget->setAllowedAreas(Qt::AllDockWidgetAreas); addDockWidget(Qt::LeftDockWidgetArea, m_appearanceDockWidget); } @@ -651,7 +655,7 @@ agaveGui::onRenderAction() ViewerWindow* renderer = m_glView->borrowRenderer(); RenderDialog* rdialog = new RenderDialog(renderer, - m_renderSettings, + m_appearanceObject->getRenderSettings(), m_appScene, camera, m_glView->context(), @@ -665,10 +669,11 @@ agaveGui::onRenderAction() connect(rdialog, &QDialog::finished, this, [this, &rdialog](int result) { // get renderer from RenderDialog and hand it back to GLView3D LOG_DEBUG << "RenderDialog finished with result " << result; - m_renderSettings.m_DirtyFlags.SetFlag(CameraDirty); - m_renderSettings.m_DirtyFlags.SetFlag(LightsDirty); - m_renderSettings.m_DirtyFlags.SetFlag(RenderParamsDirty); - m_renderSettings.m_DirtyFlags.SetFlag(TransferFunctionDirty); + auto rs = m_appearanceObject->getRenderSettings(); + rs->m_DirtyFlags.SetFlag(CameraDirty); + rs->m_DirtyFlags.SetFlag(LightsDirty); + rs->m_DirtyFlags.SetFlag(RenderParamsDirty); + rs->m_DirtyFlags.SetFlag(TransferFunctionDirty); m_glView->setEnabled(true); m_glView->resizeGL(m_glView->width(), m_glView->height()); m_glView->setUpdatesEnabled(true); @@ -1214,10 +1219,11 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v) m_appScene.m_showScaleBar = v.showScaleBar; /////////////// TODO set these through props in the AppearanceObject - m_renderSettings.m_RenderSettings.m_DensityScale = v.density; - m_renderSettings.m_RenderSettings.m_StepSizeFactor = v.pathTracer.primaryStepSize; - m_renderSettings.m_RenderSettings.m_StepSizeFactorShadow = v.pathTracer.secondaryStepSize; - m_renderSettings.m_RenderSettings.m_InterpolatedVolumeSampling = v.interpolate; + auto rs = m_appearanceObject->getRenderSettings(); + rs->m_RenderSettings.m_DensityScale = v.density; + rs->m_RenderSettings.m_StepSizeFactor = v.pathTracer.primaryStepSize; + rs->m_RenderSettings.m_StepSizeFactorShadow = v.pathTracer.secondaryStepSize; + rs->m_RenderSettings.m_InterpolatedVolumeSampling = v.interpolate; // channels for (uint32_t i = 0; i < m_appScene.m_volume->sizeC(); ++i) { @@ -1262,10 +1268,10 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v) m_captureSettings.outputDir = v.capture.outputDirectory; m_captureSettings.filenamePrefix = v.capture.filenamePrefix; - m_renderSettings.m_DirtyFlags.SetFlag(CameraDirty); - m_renderSettings.m_DirtyFlags.SetFlag(LightsDirty); - m_renderSettings.m_DirtyFlags.SetFlag(RenderParamsDirty); - m_renderSettings.m_DirtyFlags.SetFlag(TransferFunctionDirty); + rs->m_DirtyFlags.SetFlag(CameraDirty); + rs->m_DirtyFlags.SetFlag(LightsDirty); + rs->m_DirtyFlags.SetFlag(RenderParamsDirty); + rs->m_DirtyFlags.SetFlag(TransferFunctionDirty); } Serialize::ViewerState @@ -1296,7 +1302,7 @@ agaveGui::appToViewerState() v.showBoundingBox = m_appScene.m_material.m_showBoundingBox; v.showScaleBar = m_appScene.m_showScaleBar; - v.capture.samples = m_renderSettings.GetNoIterations(); + v.capture.samples = m_appearanceObject->getRenderSettings()->GetNoIterations(); v.timeline.minTime = m_appScene.m_timeLine.minTime(); v.timeline.maxTime = m_appScene.m_timeLine.maxTime(); @@ -1343,14 +1349,15 @@ agaveGui::appToViewerState() v.camera.exposure = cdo->getCameraDataObject().Exposure.GetValue(); v.camera.aperture = cdo->getCameraDataObject().ApertureSize.GetValue(); v.camera.focalDistance = cdo->getCameraDataObject().FocalDistance.GetValue(); - v.density = m_renderSettings.m_RenderSettings.m_DensityScale; - v.interpolate = m_renderSettings.m_RenderSettings.m_InterpolatedVolumeSampling; + auto rs = m_appearanceObject->getRenderSettings(); + v.density = rs->m_RenderSettings.m_DensityScale; + v.interpolate = rs->m_RenderSettings.m_InterpolatedVolumeSampling; v.rendererType = m_qrendersettings.GetRendererType() == 0 ? Serialize::RendererType_PID::RAYMARCH : Serialize::RendererType_PID::PATHTRACE; - v.pathTracer.primaryStepSize = m_renderSettings.m_RenderSettings.m_StepSizeFactor; - v.pathTracer.secondaryStepSize = m_renderSettings.m_RenderSettings.m_StepSizeFactorShadow; + v.pathTracer.primaryStepSize = rs->m_RenderSettings.m_StepSizeFactor; + v.pathTracer.secondaryStepSize = rs->m_RenderSettings.m_StepSizeFactorShadow; if (m_appScene.m_volume) { for (uint32_t i = 0; i < m_appScene.m_volume->sizeC(); ++i) { diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h index 66716c96..2474ddc3 100644 --- a/agave_app/agaveGui.h +++ b/agave_app/agaveGui.h @@ -175,7 +175,7 @@ private slots: // There is only one of these. The app owns it and hands refs to the ui widgets and the renderer. // if renderer is on a separate thread, then this will need a mutex guard // any direct programmatic changes to this obj need to be pushed to the UI as well. - RenderSettings m_renderSettings; + std::unique_ptr m_appearanceObject; // the render dialog will modify the contents of this object CaptureSettings m_captureSettings; @@ -185,7 +185,6 @@ private slots: Scene m_appScene; int m_currentScene = 0; std::unique_ptr m_cameraObject; - std::unique_ptr m_appearanceObject; std::string m_currentFilePath; // TODO remove the above m_currentFilePath and use this instead diff --git a/agave_app/renderDialog.cpp b/agave_app/renderDialog.cpp index 6e8f8d7f..3ed0da08 100644 --- a/agave_app/renderDialog.cpp +++ b/agave_app/renderDialog.cpp @@ -232,7 +232,7 @@ makeGroupLabel(const std::string& text) } RenderDialog::RenderDialog(ViewerWindow* borrowedRenderer, - const RenderSettings& renderSettings, + std::shared_ptr renderSettings, const Scene& scene, CCamera camera, QOpenGLContext* glContext, diff --git a/agave_app/renderDialog.h b/agave_app/renderDialog.h index 9854bbd6..741dbbfd 100644 --- a/agave_app/renderDialog.h +++ b/agave_app/renderDialog.h @@ -9,6 +9,8 @@ #include #include +#include + class QButtonGroup; class QCheckBox; class QComboBox; @@ -68,7 +70,7 @@ class RenderDialog : public QDialog public: RenderDialog(ViewerWindow* borrowedRenderer, - const RenderSettings& renderSettings, + std::shared_ptr renderSettings, const Scene& scene, CCamera camera, QOpenGLContext* glContext, @@ -107,7 +109,7 @@ private slots: QOpenGLContext* m_glContext; Renderer* m_renderThread; IRenderWindow* m_renderer; - const RenderSettings& m_renderSettings; + std::shared_ptr m_renderSettings; const Scene& m_scene; LoadSpec m_loadSpec; // reference that I don't own diff --git a/agave_app/renderer.cpp b/agave_app/renderer.cpp index 060966e8..d9ea2aa5 100644 --- a/agave_app/renderer.cpp +++ b/agave_app/renderer.cpp @@ -47,7 +47,7 @@ Renderer::~Renderer() void Renderer::configure(IRenderWindow* renderer, - const RenderSettings& renderSettings, + std::shared_ptr renderSettings, const Scene& scene, const CCamera& camera, const LoadSpec& loadSpec, @@ -57,7 +57,7 @@ Renderer::configure(IRenderWindow* renderer, const CaptureSettings* captureSettings) { // assumes scene is already set in renderer and everything is initialized - m_myVolumeData.m_renderSettings = new RenderSettings(renderSettings); + m_myVolumeData.m_renderSettings = new RenderSettings(*renderSettings.get()); m_myVolumeData.m_camera = new CCamera(camera); // CONTROVERSIAL: // it is hard to maintain a full scene copy ctor. diff --git a/agave_app/renderer.h b/agave_app/renderer.h index e096b323..8f1952a7 100644 --- a/agave_app/renderer.h +++ b/agave_app/renderer.h @@ -92,7 +92,7 @@ class Renderer virtual ~Renderer(); void configure(IRenderWindow* renderer, - const RenderSettings& renderSettings, + std::shared_ptr renderSettings, const Scene& scene, const CCamera& camera, const LoadSpec& loadSpec, diff --git a/agave_app/streamserver.cpp b/agave_app/streamserver.cpp index 80ff7b74..482fc784 100644 --- a/agave_app/streamserver.cpp +++ b/agave_app/streamserver.cpp @@ -17,6 +17,8 @@ #include "renderlib/Logging.h" #include "renderlib/RenderSettings.h" +#include + QT_USE_NAMESPACE // JPG selected for potentially greater compression @@ -41,7 +43,7 @@ StreamServer::createNewRenderer(QWebSocket* client) int i = this->_renderers.length(); Renderer* r = new Renderer("Thread " + QString::number(i), this, _openGLMutex); - RenderSettings* rs = new RenderSettings(); + auto rs = std::make_shared(); CCamera* camera = new CCamera(); camera->m_Film.m_ExposureIterations = 1; camera->m_Film.m_Resolution.SetResX(1024); @@ -49,7 +51,7 @@ StreamServer::createNewRenderer(QWebSocket* client) Scene* scene = new Scene(); scene->initLights(); - r->configure(nullptr, *rs, *scene, *camera, LoadSpec(), renderMode); + r->configure(nullptr, rs, *scene, *camera, LoadSpec(), renderMode); this->_renderers << r; diff --git a/renderlib/AppearanceObject.hpp b/renderlib/AppearanceObject.hpp index c5173dfa..95268163 100644 --- a/renderlib/AppearanceObject.hpp +++ b/renderlib/AppearanceObject.hpp @@ -46,6 +46,9 @@ class AppearanceObject : public prtyObject ColorPickerUiInfo* getBoundingBoxColorUiInfo() { return m_boundingBoxColor; } CheckBoxUiInfo* getShowScaleBarUiInfo() { return m_showScaleBar; } + // Getter for the rendersettings + std::shared_ptr getRenderSettings() const { return m_renderSettings; } + private: // the properties AppearanceDataObject m_appearanceDataObject; From acb1f32628d6eb16e6574931b725836ee622db6a Mon Sep 17 00:00:00 2001 From: dmt Date: Fri, 4 Jul 2025 21:50:51 -0700 Subject: [PATCH 45/60] renderertype switch --- agave_app/AppearanceWidget.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/agave_app/AppearanceWidget.cpp b/agave_app/AppearanceWidget.cpp index 1babe2fa..c57e9546 100644 --- a/agave_app/AppearanceWidget.cpp +++ b/agave_app/AppearanceWidget.cpp @@ -59,6 +59,13 @@ QAppearanceWidget2::QAppearanceWidget2(QWidget* pParent, RenderSettings* rs, Vie // QObject::connect(shadingType, &QComboBox::currentIndexChanged, [this, gradientFactor](int index) { // gradientFactor->setEnabled(index == 2); // }); + m_appearanceObject->getRendererTypeUiInfo()->GetProperty(0)->AddCallback( + new prtyCallbackLambda([this, vw](prtyProperty* i_Property, bool i_bDirty) { + if (i_bDirty) { + const int newvalue = (static_cast(i_Property))->GetValue(); + vw->setRenderer(newvalue); + } + })); } QSize From ce7580210d0c84a1018616923aada71d296aa900 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Sun, 6 Jul 2025 21:20:23 -0700 Subject: [PATCH 46/60] read and write appearance settings via properties --- agave_app/agaveGui.cpp | 71 +++++++++++++++++++--------------- renderlib/AppearanceObject.hpp | 2 +- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 98688d05..58de3f53 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -1207,23 +1207,29 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v) m_appScene.m_volume->setPhysicalSize(v.scale[0], v.scale[1], v.scale[2]); m_appScene.m_volume->setVolumeAxesFlipped(v.flipAxis[0], v.flipAxis[1], v.flipAxis[2]); - m_appScene.m_material.m_backgroundColor[0] = v.backgroundColor[0]; - m_appScene.m_material.m_backgroundColor[1] = v.backgroundColor[1]; - m_appScene.m_material.m_backgroundColor[2] = v.backgroundColor[2]; - - m_appScene.m_material.m_boundingBoxColor[0] = v.boundingBoxColor[0]; - m_appScene.m_material.m_boundingBoxColor[1] = v.boundingBoxColor[1]; - m_appScene.m_material.m_boundingBoxColor[2] = v.boundingBoxColor[2]; - - m_appScene.m_material.m_showBoundingBox = v.showBoundingBox; - m_appScene.m_showScaleBar = v.showScaleBar; + m_appearanceObject->appearanceDataObject().BackgroundColor.SetValue( + { v.backgroundColor[0], v.backgroundColor[1], v.backgroundColor[2], 1.0f }); + m_appearanceObject->appearanceDataObject().BoundingBoxColor.SetValue( + { v.boundingBoxColor[0], v.boundingBoxColor[1], v.boundingBoxColor[2], 1.0f }); + // m_appScene.m_material.m_backgroundColor[0] = v.backgroundColor[0]; + // m_appScene.m_material.m_backgroundColor[1] = v.backgroundColor[1]; + // m_appScene.m_material.m_backgroundColor[2] = v.backgroundColor[2]; + + // m_appScene.m_material.m_boundingBoxColor[0] = v.boundingBoxColor[0]; + // m_appScene.m_material.m_boundingBoxColor[1] = v.boundingBoxColor[1]; + // m_appScene.m_material.m_boundingBoxColor[2] = v.boundingBoxColor[2]; + + m_appearanceObject->appearanceDataObject().ShowBoundingBox.SetValue(v.showBoundingBox); + m_appearanceObject->appearanceDataObject().ShowScaleBar.SetValue(v.showScaleBar); + // m_appScene.m_material.m_showBoundingBox = v.showBoundingBox; + // m_appScene.m_showScaleBar = v.showScaleBar; /////////////// TODO set these through props in the AppearanceObject - auto rs = m_appearanceObject->getRenderSettings(); - rs->m_RenderSettings.m_DensityScale = v.density; - rs->m_RenderSettings.m_StepSizeFactor = v.pathTracer.primaryStepSize; - rs->m_RenderSettings.m_StepSizeFactorShadow = v.pathTracer.secondaryStepSize; - rs->m_RenderSettings.m_InterpolatedVolumeSampling = v.interpolate; + auto rs = m_appearanceObject->appearanceDataObject(); + rs.DensityScale.SetValue(v.density); + rs.StepSizePrimaryRay.SetValue(v.pathTracer.primaryStepSize); + rs.StepSizeSecondaryRay.SetValue(v.pathTracer.secondaryStepSize); + rs.Interpolate.SetValue(v.interpolate); // channels for (uint32_t i = 0; i < m_appScene.m_volume->sizeC(); ++i) { @@ -1268,10 +1274,11 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v) m_captureSettings.outputDir = v.capture.outputDirectory; m_captureSettings.filenamePrefix = v.capture.filenamePrefix; - rs->m_DirtyFlags.SetFlag(CameraDirty); - rs->m_DirtyFlags.SetFlag(LightsDirty); - rs->m_DirtyFlags.SetFlag(RenderParamsDirty); - rs->m_DirtyFlags.SetFlag(TransferFunctionDirty); + auto renderSettings = m_appearanceObject->getRenderSettings(); + renderSettings->m_DirtyFlags.SetFlag(CameraDirty); + renderSettings->m_DirtyFlags.SetFlag(LightsDirty); + renderSettings->m_DirtyFlags.SetFlag(RenderParamsDirty); + renderSettings->m_DirtyFlags.SetFlag(TransferFunctionDirty); } Serialize::ViewerState @@ -1292,15 +1299,15 @@ agaveGui::appToViewerState() v.flipAxis[2] = vflip.z > 0 ? 1 : -1; } - v.backgroundColor = { m_appScene.m_material.m_backgroundColor[0], - m_appScene.m_material.m_backgroundColor[1], - m_appScene.m_material.m_backgroundColor[2] }; + v.backgroundColor = { m_appearanceObject->getAppearanceDataObject().BackgroundColor.GetValue()[0], + m_appearanceObject->getAppearanceDataObject().BackgroundColor.GetValue()[1], + m_appearanceObject->getAppearanceDataObject().BackgroundColor.GetValue()[2] }; - v.boundingBoxColor = { m_appScene.m_material.m_boundingBoxColor[0], - m_appScene.m_material.m_boundingBoxColor[1], - m_appScene.m_material.m_boundingBoxColor[2] }; - v.showBoundingBox = m_appScene.m_material.m_showBoundingBox; - v.showScaleBar = m_appScene.m_showScaleBar; + v.boundingBoxColor = { m_appearanceObject->getAppearanceDataObject().BoundingBoxColor.GetValue()[0], + m_appearanceObject->getAppearanceDataObject().BoundingBoxColor.GetValue()[1], + m_appearanceObject->getAppearanceDataObject().BoundingBoxColor.GetValue()[2] }; + v.showBoundingBox = m_appearanceObject->getAppearanceDataObject().ShowBoundingBox.GetValue(); + v.showScaleBar = m_appearanceObject->getAppearanceDataObject().ShowScaleBar.GetValue(); v.capture.samples = m_appearanceObject->getRenderSettings()->GetNoIterations(); @@ -1349,15 +1356,15 @@ agaveGui::appToViewerState() v.camera.exposure = cdo->getCameraDataObject().Exposure.GetValue(); v.camera.aperture = cdo->getCameraDataObject().ApertureSize.GetValue(); v.camera.focalDistance = cdo->getCameraDataObject().FocalDistance.GetValue(); - auto rs = m_appearanceObject->getRenderSettings(); - v.density = rs->m_RenderSettings.m_DensityScale; - v.interpolate = rs->m_RenderSettings.m_InterpolatedVolumeSampling; + auto rs = m_appearanceObject->getAppearanceDataObject(); + v.density = rs.DensityScale.GetValue(); + v.interpolate = rs.Interpolate.GetValue(); v.rendererType = m_qrendersettings.GetRendererType() == 0 ? Serialize::RendererType_PID::RAYMARCH : Serialize::RendererType_PID::PATHTRACE; - v.pathTracer.primaryStepSize = rs->m_RenderSettings.m_StepSizeFactor; - v.pathTracer.secondaryStepSize = rs->m_RenderSettings.m_StepSizeFactorShadow; + v.pathTracer.primaryStepSize = rs.StepSizePrimaryRay.GetValue(); + v.pathTracer.secondaryStepSize = rs.StepSizeSecondaryRay.GetValue(); if (m_appScene.m_volume) { for (uint32_t i = 0; i < m_appScene.m_volume->sizeC(); ++i) { diff --git a/renderlib/AppearanceObject.hpp b/renderlib/AppearanceObject.hpp index 95268163..36774846 100644 --- a/renderlib/AppearanceObject.hpp +++ b/renderlib/AppearanceObject.hpp @@ -30,7 +30,7 @@ class AppearanceObject : public prtyObject void updateObjectFromProps(); // Getter for appearance data object - // AppearanceDataObject& getAppearanceDataObject() { return m_appearanceDataObject; } + AppearanceDataObject& appearanceDataObject() { return m_appearanceDataObject; } const AppearanceDataObject& getAppearanceDataObject() const { return m_appearanceDataObject; } // Getters for UI info objects From efd5196a640647ae171abf70e6abd00f9d5e74d1 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Mon, 7 Jul 2025 10:01:47 -0700 Subject: [PATCH 47/60] update viewerstatetoapp and apptoviewerstate --- agave_app/agaveGui.cpp | 48 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp index 58de3f53..c267a285 100644 --- a/agave_app/agaveGui.cpp +++ b/agave_app/agaveGui.cpp @@ -1299,15 +1299,17 @@ agaveGui::appToViewerState() v.flipAxis[2] = vflip.z > 0 ? 1 : -1; } - v.backgroundColor = { m_appearanceObject->getAppearanceDataObject().BackgroundColor.GetValue()[0], - m_appearanceObject->getAppearanceDataObject().BackgroundColor.GetValue()[1], - m_appearanceObject->getAppearanceDataObject().BackgroundColor.GetValue()[2] }; - - v.boundingBoxColor = { m_appearanceObject->getAppearanceDataObject().BoundingBoxColor.GetValue()[0], - m_appearanceObject->getAppearanceDataObject().BoundingBoxColor.GetValue()[1], - m_appearanceObject->getAppearanceDataObject().BoundingBoxColor.GetValue()[2] }; - v.showBoundingBox = m_appearanceObject->getAppearanceDataObject().ShowBoundingBox.GetValue(); - v.showScaleBar = m_appearanceObject->getAppearanceDataObject().ShowScaleBar.GetValue(); + // TODO just dump data objects directly to serialization? + const AppearanceDataObject& appearanceData = m_appearanceObject->getAppearanceDataObject(); + v.backgroundColor = { appearanceData.BackgroundColor.GetValue()[0], + appearanceData.BackgroundColor.GetValue()[1], + appearanceData.BackgroundColor.GetValue()[2] }; + + v.boundingBoxColor = { appearanceData.BoundingBoxColor.GetValue()[0], + appearanceData.BoundingBoxColor.GetValue()[1], + appearanceData.BoundingBoxColor.GetValue()[2] }; + v.showBoundingBox = appearanceData.ShowBoundingBox.GetValue(); + v.showScaleBar = appearanceData.ShowScaleBar.GetValue(); v.capture.samples = m_appearanceObject->getRenderSettings()->GetNoIterations(); @@ -1351,20 +1353,20 @@ agaveGui::appToViewerState() v.camera.projection = m_glView->getCamera().m_Projection == PERSPECTIVE ? Serialize::Projection_PID::PERSPECTIVE : Serialize::Projection_PID::ORTHOGRAPHIC; v.camera.orthoScale = m_glView->getCamera().m_OrthoScale; - CameraObject* cdo = m_cameraObject.get(); - v.camera.fovY = cdo->getCameraDataObject().FieldOfView.GetValue(); - v.camera.exposure = cdo->getCameraDataObject().Exposure.GetValue(); - v.camera.aperture = cdo->getCameraDataObject().ApertureSize.GetValue(); - v.camera.focalDistance = cdo->getCameraDataObject().FocalDistance.GetValue(); - auto rs = m_appearanceObject->getAppearanceDataObject(); - v.density = rs.DensityScale.GetValue(); - v.interpolate = rs.Interpolate.GetValue(); - - v.rendererType = m_qrendersettings.GetRendererType() == 0 ? Serialize::RendererType_PID::RAYMARCH - : Serialize::RendererType_PID::PATHTRACE; - - v.pathTracer.primaryStepSize = rs.StepSizePrimaryRay.GetValue(); - v.pathTracer.secondaryStepSize = rs.StepSizeSecondaryRay.GetValue(); + // CameraObject* cdo = m_cameraObject.get(); + const CameraDataObject& cameraData = m_cameraObject->getCameraDataObject(); + v.camera.fovY = cameraData.FieldOfView.GetValue(); + v.camera.exposure = cameraData.Exposure.GetValue(); + v.camera.aperture = cameraData.ApertureSize.GetValue(); + v.camera.focalDistance = cameraData.FocalDistance.GetValue(); + + v.density = appearanceData.DensityScale.GetValue(); + v.interpolate = appearanceData.Interpolate.GetValue(); + + v.rendererType = appearanceData.RendererType.GetValue() == 0 ? Serialize::RendererType_PID::RAYMARCH + : Serialize::RendererType_PID::PATHTRACE; + v.pathTracer.primaryStepSize = appearanceData.StepSizePrimaryRay.GetValue(); + v.pathTracer.secondaryStepSize = appearanceData.StepSizeSecondaryRay.GetValue(); if (m_appScene.m_volume) { for (uint32_t i = 0; i < m_appScene.m_volume->sizeC(); ++i) { From 0e1fcb477c1983c742020e9178480a7897e034e6 Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Thu, 10 Jul 2025 12:46:01 -0700 Subject: [PATCH 48/60] start adding complete camera properties --- renderlib/CameraDataObject.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index a26c862c..b3b1b867 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -3,6 +3,7 @@ #include "core/prty/prtyFloat.hpp" #include "core/prty/prtyInt8.hpp" #include "core/prty/prtyBoolean.hpp" +#include "core/prty/prtyVector3d.hpp" class CameraDataObject { @@ -13,6 +14,12 @@ class CameraDataObject prtyInt8 ExposureIterations{ "ExposureIterations", 1 }; prtyBoolean NoiseReduction{ "NoiseReduction", false }; prtyFloat ApertureSize{ "ApertureSize", 0.0f }; - prtyFloat FieldOfView{ "FieldOfView", 30.0f }; + prtyFloat FieldOfView{ "FieldOfView", 30.0f }; // degrees prtyFloat FocalDistance{ "FocalDistance", 0.0f }; + + prtyVector3d Position{ "Position", glm::vec3(0.0f, 0.0f, 0.0f) }; + prtyVector3d Target{ "Target", glm::vec3(0.0f, 0.0f, -1.0f) }; + prtyFloat NearPlane{ "NearPlane", 0.1f }; + prtyFloat FarPlane{ "FarPlane", 1000.0f }; + prtyFloat Roll{ "Roll", 0.0f }; // tilt angle in degrees }; From e262fd2ff32e84032e1d3e8430909b47bab3ac7b Mon Sep 17 00:00:00 2001 From: Daniel Toloudis Date: Mon, 28 Jul 2025 16:45:24 -0700 Subject: [PATCH 49/60] fix warning --- agave_app/qtControls/RangeWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agave_app/qtControls/RangeWidget.cpp b/agave_app/qtControls/RangeWidget.cpp index 7a5b8b32..54482f98 100644 --- a/agave_app/qtControls/RangeWidget.cpp +++ b/agave_app/qtControls/RangeWidget.cpp @@ -95,7 +95,7 @@ RangeWidget::paintEvent(QPaintEvent* event) r = QRect( std::floor((m_handleHeight - m_trackHeight + totalOutline) / 2.), 0, m_trackHeight, height() - totalOutline); QPainterPath trackPath; - trackPath.addRoundedRect(r.translated(0.5, 0.0), radius, radius); + trackPath.addRoundedRect(QRectF(r).translated(0.5, 0.0), radius, radius); p.fillPath(trackPath, m_trackFillColor); // Color the selected range of the track From 051adf3a0b1bfeff2fb4fe9aac241e56a39caf7f Mon Sep 17 00:00:00 2001 From: dmt Date: Wed, 30 Jul 2025 20:19:39 -0700 Subject: [PATCH 50/60] use prtyEnum correctly --- agave_app/GLView3D.cpp | 1 + agave_app/qtControls/controlFactory.cpp | 7 ++-- renderlib/AppearanceDataObject.cpp | 10 ++++- renderlib/AppearanceDataObject.hpp | 6 +-- renderlib/AppearanceObject.cpp | 2 - renderlib/CameraDataObject.hpp | 12 ++++-- renderlib/CameraObject.cpp | 49 +++++++++++++++++++++++-- renderlib/CameraObject.hpp | 3 ++ renderlib/core/prty/prtyEnum.hpp | 1 + renderlib/uiInfo.hpp | 1 - 10 files changed, 75 insertions(+), 17 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index 1f520aaf..f99f80f1 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -491,6 +491,7 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) camera->m_Focus.m_FocalDistance = s.camera.focalDistance; // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! + // TODO FIXME if we set everything through props, then this is not needed. m_cameraObject->updatePropsFromObject(); } diff --git a/agave_app/qtControls/controlFactory.cpp b/agave_app/qtControls/controlFactory.cpp index 7a3f19d5..0883589f 100644 --- a/agave_app/qtControls/controlFactory.cpp +++ b/agave_app/qtControls/controlFactory.cpp @@ -4,6 +4,7 @@ #include "Section.h" #include "renderlib/core/prty/prtyObject.hpp" +#include "renderlib/core/prty/prtyEnum.hpp" #include @@ -83,10 +84,10 @@ addRow(const ComboBoxUiInfo& info) QComboBox* comboBox = new QComboBox(); comboBox->setStatusTip(QString::fromStdString(info.GetStatusTip())); comboBox->setToolTip(QString::fromStdString(info.GetToolTip())); - for (const auto& item : info.items) { - comboBox->addItem(QString::fromStdString(item)); + auto* prop = static_cast(info.GetProperty(0)); + for (int i = 0; i < prop->GetNumTags(); ++i) { + comboBox->addItem(QString::fromStdString(prop->GetEnumTag(i))); } - auto* prop = static_cast(info.GetProperty(0)); comboBox->setCurrentIndex(prop->GetValue()); auto conn = QObject::connect( comboBox, &QComboBox::currentIndexChanged, [comboBox, prop](int index) { prop->SetValue(index, true); }); diff --git a/renderlib/AppearanceDataObject.cpp b/renderlib/AppearanceDataObject.cpp index 82055d9a..886966ff 100644 --- a/renderlib/AppearanceDataObject.cpp +++ b/renderlib/AppearanceDataObject.cpp @@ -3,4 +3,12 @@ #include "Enumerations.h" #include "Logging.h" -AppearanceDataObject::AppearanceDataObject() {} +AppearanceDataObject::AppearanceDataObject() +{ + RendererType.SetEnumTag(0, "Ray march blending"); + RendererType.SetEnumTag(1, "Path Traced"); + + ShadingType.SetEnumTag(0, "BRDF Only"); + ShadingType.SetEnumTag(1, "Phase Function Only"); + ShadingType.SetEnumTag(2, "Mixed"); +} diff --git a/renderlib/AppearanceDataObject.hpp b/renderlib/AppearanceDataObject.hpp index d456af83..82904e57 100644 --- a/renderlib/AppearanceDataObject.hpp +++ b/renderlib/AppearanceDataObject.hpp @@ -1,6 +1,6 @@ #pragma once -#include "core/prty/prtyInt8.hpp" +#include "core/prty/prtyEnum.hpp" #include "core/prty/prtyFloat.hpp" #include "core/prty/prtyBoolean.hpp" #include "core/prty/prtyVector3d.hpp" @@ -12,8 +12,8 @@ class AppearanceDataObject public: AppearanceDataObject(); - prtyInt8 RendererType{ "RendererType", 1 }; - prtyInt8 ShadingType{ "ShadingType", 0 }; + prtyEnum RendererType{ "RendererType", 1 }; + prtyEnum ShadingType{ "ShadingType", 0 }; prtyFloat DensityScale{ "DensityScale", 1.0f }; prtyFloat GradientFactor{ "GradientFactor", 0.5f }; prtyFloat StepSizePrimaryRay{ "StepSizePrimaryRay", 4.0f }; diff --git a/renderlib/AppearanceObject.cpp b/renderlib/AppearanceObject.cpp index 5488fdab..4d5cbc52 100644 --- a/renderlib/AppearanceObject.cpp +++ b/renderlib/AppearanceObject.cpp @@ -60,12 +60,10 @@ AppearanceObject::AppearanceObject() m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, "Appearance", "Renderer Type"); m_rendererType->SetToolTip("Select volume rendering type"); m_rendererType->SetStatusTip("Select volume rendering type"); - m_rendererType->items = { "Ray march blending", "Path Traced" }; AddProperty(m_rendererType); m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, "Appearance", "Shading Type"); m_shadingType->SetToolTip("Select volume shading style"); m_shadingType->SetStatusTip("Select volume shading style"); - m_shadingType->items = { "BRDF Only", "Phase Function Only", "Mixed" }; AddProperty(m_shadingType); m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, "Appearance", "Density Scale"); m_densityScale->SetToolTip("Set scattering density for volume"); diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index b3b1b867..7437d58b 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -1,17 +1,23 @@ #pragma once #include "core/prty/prtyFloat.hpp" -#include "core/prty/prtyInt8.hpp" +#include "core/prty/prtyEnum.hpp" #include "core/prty/prtyBoolean.hpp" #include "core/prty/prtyVector3d.hpp" class CameraDataObject { public: - CameraDataObject() {} + CameraDataObject() + { + ExposureIterations.SetEnumTag(0, "1"); + ExposureIterations.SetEnumTag(1, "2"); + ExposureIterations.SetEnumTag(2, "4"); + ExposureIterations.SetEnumTag(3, "8"); + } prtyFloat Exposure{ "Exposure", 0.75f }; - prtyInt8 ExposureIterations{ "ExposureIterations", 1 }; + prtyEnum ExposureIterations{ "ExposureIterations", 0 }; prtyBoolean NoiseReduction{ "NoiseReduction", false }; prtyFloat ApertureSize{ "ApertureSize", 0.0f }; prtyFloat FieldOfView{ "FieldOfView", 30.0f }; // degrees diff --git a/renderlib/CameraObject.cpp b/renderlib/CameraObject.cpp index 05712b7e..4d2bc5d9 100644 --- a/renderlib/CameraObject.cpp +++ b/renderlib/CameraObject.cpp @@ -63,7 +63,6 @@ CameraObject::CameraObject() new ComboBoxUiInfo(&m_cameraDataObject.ExposureIterations, "Camera", "Exposure Iterations"); m_ExposureIterationsUIInfo->SetToolTip("Set Exposure Iterations"); m_ExposureIterationsUIInfo->SetStatusTip("Set number of samples to accumulate per viewport update"); - m_ExposureIterationsUIInfo->items = { "1", "2", "4", "8" }; AddProperty(m_ExposureIterationsUIInfo); m_NoiseReductionUIInfo = new CheckBoxUiInfo(&m_cameraDataObject.NoiseReduction, "Camera", "Noise Reduction"); m_NoiseReductionUIInfo->SetToolTip("Enable Noise Reduction"); @@ -116,9 +115,31 @@ CameraObject::CameraObject() void CameraObject::updatePropsFromObject() { + // TODO FIXME if we set everything through props, then this is not needed. if (m_camera) { m_cameraDataObject.Exposure.SetValue(1.0f - m_camera->m_Film.m_Exposure); - m_cameraDataObject.ExposureIterations.SetValue(m_camera->m_Film.m_ExposureIterations); + + uint8_t exposureIterationsValue = m_camera->m_Film.m_ExposureIterations; + // convert m_camera->m_Film.m_ExposureIterations to string + // and then find the corresponding index in the enum + switch (m_camera->m_Film.m_ExposureIterations) { + case 1: + exposureIterationsValue = 0; + break; + case 2: + exposureIterationsValue = 1; + break; + case 4: + exposureIterationsValue = 2; + break; + case 8: + exposureIterationsValue = 3; + break; + default: + LOG_ERROR << "Invalid Exposure Iterations: " << m_camera->m_Film.m_ExposureIterations; + exposureIterationsValue = 0; // default to 1 + } + m_cameraDataObject.ExposureIterations.SetValue(exposureIterationsValue); // TODO this is not hooked up to the camera properly // m_cameraDataObject.NoiseReduction.SetValue(m_camera->m_Film.m_NoiseReduction); m_cameraDataObject.ApertureSize.SetValue(m_camera->m_Aperture.m_Size); @@ -126,13 +147,33 @@ CameraObject::updatePropsFromObject() m_cameraDataObject.FocalDistance.SetValue(m_camera->m_Focus.m_FocalDistance); } } +uint8_t +CameraObject::GetExposureIterationsValue(int i_ComboBoxIndex) +{ + // Convert the combo box index to the corresponding exposure iterations value + switch (i_ComboBoxIndex) { + case 0: + return 1; // 1 iteration + case 1: + return 2; // 2 iterations + case 2: + return 4; // 4 iterations + case 3: + return 8; // 8 iterations + default: + LOG_ERROR << "Invalid Exposure Iterations index: " << i_ComboBoxIndex; + return 1; // default to 1 iteration + } +} + void CameraObject::updateObjectFromProps() { // update low-level camera object from properties if (m_camera) { m_camera->m_Film.m_Exposure = 1.0f - m_cameraDataObject.Exposure.GetValue(); - m_camera->m_Film.m_ExposureIterations = m_cameraDataObject.ExposureIterations.GetValue(); + uint8_t exposureIterationsValue = GetExposureIterationsValue(m_cameraDataObject.ExposureIterations.GetValue()); + m_camera->m_Film.m_ExposureIterations = exposureIterationsValue; // Aperture m_camera->m_Aperture.m_Size = m_cameraDataObject.ApertureSize.GetValue(); @@ -162,7 +203,7 @@ CameraObject::ExposureChanged(prtyProperty* i_Property, bool i_bDirty) void CameraObject::ExposureIterationsChanged(prtyProperty* i_Property, bool i_bDirty) { - m_camera->m_Film.m_ExposureIterations = m_cameraDataObject.ExposureIterations.GetValue(); + m_camera->m_Film.m_ExposureIterations = GetExposureIterationsValue(m_cameraDataObject.ExposureIterations.GetValue()); m_camera->m_Dirty = true; } void diff --git a/renderlib/CameraObject.hpp b/renderlib/CameraObject.hpp index f61eedb8..6bcbde8a 100644 --- a/renderlib/CameraObject.hpp +++ b/renderlib/CameraObject.hpp @@ -38,6 +38,9 @@ class CameraObject : public prtyObject // Getter for the camera std::shared_ptr getCamera() const { return m_camera; } + // Convert UI specific combo box index to a known enum type + static uint8_t GetExposureIterationsValue(int i_ComboBoxIndex); + private: // the properties CameraDataObject m_cameraDataObject; diff --git a/renderlib/core/prty/prtyEnum.hpp b/renderlib/core/prty/prtyEnum.hpp index d069fe5a..b81421e4 100644 --- a/renderlib/core/prty/prtyEnum.hpp +++ b/renderlib/core/prty/prtyEnum.hpp @@ -6,6 +6,7 @@ ** ** \****************************************************************************/ +#pragma once #ifdef PRTY_ENUM_HPP #error prtyEnum.hpp multiply included #endif diff --git a/renderlib/uiInfo.hpp b/renderlib/uiInfo.hpp index 5e344432..c3b95c2e 100644 --- a/renderlib/uiInfo.hpp +++ b/renderlib/uiInfo.hpp @@ -41,7 +41,6 @@ class ComboBoxUiInfo : public prtyPropertyUIInfo { public: static constexpr const char* TYPE = "ComboBox"; - std::vector items; ComboBoxUiInfo(prtyProperty* i_pProperty) : prtyPropertyUIInfo(i_pProperty) From 34529b9c11647d85161e69daef876fae132d7982 Mon Sep 17 00:00:00 2001 From: dmt Date: Wed, 30 Jul 2025 20:19:52 -0700 Subject: [PATCH 51/60] fix weird character --- agave_app/tfeditor/gradients.cpp | 1787 ++++++++++++------------------ 1 file changed, 699 insertions(+), 1088 deletions(-) diff --git a/agave_app/tfeditor/gradients.cpp b/agave_app/tfeditor/gradients.cpp index 4c7b0405..dd21eff9 100644 --- a/agave_app/tfeditor/gradients.cpp +++ b/agave_app/tfeditor/gradients.cpp @@ -1,1088 +1,699 @@ -#include "gradients.h" - -#include "qtControls/Controls.h" -#include "Defines.h" -#include "Logging.h" - -#include - -std::vector -gradientStopsToVector(QGradientStops& stops) -{ - std::vector v; - for (int i = 0; i < stops.size(); ++i) { - v.push_back(LutControlPoint(stops.at(i).first, stops.at(i).second.alphaF())); - } - return v; -} - -QGradientStops -vectorToGradientStops(std::vector& v) -{ - QGradientStops stops; - for (int i = 0; i < v.size(); ++i) { - stops.push_back( - QPair(v[i].first, QColor::fromRgbF(v[i].second, v[i].second, v[i].second, v[i].second))); - } - return stops; -} - -static void -bound_point(double x, double y, const QRectF& bounds, int lock, double& out_x, double& out_y) -{ - qreal left = bounds.left(); - qreal right = bounds.right(); - // notice top/bottom switch here. - qreal bottom = bounds.top(); - qreal top = bounds.bottom(); - - out_x = x; - out_y = y; - - if (x <= left || (lock & GradientEditor::LockToLeft)) - out_x = left; - else if (x >= right || (lock & GradientEditor::LockToRight)) - out_x = right; - - if (y >= top || (lock & GradientEditor::LockToTop)) - out_y = top; - else if (y <= bottom || (lock & GradientEditor::LockToBottom)) - out_y = bottom; -} - -static constexpr double SCATTERSIZE = 10.0; - -GradientEditor::GradientEditor(const Histogram& histogram, QWidget* parent) - : QWidget(parent) - , m_histogram(histogram) -{ - QVBoxLayout* vbox = new QVBoxLayout(this); - vbox->setSpacing(1); - - m_customPlot = new QCustomPlot(this); - - // first graph will be histogram - QPalette pal = m_customPlot->palette(); - QColor histFillColor = pal.color(QPalette::Link).lighter(150); - m_histogramBars = new QCPBars(m_customPlot->xAxis, m_customPlot->yAxis); - QBrush barBrush = m_histogramBars->brush(); - barBrush.setColor(histFillColor); - m_histogramBars->setBrush(barBrush); - m_histogramBars->setPen(Qt::NoPen); - m_histogramBars->setWidthType(QCPBars::wtPlotCoords); - float firstBinCenter, lastBinCenter, binSize; - histogram.bin_range(histogram._bins.size(), firstBinCenter, lastBinCenter, binSize); - m_histogramBars->setWidth(binSize); - QVector keyData; - QVector valueData; - static constexpr double MIN_BAR_HEIGHT = 0.01; // Minimum height for nonzero bins (0.1% of max) - for (size_t i = 0; i < histogram._bins.size(); ++i) { - keyData << firstBinCenter + i * binSize; - if (histogram._bins[i] == 0) { - // Zero bins get zero height - valueData << 0.0; - } else { - // Nonzero bins get at least the minimum height - double normalizedHeight = (double)histogram._bins[i] / (double)histogram._bins[histogram._maxBin]; - valueData << std::max(normalizedHeight, MIN_BAR_HEIGHT); - } - } - m_histogramBars->setData(keyData, valueData); - m_histogramBars->setSelectable(QCP::stNone); - - // first added graph will the the piecewise linear transfer function - m_customPlot->addGraph(); - m_customPlot->graph(0)->setPen(QPen(Qt::black)); - QPen scatterPen(Qt::black); - scatterPen.setWidthF(1.0); - m_customPlot->graph(0)->setScatterStyle( - QCPScatterStyle(QCPScatterStyle::ssCircle, scatterPen, Qt::NoBrush, SCATTERSIZE)); - m_customPlot->graph(0)->setSelectable(QCP::stSingleData); - - // give the axes some labels: - m_customPlot->xAxis->setLabel(""); - m_customPlot->yAxis->setLabel(""); - - // set axes ranges, so we see all data: - m_customPlot->xAxis->setRange(histogram._dataMin, histogram._dataMax); - m_customPlot->xAxis->ticker()->setTickCount(4); - m_customPlot->xAxis->ticker()->setTickOrigin(histogram._dataMin); - auto tickLabelFont = m_customPlot->xAxis->tickLabelFont(); - tickLabelFont.setPointSize((float)tickLabelFont.pointSize() * 0.75); - m_customPlot->xAxis->setTickLabelFont(tickLabelFont); - QPen penx = m_customPlot->xAxis->basePen(); - penx.setWidthF(1.0); - m_customPlot->xAxis->setBasePen(penx); - - // increasing this will extend the Y axis up and down, so that the scatter handles are not clipped. - static constexpr double AXIS_OFFSET_FRACTION = 0.0; - m_customPlot->xAxis->setOffset(AXIS_OFFSET_FRACTION); - - m_customPlot->yAxis->setRange(0 - AXIS_OFFSET_FRACTION, 1 + AXIS_OFFSET_FRACTION); - m_customPlot->yAxis->ticker()->setTickCount(1); - tickLabelFont = m_customPlot->yAxis->tickLabelFont(); - tickLabelFont.setPointSize((float)tickLabelFont.pointSize() * 0.75); - m_customPlot->yAxis->setTickLabelFont(tickLabelFont); - QPen peny = m_customPlot->yAxis->basePen(); - peny.setWidthF(1.0); - m_customPlot->yAxis->setBasePen(peny); - - m_customPlot->xAxis->grid()->setVisible(true); - m_customPlot->xAxis->grid()->setSubGridVisible(true); - m_customPlot->yAxis->grid()->setVisible(true); - m_customPlot->yAxis->grid()->setSubGridVisible(true); - - m_customPlot->setInteractions( - QCP::iRangeDrag | QCP::iRangeZoom | - QCP::iSelectPlottables); // allow user to drag axis ranges with mouse, zoom with mouse wheel - m_customPlot->axisRect()->setRangeDrag(Qt::Horizontal); - m_customPlot->axisRect()->setRangeZoom(Qt::Horizontal); - - m_customPlot->replot(); - - connect(m_customPlot, &QCustomPlot::mousePress, this, &GradientEditor::onPlotMousePress); - connect(m_customPlot, &QCustomPlot::mouseMove, this, &GradientEditor::onPlotMouseMove); - connect(m_customPlot, &QCustomPlot::mouseRelease, this, &GradientEditor::onPlotMouseRelease); - connect(m_customPlot, &QCustomPlot::mouseWheel, this, &GradientEditor::onPlotMouseWheel); - connect(m_customPlot, &QCustomPlot::mouseDoubleClick, this, &GradientEditor::onPlotMouseDoubleClick); - - vbox->addWidget(m_customPlot); -} - -void -GradientEditor::changeEvent(QEvent* event) -{ - // This might be too many event types to check, but ThemeChange only seems to work on the QMainWindow. - // At least on Windows, changing dark mode to light mode incurs StyleChange and PaletteChange events too. - if (event->type() == QEvent::ThemeChange || event->type() == QEvent::ApplicationPaletteChange || - event->type() == QEvent::StyleChange || event->type() == QEvent::PaletteChange) { - // check for dark or light mode - auto sh = QGuiApplication::styleHints(); - auto colorScheme = sh->colorScheme(); - QColor plotLineColor; - QColor backgroundColor; - QColor barsColor; - QColor gridColor; - QColor subgridColor; - if (colorScheme == Qt::ColorScheme::Dark) { - barsColor = Qt::magenta; - barsColor.setAlphaF(0.5); - plotLineColor = this->palette().color(QPalette::Text); - backgroundColor = this->palette().color(QPalette::Window); - gridColor = plotLineColor.darker(150); - subgridColor = plotLineColor.darker(170); - } else if (colorScheme == Qt::ColorScheme::Light) { - barsColor = Qt::magenta; - barsColor.setAlphaF(0.25); - plotLineColor = this->palette().color(QPalette::Text); - backgroundColor = this->palette().color(QPalette::Window); - gridColor = plotLineColor.lighter(150); - subgridColor = plotLineColor.lighter(170); - } - m_customPlot->graph(0)->setPen(QPen(plotLineColor)); - QPen scatterPen(plotLineColor); - scatterPen.setWidthF(1.0); - m_customPlot->graph(0)->setScatterStyle( - QCPScatterStyle(QCPScatterStyle::ssCircle, scatterPen, Qt::NoBrush, SCATTERSIZE)); - m_customPlot->setBackground(QBrush(backgroundColor)); - m_customPlot->axisRect(); - - QPen basepen = m_customPlot->xAxis->basePen(); - basepen.setColor(plotLineColor); - m_customPlot->xAxis->setBasePen(basepen); - m_customPlot->yAxis->setBasePen(basepen); - - QPen gridpen = m_customPlot->xAxis->grid()->pen(); - gridpen.setColor(gridColor); - m_customPlot->xAxis->grid()->setPen(gridpen); - m_customPlot->yAxis->grid()->setPen(gridpen); - QPen subgridpen = m_customPlot->xAxis->grid()->subGridPen(); - subgridpen.setColor(subgridColor); - m_customPlot->xAxis->grid()->setSubGridPen(subgridpen); - m_customPlot->yAxis->grid()->setSubGridPen(subgridpen); - m_customPlot->xAxis->grid()->setAntialiasedSubGrid(true); - m_customPlot->yAxis->grid()->setAntialiasedSubGrid(true); - - QPen axisTickPen = m_customPlot->xAxis->tickPen(); - axisTickPen.setColor(plotLineColor); - m_customPlot->xAxis->setTickPen(axisTickPen); - m_customPlot->yAxis->setTickPen(axisTickPen); - m_customPlot->xAxis->setTickLabelColor(plotLineColor); - m_customPlot->yAxis->setTickLabelColor(plotLineColor); - QPen axisSubTickPen = m_customPlot->xAxis->subTickPen(); - axisSubTickPen.setColor(plotLineColor); - m_customPlot->xAxis->setSubTickPen(axisSubTickPen); - m_customPlot->yAxis->setSubTickPen(axisSubTickPen); - - m_histogramBars->setPen(Qt::NoPen); // QPen(barsColor)); - m_histogramBars->setBrush(QBrush(barsColor)); - - m_customPlot->replot(); - } - QWidget::changeEvent(event); -} - -void -GradientEditor::onPlotMousePress(QMouseEvent* event) -{ - // in custom mode, any click is either ON a point or creating a new point? - bool isCustomMode = (m_currentEditMode == GradientEditMode::CUSTOM); - bool isMinMaxMode = (m_currentEditMode == GradientEditMode::MINMAX); - bool isWindowLevelMode = (m_currentEditMode == GradientEditMode::WINDOW_LEVEL); - bool isPercentileMode = (m_currentEditMode == GradientEditMode::PERCENTILE); - bool isInteractiveMode = isCustomMode || isMinMaxMode || isWindowLevelMode || isPercentileMode; - - if (!isInteractiveMode) { - return; - } - - // let's look to see if a data point was clicked. - - int indexOfDataPoint = -1; - double dist = 1E+9; - - auto graph = m_customPlot->graph(0); - for (int n = 0; n < (graph->data()->size()); n++) { - // get xy of each data pt in pixels. compare with scattersize. - // first hit wins. - double x = (graph->data()->begin() + n)->key; - double y = (graph->data()->begin() + n)->value; - double px = m_customPlot->xAxis->coordToPixel(x); - double py = m_customPlot->yAxis->coordToPixel(y); - double dx = (px - (double)event->pos().x()); - double dy = (py - (double)event->pos().y()); - dist = sqrt(dx * dx + dy * dy); - if (dist < SCATTERSIZE / 2.0) { - indexOfDataPoint = n; - // remember dist! - break; - } - } - - if (event->button() == Qt::LeftButton) { - - // if we didn't click on a point, then we could add a point (only in custom mode): - if (indexOfDataPoint == -1 && isCustomMode) { - // this checks to see if user clicked along the line anywhere close. - QCPGraph* plottable = m_customPlot->plottableAt(event->pos(), true, &indexOfDataPoint); - if (plottable != nullptr && indexOfDataPoint > -1) { - // create a new point at x, y - double x = m_customPlot->xAxis->pixelToCoord(event->pos().x()); - double y = m_customPlot->yAxis->pixelToCoord(event->pos().y()); - // find first point above x to know the index? - for (int n = 0; n < (graph->data()->size()); n++) { - // get xy of each data pt in pixels. compare with scattersize. - // first hit wins. - double xn = (graph->data()->begin() + n)->key; - if (x < xn) { - // the index of x will be n. - indexOfDataPoint = n; - break; - } - } - m_locks.insert(indexOfDataPoint, 0); - graph->addData(x, y); - graph->data()->sort(); - m_customPlot->replot(); - } - } - - if (indexOfDataPoint > -1) { - // In MINMAX, Window/Level, and Percentile modes, only allow dragging of second and third points (threshold - // points) - if (isMinMaxMode || isWindowLevelMode || isPercentileMode) { - int dataSize = graph->data()->size(); - if (indexOfDataPoint != 1 && indexOfDataPoint != 2) { - // Not the second or third point (threshold points), don't allow dragging - return; - } - } - - m_isDraggingPoint = true; - m_currentPointIndex = indexOfDataPoint; - // turn off axis dragging while we are dragging a point - m_customPlot->axisRect()->setRangeDrag((Qt::Orientations)0); - // swallow this event so it doesn't propagate to the plot - event->accept(); - } - } else if (event->button() == Qt::RightButton) { - // Only allow point deletion in custom mode - if (indexOfDataPoint >= 0 && isCustomMode) { - if (m_locks[indexOfDataPoint] == 0) { - m_locks.remove(indexOfDataPoint); - // remove data pt from plot - graph->data()->remove((graph->data()->begin() + indexOfDataPoint)->key); - - // update the stuff because we did something - emit gradientStopsChanged(this->buildStopsFromPlot()); - m_customPlot->replot(); - event->accept(); - } - } - } -} -void -GradientEditor::onPlotMouseMove(QMouseEvent* event) -{ - bool isCustomMode = (m_currentEditMode == GradientEditMode::CUSTOM); - bool isMinMaxMode = (m_currentEditMode == GradientEditMode::MINMAX); - bool isWindowLevelMode = (m_currentEditMode == GradientEditMode::WINDOW_LEVEL); - bool isPercentileMode = (m_currentEditMode == GradientEditMode::PERCENTILE); - bool isInteractiveMode = isCustomMode || isMinMaxMode || isWindowLevelMode || isPercentileMode; - - if (!isInteractiveMode) { - return; - } - - if (m_isDraggingPoint && m_currentPointIndex >= 0) { - if (event->buttons() & Qt::LeftButton) { - auto graph = m_customPlot->graph(0); - double evx = m_customPlot->xAxis->pixelToCoord(event->pos().x()); - double evy = m_customPlot->yAxis->pixelToCoord(event->pos().y()); - - // Handle threshold-based modes (MINMAX, Window/Level, Percentile) differently - if (isMinMaxMode || isWindowLevelMode || isPercentileMode) { - // In threshold-based modes, keep Y value constant and only allow horizontal movement - double originalY = (graph->data()->begin() + m_currentPointIndex)->value; - evy = originalY; // Keep Y constant - - static constexpr double OVERLAP_EPSILON = 0.001; - // Apply additional constraints for min/max threshold points - if (m_currentPointIndex == 1) { - // This is the min threshold point - don't let it go past the max threshold point - if (graph->data()->size() > 2) { - double maxThresholdX = (graph->data()->begin() + 2)->key; - evx = std::min(evx, maxThresholdX - OVERLAP_EPSILON); // Small epsilon to prevent overlap - } - // Also don't let it go before the first fixed point - if (graph->data()->size() > 0) { - double firstPointX = (graph->data()->begin())->key; - evx = std::max(evx, firstPointX + OVERLAP_EPSILON); - } - } else if (m_currentPointIndex == 2) { - // This is the max threshold point - don't let it go past the min threshold point - if (graph->data()->size() > 1) { - double minThresholdX = (graph->data()->begin() + 1)->key; - evx = std::max(evx, minThresholdX + OVERLAP_EPSILON); // Small epsilon to prevent overlap - } - // Also don't let it go past the last fixed point - if (graph->data()->size() > 3) { - double lastPointX = (graph->data()->begin() + 3)->key; - evx = std::min(evx, lastPointX - OVERLAP_EPSILON); - } - } - } - - // see hoverpoints.cpp. - // this will make sure we don't move past locked edges in the bounding rectangle. - double px = evx, py = evy; - bound_point(evx, - evy, - // we really want clipRect() here? to capture zoomed region - QRectF(m_histogram._dataMin, 0.0f, m_histogram._dataMax - m_histogram._dataMin, 1.0f), - m_locks.at(m_currentPointIndex), - px, - py); - - // if we are dragging a point then move it - (graph->data()->begin() + m_currentPointIndex)->value = py; - (graph->data()->begin() + m_currentPointIndex)->key = px; - - // In MINMAX mode, don't sort - keep points in their fixed positions - if (!isMinMaxMode) { - // The point may have moved past other points, so sort, - // and account for current point index possibly changing. - // TODO should we always sort on every move? Or can we tell if we crossed another point? - graph->data().data()->sort(); - // find new index of current point - // find first point above x to know the index? - int indexOfDataPoint = m_currentPointIndex; - for (int n = 0; n < (graph->data()->size()); n++) { - // get xy of each data pt in pixels. compare with scattersize. - // first hit wins. - double xn = (graph->data()->begin() + n)->key; - if (px == xn) { - // the index of x will be n. - indexOfDataPoint = n; - break; - } - } - if (indexOfDataPoint != m_currentPointIndex) { - m_currentPointIndex = indexOfDataPoint; - } - } - - // In threshold-based modes, emit interactivePointsChanged for real-time slider updates - // Use the second and third points (indices 1 and 2) as the threshold points - if ((isMinMaxMode || isWindowLevelMode || isPercentileMode) && graph->data()->size() >= 4) { - double minThresholdX = (graph->data()->begin() + 1)->key; - double maxThresholdX = (graph->data()->begin() + 2)->key; - emit interactivePointsChanged(minThresholdX, maxThresholdX); - } - - // emit( DataChanged() ); - - emit gradientStopsChanged(this->buildStopsFromPlot()); - - m_customPlot->replot(); - } - } -} - -QGradientStops -GradientEditor::buildStopsFromPlot() -{ - // build up coords from the customplot into the form of gradient stops - QGradientStops stops; - - auto graph = m_customPlot->graph(0); - for (int n = 0; n < (graph->data()->size()); n++) { - auto dataIter = graph->data()->begin() + n; - double x = dataIter->key; - // skip duplicates? - if (n + 1 < graph->data()->size() && x == graph->data()->at(n + 1)->key) - continue; - - // rescale x to 0-1 range. - x = (x - m_histogram._dataMin) / (m_histogram._dataMax - m_histogram._dataMin); - double y = dataIter->value; - - QColor color = QColor::fromRgbF(y, y, y, y); - if (x > 1.0) { - LOG_ERROR << "control point x greater than 1"; - return stops; - } - - stops << QGradientStop(x, color); - } - return stops; -} - -void -GradientEditor::onPlotMouseRelease(QMouseEvent* event) -{ - Q_UNUSED(event); - if (m_currentEditMode != GradientEditMode::CUSTOM && m_currentEditMode != GradientEditMode::MINMAX && - m_currentEditMode != GradientEditMode::WINDOW_LEVEL && m_currentEditMode != GradientEditMode::PERCENTILE) { - return; - } - // if we were dragging a point then stop - m_isDraggingPoint = false; - m_currentPointIndex = -1; - // re-enable axis dragging - m_customPlot->axisRect()->setRangeDrag(Qt::Horizontal); -} - -void -GradientEditor::onPlotMouseDoubleClick(QMouseEvent* event) -{ - // double click should reset zoom - this->m_customPlot->rescaleAxes(); - this->m_customPlot->replot(); -} - -void -GradientEditor::onPlotMouseWheel(QWheelEvent* event) -{ - Q_UNUSED(event); -} - -inline static bool -x_less_than(const QPointF& p1, const QPointF& p2) -{ - return p1.x() < p2.x(); -} - -inline static bool -controlpoint_x_less_than(const LutControlPoint& p1, const LutControlPoint& p2) -{ - return p1.first < p2.first; -} - -QGradientStops -pointsToGradientStops(QPolygonF points) -{ - QGradientStops stops; - std::sort(points.begin(), points.end(), x_less_than); - - for (int i = 0; i < points.size(); ++i) { - qreal x = points.at(i).x(); - if (i + 1 < points.size() && x == points.at(i + 1).x()) - continue; - float pixelvalue = points.at(i).y(); - // TODO future: let each point have a full RGBA color and use a color picker to assign it via dbl - // click or some other means - - QColor color = QColor::fromRgbF(pixelvalue, pixelvalue, pixelvalue, pixelvalue); - if (x > 1) { - return stops; - } - - stops << QGradientStop(x, color); - } - return stops; -} - -void -GradientEditor::set_shade_points(const QPolygonF& points, QCustomPlot* plot, const Histogram& histogram) -{ - if (points.size() < 2) { - return; - } - - QGradientStops stops = pointsToGradientStops(points); - - m_locks.clear(); - if (points.size() > 0) { - m_locks.resize(points.size()); - m_locks.fill(0); - } - m_locks[0] = GradientEditor::LockToLeft; - m_locks[points.size() - 1] = GradientEditor::LockToRight; - - QVector x, y; - for (int i = 0; i < points.size(); ++i) { - // incoming points x values are in 0-1 range which is normalized to histogram data range - float dx = histogram._dataMin + points.at(i).x() * (histogram._dataMax - histogram._dataMin); - x << dx; - y << points.at(i).y(); - } - plot->graph(0)->setData(x, y); - plot->replot(); -} - -void -GradientEditor::setControlPoints(const std::vector& points) -{ - QPolygonF pts_alpha; - - for (auto p : points) { - pts_alpha << QPointF(p.first, p.second); - } - - set_shade_points(pts_alpha, m_customPlot, m_histogram); -} - -void -GradientEditor::wheelEvent(QWheelEvent* event) -{ - // wheel does nothing here! - event->ignore(); -} - -GradientWidget::GradientWidget(const Histogram& histogram, GradientData* dataObject, QWidget* parent) - : QWidget(parent) - , m_histogram(histogram) - , m_gradientData(dataObject) -{ - QVBoxLayout* mainGroupLayout = new QVBoxLayout(this); - - m_editor = new GradientEditor(m_histogram, this); - mainGroupLayout->addWidget(m_editor); - - auto* sectionLayout = Controls::createAgaveFormLayout(); - - QButtonGroup* btnGroup = new QButtonGroup(this); - QPushButton* minMaxButton = new QPushButton("Min/Max"); - minMaxButton->setToolTip(tr("Min/Max")); - minMaxButton->setStatusTip(tr("Choose Min/Max mode")); - QPushButton* windowLevelButton = new QPushButton("Wnd/Lvl"); - windowLevelButton->setToolTip(tr("Window/Level")); - windowLevelButton->setStatusTip(tr("Choose Window/Level mode")); - QPushButton* isoButton = new QPushButton("Iso"); - isoButton->setToolTip(tr("Isovalue")); - isoButton->setStatusTip(tr("Choose Isovalue mode")); - QPushButton* pctButton = new QPushButton("Pct"); - pctButton->setToolTip(tr("Histogram Percentiles")); - pctButton->setStatusTip(tr("Choose Histogram percentiles mode")); - QPushButton* customButton = new QPushButton("Custom"); - customButton->setToolTip(tr("Custom")); - customButton->setStatusTip(tr("Choose Custom editing mode")); - - static const int WINDOW_LEVEL_BTNID = 1; - static const int ISO_BTNID = 2; - static const int PCT_BTNID = 3; - static const int CUSTOM_BTNID = 4; - static const int MINMAX_BTNID = 5; - static std::map btnIdToGradientMode = { { WINDOW_LEVEL_BTNID, GradientEditMode::WINDOW_LEVEL }, - { ISO_BTNID, GradientEditMode::ISOVALUE }, - { PCT_BTNID, GradientEditMode::PERCENTILE }, - { MINMAX_BTNID, GradientEditMode::MINMAX }, - { CUSTOM_BTNID, GradientEditMode::CUSTOM } }; - static std::map gradientModeToBtnId = { { GradientEditMode::WINDOW_LEVEL, WINDOW_LEVEL_BTNID }, - { GradientEditMode::ISOVALUE, ISO_BTNID }, - { GradientEditMode::PERCENTILE, PCT_BTNID }, - { GradientEditMode::MINMAX, MINMAX_BTNID }, - { GradientEditMode::CUSTOM, CUSTOM_BTNID } }; - static std::map btnIdToStackedPage = { - { WINDOW_LEVEL_BTNID, 1 }, { ISO_BTNID, 2 }, { PCT_BTNID, 3 }, { MINMAX_BTNID, 0 }, { CUSTOM_BTNID, 4 } - }; - btnGroup->addButton(minMaxButton, MINMAX_BTNID); - btnGroup->addButton(windowLevelButton, WINDOW_LEVEL_BTNID); - btnGroup->addButton(isoButton, ISO_BTNID); - btnGroup->addButton(pctButton, PCT_BTNID); - btnGroup->addButton(customButton, CUSTOM_BTNID); - QHBoxLayout* hbox = new QHBoxLayout(); - hbox->setSpacing(0); - - int initialButtonId = WINDOW_LEVEL_BTNID; - GradientEditMode m = m_gradientData->m_activeMode; - initialButtonId = gradientModeToBtnId[m]; - - for (auto btn : btnGroup->buttons()) { - btn->setCheckable(true); - // set checked state initially. - int btnid = btnGroup->id(btn); - if (btnid == initialButtonId) { - btn->setChecked(true); - } - hbox->addWidget(btn); - } - mainGroupLayout->addLayout(hbox); - - QWidget* firstPageWidget = new QWidget; - auto* section0Layout = Controls::createAgaveFormLayout(); - firstPageWidget->setLayout(section0Layout); - - QWidget* secondPageWidget = new QWidget; - auto* section1Layout = Controls::createAgaveFormLayout(); - secondPageWidget->setLayout(section1Layout); - - QWidget* thirdPageWidget = new QWidget; - auto* section2Layout = Controls::createAgaveFormLayout(); - thirdPageWidget->setLayout(section2Layout); - - QWidget* fourthPageWidget = new QWidget; - auto* section3Layout = Controls::createAgaveFormLayout(); - fourthPageWidget->setLayout(section3Layout); - - QWidget* fifthPageWidget = new QWidget; - auto* section4Layout = Controls::createAgaveFormLayout(); - fifthPageWidget->setLayout(section4Layout); - - QStackedLayout* stackedLayout = new QStackedLayout(mainGroupLayout); - stackedLayout->addWidget(firstPageWidget); - stackedLayout->addWidget(secondPageWidget); - stackedLayout->addWidget(thirdPageWidget); - stackedLayout->addWidget(fourthPageWidget); - stackedLayout->addWidget(fifthPageWidget); - - int initialStackedPageIndex = btnIdToStackedPage[initialButtonId]; - stackedLayout->setCurrentIndex(initialStackedPageIndex); - // if this is not custom mode, then disable the gradient editor - // m_editor->setEditable(m == GradientEditMode::CUSTOM); - m_editor->setEditMode(m); - - connect(btnGroup, - QOverload::of(&QButtonGroup::buttonClicked), - [this, btnGroup, stackedLayout](QAbstractButton* button) { - int id = btnGroup->id(button); - GradientEditMode modeToSet = btnIdToGradientMode[id]; - // if mode is not changing, we are done. - if (modeToSet == this->m_gradientData->m_activeMode) { - return; - } - this->m_gradientData->m_activeMode = modeToSet; - - stackedLayout->setCurrentIndex(btnIdToStackedPage[id]); - - // if this is not custom mode, then disable the gradient editor - // m_editor->setEditable(modeToSet == GradientEditMode::CUSTOM); - m_editor->setEditMode(modeToSet); - - this->forceDataUpdate(); - }); - - minu16Slider = new QIntSlider(); - minu16Slider->setStatusTip(tr("Minimum u16 value")); - minu16Slider->setToolTip(tr("Set minimum u16 value")); - minu16Slider->setRange(m_histogram._dataMin, m_histogram._dataMax); - minu16Slider->setSingleStep(1); - minu16Slider->setValue(m_gradientData->m_minu16); - section0Layout->addRow("Min u16", minu16Slider); - maxu16Slider = new QIntSlider(); - maxu16Slider->setStatusTip(tr("Maximum u16 value")); - maxu16Slider->setToolTip(tr("Set maximum u16 value")); - maxu16Slider->setRange(m_histogram._dataMin, m_histogram._dataMax); - maxu16Slider->setSingleStep(1); - maxu16Slider->setValue(m_gradientData->m_maxu16); - section0Layout->addRow("Max u16", maxu16Slider); - connect(minu16Slider, &QIntSlider::valueChanged, [this](int i) { - this->m_gradientData->m_minu16 = i; - this->onSetMinMax(i, this->m_gradientData->m_maxu16); - }); - connect(maxu16Slider, &QIntSlider::valueChanged, [this](int i) { - this->m_gradientData->m_maxu16 = i; - this->onSetMinMax(this->m_gradientData->m_minu16, i); - }); - - windowSlider = new QNumericSlider(); - windowSlider->setStatusTip(tr("Window")); - windowSlider->setToolTip(tr("Set size of range of intensities")); - windowSlider->setRange(0.0, 1.0); - windowSlider->setSingleStep(0.01); - windowSlider->setDecimals(3); - windowSlider->setValue(m_gradientData->m_window); - section1Layout->addRow("Window", windowSlider); - levelSlider = new QNumericSlider(); - levelSlider->setStatusTip(tr("Level")); - levelSlider->setToolTip(tr("Set level of mid intensity")); - levelSlider->setRange(0.0, 1.0); - levelSlider->setSingleStep(0.01); - levelSlider->setDecimals(3); - levelSlider->setValue(m_gradientData->m_level); - section1Layout->addRow("Level", levelSlider); - connect(windowSlider, &QNumericSlider::valueChanged, [this](double d) { - this->m_gradientData->m_window = d; - this->onSetWindowLevel(d, levelSlider->value()); - }); - connect(levelSlider, &QNumericSlider::valueChanged, [this](double d) { - this->m_gradientData->m_level = d; - this->onSetWindowLevel(windowSlider->value(), d); - }); - - isovalueSlider = new QNumericSlider(); - isovalueSlider->setStatusTip(tr("Isovalue")); - isovalueSlider->setToolTip(tr("Set Isovalue")); - isovalueSlider->setRange(0.0, 1.0); - isovalueSlider->setSingleStep(0.01); - isovalueSlider->setDecimals(3); - isovalueSlider->setValue(m_gradientData->m_isovalue); - section2Layout->addRow("Isovalue", isovalueSlider); - isorangeSlider = new QNumericSlider(); - isorangeSlider->setStatusTip(tr("Isovalue range")); - isorangeSlider->setToolTip(tr("Set range above and below isovalue")); - isorangeSlider->setRange(0.0, 1.0); - isorangeSlider->setSingleStep(0.01); - isorangeSlider->setDecimals(3); - isorangeSlider->setValue(m_gradientData->m_isorange); - section2Layout->addRow("Iso-range", isorangeSlider); - connect(isovalueSlider, &QNumericSlider::valueChanged, [this](double d) { - this->m_gradientData->m_isovalue = d; - this->onSetIsovalue(d, isorangeSlider->value()); - }); - connect(isorangeSlider, &QNumericSlider::valueChanged, [this](double d) { - this->m_gradientData->m_isorange = d; - this->onSetIsovalue(isovalueSlider->value(), d); - }); - - pctLowSlider = new QNumericSlider(); - pctLowSlider->setStatusTip(tr("Low percentile")); - pctLowSlider->setToolTip(tr("Set bottom percentile")); - pctLowSlider->setRange(0.0, 1.0); - pctLowSlider->setSingleStep(0.01); - pctLowSlider->setDecimals(3); - pctLowSlider->setValue(m_gradientData->m_pctLow); - section3Layout->addRow("Pct Min", pctLowSlider); - pctHighSlider = new QNumericSlider(); - pctHighSlider->setStatusTip(tr("High percentile")); - pctHighSlider->setToolTip(tr("Set top percentile")); - pctHighSlider->setRange(0.0, 1.0); - pctHighSlider->setSingleStep(0.01); - pctHighSlider->setDecimals(3); - pctHighSlider->setValue(m_gradientData->m_pctHigh); - section3Layout->addRow("Pct Max", pctHighSlider); - connect(pctLowSlider, &QNumericSlider::valueChanged, [this](double d) { - this->m_gradientData->m_pctLow = d; - this->onSetHistogramPercentiles(d, pctHighSlider->value()); - }); - connect(pctHighSlider, &QNumericSlider::valueChanged, [this](double d) { - this->m_gradientData->m_pctHigh = d; - this->onSetHistogramPercentiles(pctLowSlider->value(), d); - }); - - mainGroupLayout->addLayout(sectionLayout); - mainGroupLayout->addStretch(1); - - connect(m_editor, &GradientEditor::gradientStopsChanged, this, &GradientWidget::onGradientStopsChanged); - connect(m_editor, &GradientEditor::interactivePointsChanged, this, &GradientWidget::onInteractivePointsChanged); - - forceDataUpdate(); -} - -void -GradientWidget::forceDataUpdate() -{ - GradientEditMode mode = this->m_gradientData->m_activeMode; - - switch (mode) { - case GradientEditMode::WINDOW_LEVEL: - this->onSetWindowLevel(this->m_gradientData->m_window, this->m_gradientData->m_level); - break; - case GradientEditMode::ISOVALUE: - this->onSetIsovalue(this->m_gradientData->m_isovalue, this->m_gradientData->m_isorange); - break; - case GradientEditMode::PERCENTILE: - this->onSetHistogramPercentiles(this->m_gradientData->m_pctLow, this->m_gradientData->m_pctHigh); - break; - case GradientEditMode::MINMAX: - this->onSetMinMax(this->m_gradientData->m_minu16, this->m_gradientData->m_maxu16); - break; - case GradientEditMode::CUSTOM: { - m_editor->setControlPoints(this->m_gradientData->m_customControlPoints); - QGradientStops stops = vectorToGradientStops(this->m_gradientData->m_customControlPoints); - emit gradientStopsChanged(stops); - } break; - default: - LOG_ERROR << "Bad gradient editor mode"; - break; - } -} - -void -GradientWidget::onGradientStopsChanged(const QGradientStops& stops) -{ - // update the data stored in m_gradientData - // depending on our mode: - if (m_gradientData->m_activeMode == GradientEditMode::CUSTOM) { - m_gradientData->m_customControlPoints.clear(); - for (int i = 0; i < stops.size(); ++i) { - m_gradientData->m_customControlPoints.push_back(LutControlPoint(stops.at(i).first, stops.at(i).second.alphaF())); - } - emit gradientStopsChanged(stops); - } else if (m_gradientData->m_activeMode == GradientEditMode::WINDOW_LEVEL) { - // extract window and level from the stops - use second and third points (threshold points) - std::vector points = gradientStopsToVector(const_cast(stops)); - if (points.size() < 4) { - return; - } - std::sort(points.begin(), points.end(), controlpoint_x_less_than); - float low = points[1].first; // Second point (low threshold) - float high = points[2].first; // Third point (high threshold) - float window = high - low; - float level = (high + low) * 0.5f; - m_gradientData->m_window = window; - m_gradientData->m_level = level; - - // update the sliders to match: - windowSlider->setValue(window); - levelSlider->setValue(level); - - } else if (m_gradientData->m_activeMode == GradientEditMode::ISOVALUE) { - // extract isovalue and range from the stops - std::vector points = gradientStopsToVector(const_cast(stops)); - if (points.size() < 2) { - return; - } - std::sort(points.begin(), points.end(), controlpoint_x_less_than); - float low = points[0].first; - float high = points[1].first; - float isovalue = (high + low) * 0.5f; - float isorange = high - low; - m_gradientData->m_isovalue = isovalue; - m_gradientData->m_isorange = isorange; - - // update the sliders to match: - isovalueSlider->setValue(isovalue); - isorangeSlider->setValue(isorange); - } else if (m_gradientData->m_activeMode == GradientEditMode::PERCENTILE) { - // get percentiles from the stops and histogram - use second and third points (threshold points) - std::vector points = gradientStopsToVector(const_cast(stops)); - if (points.size() < 4) { - return; - } - std::sort(points.begin(), points.end(), controlpoint_x_less_than); - float low = points[1].first; // Second point (low threshold) - float high = points[2].first; // Third point (high threshold) - // calculate percentiles from the histogram: - uint16_t ulow = m_histogram._dataMin + static_cast(low * (m_histogram._dataMax - m_histogram._dataMin)); - uint16_t uhigh = m_histogram._dataMin + static_cast(high * (m_histogram._dataMax - m_histogram._dataMin)); - float pctLow = 0.0f, pctHigh = 1.0f; - m_histogram.computePercentile(ulow, pctLow); - m_histogram.computePercentile(uhigh, pctHigh); - m_gradientData->m_pctLow = pctLow; - m_gradientData->m_pctHigh = pctHigh; - - // update the sliders to match: - pctLowSlider->setValue(pctLow); - pctHighSlider->setValue(pctHigh); - } else if (m_gradientData->m_activeMode == GradientEditMode::MINMAX) { - // get absolute min/max from the stops - use second and third points (threshold points) - std::vector points = gradientStopsToVector(const_cast(stops)); - if (points.size() < 4) { - return; - } - std::sort(points.begin(), points.end(), controlpoint_x_less_than); - // turn the second and third points' x values into u16 intensities from the histogram range: - float low = points[1].first; // Second point (min threshold) - float high = points[2].first; // Third point (max threshold) - // calculate percentiles from the histogram: - uint16_t ulow = m_histogram._dataMin + static_cast(low * (m_histogram._dataMax - m_histogram._dataMin)); - uint16_t uhigh = m_histogram._dataMin + static_cast(high * (m_histogram._dataMax - m_histogram._dataMin)); - m_gradientData->m_minu16 = ulow; - m_gradientData->m_maxu16 = uhigh; - - // update the sliders to match: - minu16Slider->setValue(ulow); - maxu16Slider->setValue(uhigh); - } -} - -void -GradientWidget::onSetHistogramPercentiles(float pctLow, float pctHigh) -{ - float window, level; - m_histogram.computeWindowLevelFromPercentiles(pctLow, pctHigh, window, level); - this->onSetWindowLevel(window, level); -} - -void -GradientWidget::onSetWindowLevel(float window, float level) -{ - std::vector points; - static const float epsilon = 0.000001f; - window = std::max(window, epsilon); - float lowEnd = level - window * 0.5f; - float highEnd = level + window * 0.5f; - if (lowEnd <= 0.0f) { - float val = -lowEnd / (highEnd - lowEnd); - points.push_back({ 0.0f, val }); - } else { - points.push_back({ 0.0f, 0.0f }); - points.push_back({ lowEnd, 0.0f }); - } - if (highEnd >= 1.0f) { - float val = (1.0f - lowEnd) / (highEnd - lowEnd); - points.push_back({ 1.0f, val }); - } else { - points.push_back({ highEnd, 1.0f }); - points.push_back({ 1.0f, 1.0f }); - } - m_editor->setControlPoints(points); - emit gradientStopsChanged(vectorToGradientStops(points)); -} - -void -GradientWidget::onSetMinMax(uint16_t minu16, uint16_t maxu16) -{ - // these need to be relative to the data range of the channel, not absolute! - float relativeMin = normalizeInt(minu16, m_histogram._dataMin, m_histogram._dataMax); - float relativeMax = normalizeInt(maxu16, m_histogram._dataMin, m_histogram._dataMax); - relativeMin = std::max(relativeMin, 0.0f); - relativeMax = std::min(relativeMax, 1.0f); - if (relativeMin >= relativeMax) { - LOG_ERROR << "Min value is greater than or equal to max value: " << minu16 << " >= " << maxu16 - << ", datarange=" << m_histogram.dataRange(); - return; - } - float window = relativeMax - relativeMin; - float level = (relativeMax + relativeMin) / 2.0f; - this->onSetWindowLevel(window, level); -} - -void -GradientWidget::onSetIsovalue(float isovalue, float width) -{ - std::vector points; - float lowEnd = isovalue - width * 0.5f; - float highEnd = isovalue + width * 0.5f; - static const float epsilon = 0.00001f; - points.push_back({ 0.0f, 0.0f }); - points.push_back({ lowEnd - epsilon, 0.0f }); - points.push_back({ lowEnd + epsilon, 1.0f }); - points.push_back({ highEnd - epsilon, 1.0f }); - points.push_back({ highEnd + epsilon, 0.0f }); - points.push_back({ 1.0f, 0.0f }); - m_editor->setControlPoints(points); - emit gradientStopsChanged(vectorToGradientStops(points)); -} - -void -GradientWidget::onInteractivePointsChanged(float minIntensity, float maxIntensity) -{ - // Handle different modes appropriately - if (m_gradientData->m_activeMode == GradientEditMode::MINMAX) { - // Convert from graph coordinates (histogram data range) to u16 intensity values - uint16_t minu16 = static_cast(minIntensity); - uint16_t maxu16 = static_cast(maxIntensity); - - // Ensure values are within valid range - minu16 = std::max(minu16, static_cast(m_histogram._dataMin)); - maxu16 = std::min(maxu16, static_cast(m_histogram._dataMax)); - - // Update the data - m_gradientData->m_minu16 = minu16; - m_gradientData->m_maxu16 = maxu16; - - // Update sliders without triggering their signals (to avoid feedback loops) - if (minu16Slider) { - minu16Slider->blockSignals(true); - minu16Slider->setValue(minu16); - minu16Slider->blockSignals(false); - } - if (maxu16Slider) { - maxu16Slider->blockSignals(true); - maxu16Slider->setValue(maxu16); - maxu16Slider->blockSignals(false); - } - } else if (m_gradientData->m_activeMode == GradientEditMode::WINDOW_LEVEL) { - // Convert intensities to normalized values (0-1 range) - uint16_t minInt = static_cast(minIntensity); - uint16_t maxInt = static_cast(maxIntensity); - float relativeMin = normalizeInt(minInt, m_histogram._dataMin, m_histogram._dataMax); - float relativeMax = normalizeInt(maxInt, m_histogram._dataMin, m_histogram._dataMax); - - // Calculate window and level from the threshold points - float window = relativeMax - relativeMin; - float level = (relativeMax + relativeMin) * 0.5f; - - // Update the data - m_gradientData->m_window = window; - m_gradientData->m_level = level; - - // Update sliders without triggering their signals - if (windowSlider) { - windowSlider->blockSignals(true); - windowSlider->setValue(window); - windowSlider->blockSignals(false); - } - if (levelSlider) { - levelSlider->blockSignals(true); - levelSlider->setValue(level); - levelSlider->blockSignals(false); - } - } else if (m_gradientData->m_activeMode == GradientEditMode::PERCENTILE) { - // Convert intensities to u16 values first - uint16_t minu16 = static_cast(std::max(minIntensity, (float)m_histogram._dataMin)); - uint16_t maxu16 = static_cast(std::min(maxIntensity, (float)m_histogram._dataMax)); - - // Calculate percentiles by converting intensity to bin index and using cumulative counts - float pctLow = 0.0f, pctHigh = 1.0f; - - if (m_histogram._pixelCount > 0 && !m_histogram._ccounts.empty()) { - // For low percentile - if (minu16 <= m_histogram._dataMin) { - pctLow = 0.0f; - } else if (minu16 >= m_histogram._dataMax) { - pctLow = 1.0f; - } else { - m_histogram.computePercentile(minu16, pctLow); - } - - // For high percentile - if (maxu16 <= m_histogram._dataMin) { - pctHigh = 0.0f; - } else if (maxu16 >= m_histogram._dataMax) { - pctHigh = 1.0f; - } else { - m_histogram.computePercentile(maxu16, pctHigh); - } - } - - // Update the data - m_gradientData->m_pctLow = pctLow; - m_gradientData->m_pctHigh = pctHigh; - - // Update sliders without triggering their signals - if (pctLowSlider) { - pctLowSlider->blockSignals(true); - pctLowSlider->setValue(pctLow); - pctLowSlider->blockSignals(false); - } - if (pctHighSlider) { - pctHighSlider->blockSignals(true); - pctHighSlider->setValue(pctHigh); - pctHighSlider->blockSignals(false); - } - } -} +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gradients.h" +#include "hoverpoints.h" + +#include "qtControls/Controls.h" +#include "renderlib/Defines.h" +#include "renderlib/Logging.h" +#include "renderlib/MathUtil.h" + +#include + +std::vector +gradientStopsToVector(QGradientStops& stops) +{ + std::vector v; + for (int i = 0; i < stops.size(); ++i) { + v.push_back(LutControlPoint(stops.at(i).first, stops.at(i).second.alphaF())); + } + return v; +} + +QGradientStops +vectorToGradientStops(std::vector& v) +{ + QGradientStops stops; + for (int i = 0; i < v.size(); ++i) { + stops.push_back( + QPair(v[i].first, QColor::fromRgbF(v[i].second, v[i].second, v[i].second, v[i].second))); + } + return stops; +} + +ShadeWidget::ShadeWidget(const Histogram& histogram, ShadeType type, QWidget* parent) + : QWidget(parent) + , m_shade_type(type) + , m_alpha_gradient(QLinearGradient(0, 0, 0, 0)) + , m_histogram(histogram) +{ + // Checkers background + if (m_shade_type == ARGBShade) { + QPixmap pm(20, 20); + QPainter pmp(&pm); + pmp.fillRect(0, 0, 10, 10, Qt::lightGray); + pmp.fillRect(10, 10, 10, 10, Qt::lightGray); + pmp.fillRect(0, 10, 10, 10, Qt::darkGray); + pmp.fillRect(10, 0, 10, 10, Qt::darkGray); + pmp.end(); + QPalette pal = palette(); + pal.setBrush(backgroundRole(), QBrush(pm)); + setAutoFillBackground(true); + setPalette(pal); + + } else { + setAttribute(Qt::WA_OpaquePaintEvent); + } + + QPolygonF points; + points << QPointF(0.0f, 0.0f) << QPointF(1.0f, 1.0f); + + m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape); + // m_hoverPoints->setConnectionType(HoverPoints::LineConnection); + m_hoverPoints->setPoints(points); + m_hoverPoints->setPointLock(0, HoverPoints::LockToLeft); + m_hoverPoints->setPointLock(1, HoverPoints::LockToRight); + m_hoverPoints->setSortType(HoverPoints::XSort); + + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + connect(m_hoverPoints, &HoverPoints::pointsChanged, this, &ShadeWidget::colorsChanged); +} + +QPolygonF +ShadeWidget::points() const +{ + return m_hoverPoints->points(); +} + +void +ShadeWidget::setEditable(bool editable) +{ + m_hoverPoints->setEditable(editable); +} + +uint +ShadeWidget::colorAt(int x) +{ + generateShade(); + if (m_shade.isNull()) { + return 0; + } + + QPolygonF pts = m_hoverPoints->points(); + for (int i = 1; i < pts.size(); ++i) { + if (pts.at(i - 1).x() <= x && pts.at(i).x() >= x) { + QLineF l(pts.at(i - 1), pts.at(i)); + l.setLength(l.length() * ((x - l.x1()) / l.dx())); + return m_shade.pixel(qRound(qMin(l.x2(), (qreal(m_shade.width() - 1)))), + qRound(qMin(l.y2(), qreal(m_shade.height() - 1)))); + } + } + return 0; +} + +void +ShadeWidget::setGradientStops(const QGradientStops& stops) +{ + if (m_shade_type == ARGBShade) { + m_alpha_gradient = QLinearGradient(0, 0, width(), 0); + + for (int i = 0; i < stops.size(); ++i) { + QColor c = stops.at(i).second; + m_alpha_gradient.setColorAt(stops.at(i).first, QColor(c.red(), c.green(), c.blue())); + } + + m_shade = QImage(); + generateShade(); + update(); + } +} + +void +ShadeWidget::paintEvent(QPaintEvent*) +{ + generateShade(); + + QPainter p(this); + p.drawImage(0, 0, m_shade); + /* + qreal barWidth = width() / (qreal)m_histogram.size(); + + for (int i = 0; i < m_histogram.size(); ++i) { + qreal h = m_histogram[i] * height(); + // draw level + painter.fillRect(barWidth * i, height() - h, barWidth * (i + 1), height(), Qt::red); + // clear the rest of the control + painter.fillRect(barWidth * i, 0, barWidth * (i + 1), height() - h, Qt::black); + } + */ + p.setPen(QColor(146, 146, 146)); + p.drawRect(0, 0, width() - 1, height() - 1); +} + +void +ShadeWidget::drawHistogram(QPainter& p, int w, int h) +{ + size_t nbins = m_histogram._bins.size(); + int maxbinsize = m_histogram._bins[m_histogram._maxBin]; + for (size_t i = 0; i < nbins; ++i) { + float binheight = (float)m_histogram._bins[i] * (float)(h - 1) / (float)maxbinsize; + p.fillRect( + QRectF((float)i * (float)(w - 1) / (float)nbins, h - 1 - binheight, (float)(w - 1) / (float)nbins, binheight), + QColor(0, 0, 0, 255)); + } +} + +void +ShadeWidget::generateShade() +{ + if (m_shade.isNull() || m_shade.size() != size()) { + + QRect qrect = rect(); + QSize qsize = size(); + if (m_shade_type == ARGBShade) { + m_shade = QImage(qsize, QImage::Format_ARGB32_Premultiplied); + if (m_shade.isNull()) { + return; + } + m_shade.fill(0); + + QPainter p(&m_shade); + p.fillRect(qrect, m_alpha_gradient); + + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + QLinearGradient fade(0, 0, 0, height() - 1); + fade.setColorAt(0, QColor(255, 255, 255, 255)); + fade.setColorAt(1, QColor(0, 0, 0, 0)); + p.fillRect(qrect, fade); + + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + + drawHistogram(p, qsize.width(), qsize.height()); + + } else { + m_shade = QImage(qsize, QImage::Format_RGB32); + if (m_shade.isNull()) { + return; + } + QLinearGradient shade(0, 0, 0, height()); + shade.setColorAt(1, Qt::black); + + if (m_shade_type == RedShade) + shade.setColorAt(0, Qt::red); + else if (m_shade_type == GreenShade) + shade.setColorAt(0, Qt::green); + else + shade.setColorAt(0, Qt::blue); + + QPainter p(&m_shade); + p.fillRect(qrect, shade); + + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + + drawHistogram(p, qsize.width(), qsize.height()); + } + } +} + +GradientEditor::GradientEditor(const Histogram& histogram, QWidget* parent) + : QWidget(parent) +{ + QVBoxLayout* vbox = new QVBoxLayout(this); + vbox->setSpacing(1); + // vbox->setMargin(1); + + m_alpha_shade = new ShadeWidget(histogram, ShadeWidget::ARGBShade, this); + + vbox->addWidget(m_alpha_shade); + + connect(m_alpha_shade, &ShadeWidget::colorsChanged, this, &GradientEditor::pointsUpdated); +} + +inline static bool +x_less_than(const QPointF& p1, const QPointF& p2) +{ + return p1.x() < p2.x(); +} + +inline static bool +controlpoint_x_less_than(const LutControlPoint& p1, const LutControlPoint& p2) +{ + return p1.first < p2.first; +} + +QGradientStops +pointsToGradientStops(QPolygonF points) +{ + QGradientStops stops; + std::sort(points.begin(), points.end(), x_less_than); + + for (int i = 0; i < points.size(); ++i) { + qreal x = points.at(i).x(); + if (i + 1 < points.size() && x == points.at(i + 1).x()) + continue; + float pixelvalue = points.at(i).y(); + // TODO future: let each point in m_alpha_shade have a full RGBA color and use a color picker to assign it via dbl + // click or some other means + // unsigned int pixelvalue = m_alpha_shade->colorAt(int(x)); + // unsigned int r = (0x00ff0000 & pixelvalue) >> 16; + // unsigned int g = (0x0000ff00 & pixelvalue) >> 8; + // unsigned int b = (0x000000ff & pixelvalue); + // unsigned int a = (0xff000000 & pixelvalue) >> 24; + // QColor color(r, g, b, a); + + QColor color = QColor::fromRgbF(pixelvalue, pixelvalue, pixelvalue, pixelvalue); + if (x > 1) { + LOG_ERROR << "control point x greater than 1"; + return stops; + } + + stops << QGradientStop(x, color); + } + return stops; +} + +void +GradientEditor::pointsUpdated() +{ + // qreal w = m_alpha_shade->width(); + + QGradientStops stops = pointsToGradientStops(m_alpha_shade->points()); + + m_alpha_shade->setGradientStops(stops); + + emit gradientStopsChanged(stops); +} + +static void +set_shade_points(const QPolygonF& points, ShadeWidget* shade) +{ + if (points.size() < 2) { + return; + } + + QGradientStops stops = pointsToGradientStops(points); + shade->setGradientStops(stops); + + shade->hoverPoints()->setPoints(points); + shade->hoverPoints()->setPointLock(0, HoverPoints::LockToLeft); + shade->hoverPoints()->setPointLock(points.size() - 1, HoverPoints::LockToRight); + shade->update(); +} + +void +GradientEditor::setControlPoints(const std::vector& points) +{ + QPolygonF pts_alpha; + + for (auto p : points) { + pts_alpha << QPointF(p.first, p.second); + } + + set_shade_points(pts_alpha, m_alpha_shade); +} + +void +GradientEditor::wheelEvent(QWheelEvent* event) +{ + // wheel does nothing here! + event->ignore(); +} + +GradientWidget::GradientWidget(const Histogram& histogram, GradientData* dataObject, QWidget* parent) + : QWidget(parent) + , m_histogram(histogram) + , m_gradientData(dataObject) +{ + QVBoxLayout* mainGroupLayout = new QVBoxLayout(this); + + // setWindowTitle(tr("Gradients")); + + // QGroupBox* editorGroup = new QGroupBox(this); + // editorGroup->setTitle(tr("Color Editor")); + m_editor = new GradientEditor(m_histogram, this); + mainGroupLayout->addWidget(m_editor); + + auto* sectionLayout = Controls::createAgaveFormLayout(); + + QButtonGroup* btnGroup = new QButtonGroup(this); + QPushButton* minMaxButton = new QPushButton("Min/Max"); + minMaxButton->setToolTip(tr("Min/Max")); + minMaxButton->setStatusTip(tr("Choose Min/Max mode")); + QPushButton* windowLevelButton = new QPushButton("Wnd/Lvl"); + windowLevelButton->setToolTip(tr("Window/Level")); + windowLevelButton->setStatusTip(tr("Choose Window/Level mode")); + QPushButton* isoButton = new QPushButton("Iso"); + isoButton->setToolTip(tr("Isovalue")); + isoButton->setStatusTip(tr("Choose Isovalue mode")); + QPushButton* pctButton = new QPushButton("Pct"); + pctButton->setToolTip(tr("Histogram Percentiles")); + pctButton->setStatusTip(tr("Choose Histogram percentiles mode")); + QPushButton* customButton = new QPushButton("Custom"); + customButton->setToolTip(tr("Custom")); + customButton->setStatusTip(tr("Choose Custom editing mode")); + + static const int WINDOW_LEVEL_BTNID = 1; + static const int ISO_BTNID = 2; + static const int PCT_BTNID = 3; + static const int CUSTOM_BTNID = 4; + static const int MINMAX_BTNID = 5; + static std::map btnIdToGradientMode = { { WINDOW_LEVEL_BTNID, GradientEditMode::WINDOW_LEVEL }, + { ISO_BTNID, GradientEditMode::ISOVALUE }, + { PCT_BTNID, GradientEditMode::PERCENTILE }, + { MINMAX_BTNID, GradientEditMode::MINMAX }, + { CUSTOM_BTNID, GradientEditMode::CUSTOM } }; + static std::map gradientModeToBtnId = { { GradientEditMode::WINDOW_LEVEL, WINDOW_LEVEL_BTNID }, + { GradientEditMode::ISOVALUE, ISO_BTNID }, + { GradientEditMode::PERCENTILE, PCT_BTNID }, + { GradientEditMode::MINMAX, MINMAX_BTNID }, + { GradientEditMode::CUSTOM, CUSTOM_BTNID } }; + static std::map btnIdToStackedPage = { + { WINDOW_LEVEL_BTNID, 1 }, { ISO_BTNID, 2 }, { PCT_BTNID, 3 }, { MINMAX_BTNID, 0 }, { CUSTOM_BTNID, 4 } + }; + btnGroup->addButton(minMaxButton, MINMAX_BTNID); + btnGroup->addButton(windowLevelButton, WINDOW_LEVEL_BTNID); + btnGroup->addButton(isoButton, ISO_BTNID); + btnGroup->addButton(pctButton, PCT_BTNID); + btnGroup->addButton(customButton, CUSTOM_BTNID); + QHBoxLayout* hbox = new QHBoxLayout(); + hbox->setSpacing(0); + + int initialButtonId = WINDOW_LEVEL_BTNID; + GradientEditMode m = m_gradientData->m_activeMode; + initialButtonId = gradientModeToBtnId[m]; + + for (auto btn : btnGroup->buttons()) { + btn->setCheckable(true); + // set checked state initially. + int btnid = btnGroup->id(btn); + if (btnid == initialButtonId) { + btn->setChecked(true); + } + hbox->addWidget(btn); + } + mainGroupLayout->addLayout(hbox); + + QWidget* firstPageWidget = new QWidget; + auto* section0Layout = Controls::createAgaveFormLayout(); + firstPageWidget->setLayout(section0Layout); + + QWidget* secondPageWidget = new QWidget; + auto* section1Layout = Controls::createAgaveFormLayout(); + secondPageWidget->setLayout(section1Layout); + + QWidget* thirdPageWidget = new QWidget; + auto* section2Layout = Controls::createAgaveFormLayout(); + thirdPageWidget->setLayout(section2Layout); + + QWidget* fourthPageWidget = new QWidget; + auto* section3Layout = Controls::createAgaveFormLayout(); + fourthPageWidget->setLayout(section3Layout); + + QWidget* fifthPageWidget = new QWidget; + auto* section4Layout = Controls::createAgaveFormLayout(); + fifthPageWidget->setLayout(section4Layout); + + QStackedLayout* stackedLayout = new QStackedLayout(mainGroupLayout); + stackedLayout->addWidget(firstPageWidget); + stackedLayout->addWidget(secondPageWidget); + stackedLayout->addWidget(thirdPageWidget); + stackedLayout->addWidget(fourthPageWidget); + stackedLayout->addWidget(fifthPageWidget); + + int initialStackedPageIndex = btnIdToStackedPage[initialButtonId]; + stackedLayout->setCurrentIndex(initialStackedPageIndex); + // if this is not custom mode, then disable the gradient editor + m_editor->setEditable(m == GradientEditMode::CUSTOM); + + connect(btnGroup, + QOverload::of(&QButtonGroup::buttonClicked), + [this, btnGroup, stackedLayout](QAbstractButton* button) { + int id = btnGroup->id(button); + GradientEditMode modeToSet = btnIdToGradientMode[id]; + // if mode is not changing, we are done. + if (modeToSet == this->m_gradientData->m_activeMode) { + return; + } + this->m_gradientData->m_activeMode = modeToSet; + + stackedLayout->setCurrentIndex(btnIdToStackedPage[id]); + + // if this is not custom mode, then disable the gradient editor + m_editor->setEditable(modeToSet == GradientEditMode::CUSTOM); + + this->forceDataUpdate(); + }); + + QIntSlider* minu16Slider = new QIntSlider(); + minu16Slider->setStatusTip(tr("Minimum u16 value")); + minu16Slider->setToolTip(tr("Set minimum u16 value")); + minu16Slider->setRange(0, 65535); + minu16Slider->setSingleStep(1); + minu16Slider->setValue(m_gradientData->m_minu16); + section0Layout->addRow("Min u16", minu16Slider); + QIntSlider* maxu16Slider = new QIntSlider(); + maxu16Slider->setStatusTip(tr("Maximum u16 value")); + maxu16Slider->setToolTip(tr("Set maximum u16 value")); + maxu16Slider->setRange(0, 65535); + maxu16Slider->setSingleStep(1); + maxu16Slider->setValue(m_gradientData->m_maxu16); + section0Layout->addRow("Max u16", maxu16Slider); + connect(minu16Slider, &QIntSlider::valueChanged, [this, maxu16Slider](int i) { + this->m_gradientData->m_minu16 = i; + this->onSetMinMax(i, this->m_gradientData->m_maxu16); + }); + connect(maxu16Slider, &QIntSlider::valueChanged, [this, minu16Slider](int i) { + this->m_gradientData->m_maxu16 = i; + this->onSetMinMax(this->m_gradientData->m_minu16, i); + }); + + QNumericSlider* windowSlider = new QNumericSlider(); + windowSlider->setStatusTip(tr("Window")); + windowSlider->setToolTip(tr("Set size of range of intensities")); + windowSlider->setRange(0.0, 1.0); + windowSlider->setSingleStep(0.01); + windowSlider->setDecimals(3); + windowSlider->setValue(m_gradientData->m_window); + section1Layout->addRow("Window", windowSlider); + QNumericSlider* levelSlider = new QNumericSlider(); + levelSlider->setStatusTip(tr("Level")); + levelSlider->setToolTip(tr("Set level of mid intensity")); + levelSlider->setRange(0.0, 1.0); + levelSlider->setSingleStep(0.01); + levelSlider->setDecimals(3); + levelSlider->setValue(m_gradientData->m_level); + section1Layout->addRow("Level", levelSlider); + connect(windowSlider, &QNumericSlider::valueChanged, [this, levelSlider](double d) { + this->m_gradientData->m_window = d; + this->onSetWindowLevel(d, levelSlider->value()); + }); + connect(levelSlider, &QNumericSlider::valueChanged, [this, windowSlider](double d) { + this->m_gradientData->m_level = d; + this->onSetWindowLevel(windowSlider->value(), d); + }); + + QNumericSlider* isovalueSlider = new QNumericSlider(); + isovalueSlider->setStatusTip(tr("Isovalue")); + isovalueSlider->setToolTip(tr("Set Isovalue")); + isovalueSlider->setRange(0.0, 1.0); + isovalueSlider->setSingleStep(0.01); + isovalueSlider->setDecimals(3); + isovalueSlider->setValue(m_gradientData->m_isovalue); + section2Layout->addRow("Isovalue", isovalueSlider); + QNumericSlider* isorangeSlider = new QNumericSlider(); + isorangeSlider->setStatusTip(tr("Isovalue range")); + isorangeSlider->setToolTip(tr("Set range above and below isovalue")); + isorangeSlider->setRange(0.0, 1.0); + isorangeSlider->setSingleStep(0.01); + isorangeSlider->setDecimals(3); + isorangeSlider->setValue(m_gradientData->m_isorange); + section2Layout->addRow("Iso-range", isorangeSlider); + connect(isovalueSlider, &QNumericSlider::valueChanged, [this, isorangeSlider](double d) { + this->m_gradientData->m_isovalue = d; + this->onSetIsovalue(d, isorangeSlider->value()); + }); + connect(isorangeSlider, &QNumericSlider::valueChanged, [this, isovalueSlider](double d) { + this->m_gradientData->m_isorange = d; + this->onSetIsovalue(isovalueSlider->value(), d); + }); + + QNumericSlider* pctLowSlider = new QNumericSlider(); + pctLowSlider->setStatusTip(tr("Low percentile")); + pctLowSlider->setToolTip(tr("Set bottom percentile")); + pctLowSlider->setRange(0.0, 1.0); + pctLowSlider->setSingleStep(0.01); + pctLowSlider->setDecimals(3); + pctLowSlider->setValue(m_gradientData->m_pctLow); + section3Layout->addRow("Pct Min", pctLowSlider); + QNumericSlider* pctHighSlider = new QNumericSlider(); + pctHighSlider->setStatusTip(tr("High percentile")); + pctHighSlider->setToolTip(tr("Set top percentile")); + pctHighSlider->setRange(0.0, 1.0); + pctHighSlider->setSingleStep(0.01); + pctHighSlider->setDecimals(3); + pctHighSlider->setValue(m_gradientData->m_pctHigh); + section3Layout->addRow("Pct Max", pctHighSlider); + connect(pctLowSlider, &QNumericSlider::valueChanged, [this, pctHighSlider](double d) { + this->m_gradientData->m_pctLow = d; + this->onSetHistogramPercentiles(d, pctHighSlider->value()); + }); + connect(pctHighSlider, &QNumericSlider::valueChanged, [this, pctLowSlider](double d) { + this->m_gradientData->m_pctHigh = d; + this->onSetHistogramPercentiles(pctLowSlider->value(), d); + }); + + mainGroupLayout->addLayout(sectionLayout); + mainGroupLayout->addStretch(1); + + connect(m_editor, &GradientEditor::gradientStopsChanged, this, &GradientWidget::onGradientStopsChanged); + + forceDataUpdate(); +} + +void +GradientWidget::forceDataUpdate() +{ + GradientEditMode mode = this->m_gradientData->m_activeMode; + + switch (mode) { + case GradientEditMode::WINDOW_LEVEL: + this->onSetWindowLevel(this->m_gradientData->m_window, this->m_gradientData->m_level); + break; + case GradientEditMode::ISOVALUE: + this->onSetIsovalue(this->m_gradientData->m_isovalue, this->m_gradientData->m_isorange); + break; + case GradientEditMode::PERCENTILE: + this->onSetHistogramPercentiles(this->m_gradientData->m_pctLow, this->m_gradientData->m_pctHigh); + break; + case GradientEditMode::MINMAX: + this->onSetMinMax(this->m_gradientData->m_minu16, this->m_gradientData->m_maxu16); + break; + case GradientEditMode::CUSTOM: { + m_editor->setControlPoints(this->m_gradientData->m_customControlPoints); + QGradientStops stops = vectorToGradientStops(this->m_gradientData->m_customControlPoints); + emit gradientStopsChanged(stops); + } break; + default: + LOG_ERROR << "Bad gradient editor mode"; + break; + } +} + +void +GradientWidget::onGradientStopsChanged(const QGradientStops& stops) +{ + // update the data stored in m_gradientData + m_gradientData->m_customControlPoints.clear(); + for (int i = 0; i < stops.size(); ++i) { + m_gradientData->m_customControlPoints.push_back(LutControlPoint(stops.at(i).first, stops.at(i).second.alphaF())); + } + + emit gradientStopsChanged(stops); +} + +void +GradientWidget::onSetHistogramPercentiles(float pctLow, float pctHigh) +{ + float window, level; + m_histogram.computeWindowLevelFromPercentiles(pctLow, pctHigh, window, level); + this->onSetWindowLevel(window, level); +} + +void +GradientWidget::onSetWindowLevel(float window, float level) +{ + std::vector points; + static const float epsilon = 0.000001f; + window = std::max(window, epsilon); + float lowEnd = level - window * 0.5f; + float highEnd = level + window * 0.5f; + if (lowEnd <= 0.0f) { + float val = -lowEnd / (highEnd - lowEnd); + points.push_back({ 0.0f, val }); + } else { + points.push_back({ 0.0f, 0.0f }); + points.push_back({ lowEnd, 0.0f }); + } + if (highEnd >= 1.0f) { + float val = (1.0f - lowEnd) / (highEnd - lowEnd); + points.push_back({ 1.0f, val }); + } else { + points.push_back({ highEnd, 1.0f }); + points.push_back({ 1.0f, 1.0f }); + } + m_editor->setControlPoints(points); + emit gradientStopsChanged(vectorToGradientStops(points)); +} + +void +GradientWidget::onSetMinMax(uint16_t minu16, uint16_t maxu16) +{ + float relativeMin = normalizeInt(minu16); + float relativeMax = normalizeInt(maxu16); + relativeMin = std::max(relativeMin, 0.0f); + relativeMax = std::min(relativeMax, 1.0f); + if (relativeMin >= relativeMax) { + LOG_ERROR << "Min value is greater than or equal to max value: " << minu16 << " >= " << maxu16 + << ", datarange=" << m_histogram.dataRange(); + return; + } + float window = relativeMax - relativeMin; + float level = (relativeMax + relativeMin) / 2.0f; + this->onSetWindowLevel(window, level); +} + +void +GradientWidget::onSetIsovalue(float isovalue, float width) +{ + std::vector points; + float lowEnd = isovalue - width * 0.5f; + float highEnd = isovalue + width * 0.5f; + static const float epsilon = 0.00001f; + points.push_back({ 0.0f, 0.0f }); + points.push_back({ lowEnd - epsilon, 0.0f }); + points.push_back({ lowEnd + epsilon, 1.0f }); + points.push_back({ highEnd - epsilon, 1.0f }); + points.push_back({ highEnd + epsilon, 0.0f }); + points.push_back({ 1.0f, 0.0f }); + m_editor->setControlPoints(points); + emit gradientStopsChanged(vectorToGradientStops(points)); +} From 818fc7eef14e7a432571b6c216e1c232e080871a Mon Sep 17 00:00:00 2001 From: dmt Date: Sat, 2 Aug 2025 13:48:01 -0700 Subject: [PATCH 52/60] update camera via properties --- agave_app/GLView3D.cpp | 38 ++++++++++++++++++++++++++-------- renderlib/CameraDataObject.hpp | 6 ++++++ renderlib/CameraObject.hpp | 2 +- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/agave_app/GLView3D.cpp b/agave_app/GLView3D.cpp index f99f80f1..62274adc 100644 --- a/agave_app/GLView3D.cpp +++ b/agave_app/GLView3D.cpp @@ -13,6 +13,8 @@ #include "renderlib/graphics/RenderGLPT.h" #include "renderlib/graphics/gl/Image3D.h" #include "renderlib/graphics/gl/Util.h" +#include "renderlib/core/prty/prtyVector3d.hpp" +#include "renderlib/core/prty/prtyFloat.hpp" #include @@ -478,20 +480,38 @@ GLView3D::fromViewerState(const Serialize::ViewerState& s) /////////////////// // TODO do all of this through the camera object's properties!!!!!!!!! /////////////////// + m_cameraObject->getCameraDataObject().Position.SetValue(glm::vec3(s.camera.eye[0], s.camera.eye[1], s.camera.eye[2])); + // camera->m_From = glm::vec3(s.camera.eye[0], s.camera.eye[1], s.camera.eye[2]); - camera->m_From = glm::vec3(s.camera.eye[0], s.camera.eye[1], s.camera.eye[2]); - camera->m_Target = glm::vec3(s.camera.target[0], s.camera.target[1], s.camera.target[2]); + m_cameraObject->getCameraDataObject().Target.SetValue( + glm::vec3(s.camera.target[0], s.camera.target[1], s.camera.target[2])); + // camera->m_Target = glm::vec3(s.camera.target[0], s.camera.target[1], s.camera.target[2]); + + // m_cameraObject->getCameraDataObject().Up.SetValue(glm::vec3(s.camera.up[0], s.camera.up[1], s.camera.up[2])); camera->m_Up = glm::vec3(s.camera.up[0], s.camera.up[1], s.camera.up[2]); - camera->m_FovV = s.camera.fovY; - camera->SetProjectionMode(s.camera.projection == Serialize::Projection_PID::PERSPECTIVE ? PERSPECTIVE : ORTHOGRAPHIC); - camera->m_OrthoScale = s.camera.orthoScale; - camera->m_Film.m_Exposure = s.camera.exposure; - camera->m_Aperture.m_Size = s.camera.aperture; - camera->m_Focus.m_FocalDistance = s.camera.focalDistance; + m_cameraObject->getCameraDataObject().FieldOfView.SetValue(s.camera.fovY); + // camera->m_FovV = s.camera.fovY; + + m_cameraObject->getCameraDataObject().ProjectionMode.SetValue( + (s.camera.projection == Serialize::Projection_PID::PERSPECTIVE) ? PERSPECTIVE : ORTHOGRAPHIC); + // camera->SetProjectionMode(s.camera.projection == Serialize::Projection_PID::PERSPECTIVE ? PERSPECTIVE : + // ORTHOGRAPHIC); + + m_cameraObject->getCameraDataObject().OrthoScale.SetValue(s.camera.orthoScale); + // camera->m_OrthoScale = s.camera.orthoScale; + + m_cameraObject->getCameraDataObject().Exposure.SetValue(s.camera.exposure); + // camera->m_Film.m_Exposure = s.camera.exposure; + + m_cameraObject->getCameraDataObject().ApertureSize.SetValue(s.camera.aperture); + // camera->m_Aperture.m_Size = s.camera.aperture; + + m_cameraObject->getCameraDataObject().FocalDistance.SetValue(s.camera.focalDistance); + // camera->m_Focus.m_FocalDistance = s.camera.focalDistance; // ASSUMES THIS IS ATTACHED TO m_viewerWindow->m_CCamera !!! - // TODO FIXME if we set everything through props, then this is not needed. + // TODO FIXME if we set EVERYTHING through props, then this is not needed. m_cameraObject->updatePropsFromObject(); } diff --git a/renderlib/CameraDataObject.hpp b/renderlib/CameraDataObject.hpp index 7437d58b..1e4eb095 100644 --- a/renderlib/CameraDataObject.hpp +++ b/renderlib/CameraDataObject.hpp @@ -14,6 +14,9 @@ class CameraDataObject ExposureIterations.SetEnumTag(1, "2"); ExposureIterations.SetEnumTag(2, "4"); ExposureIterations.SetEnumTag(3, "8"); + + ProjectionMode.SetEnumTag(0, "Perspective"); + ProjectionMode.SetEnumTag(1, "Orthographic"); } prtyFloat Exposure{ "Exposure", 0.75f }; @@ -28,4 +31,7 @@ class CameraDataObject prtyFloat NearPlane{ "NearPlane", 0.1f }; prtyFloat FarPlane{ "FarPlane", 1000.0f }; prtyFloat Roll{ "Roll", 0.0f }; // tilt angle in degrees + + prtyFloat OrthoScale{ "OrthoScale", 1.0f }; // orthographic scale for orthographic projection + prtyEnum ProjectionMode{ "ProjectionMode", 0 }; // 0 = perspective, 1 = orthographic }; diff --git a/renderlib/CameraObject.hpp b/renderlib/CameraObject.hpp index 6bcbde8a..69a29e54 100644 --- a/renderlib/CameraObject.hpp +++ b/renderlib/CameraObject.hpp @@ -24,7 +24,7 @@ class CameraObject : public prtyObject void updateObjectFromProps(); // Getter for camera data object - // CameraDataObject& getCameraDataObject() { return m_cameraDataObject; } + CameraDataObject& getCameraDataObject() { return m_cameraDataObject; } const CameraDataObject& getCameraDataObject() const { return m_cameraDataObject; } // Getters for UI info objects From 5e6dc57a4fd15e094981b71309c2df558ba15ddc Mon Sep 17 00:00:00 2001 From: dmt Date: Mon, 4 Aug 2025 17:52:51 -0700 Subject: [PATCH 53/60] add target, pos and roll properties to camera --- renderlib/CameraObject.cpp | 30 ++++++++++++++++++++++++++++++ renderlib/CameraObject.hpp | 1 + 2 files changed, 31 insertions(+) diff --git a/renderlib/CameraObject.cpp b/renderlib/CameraObject.cpp index 4d2bc5d9..1d3614cc 100644 --- a/renderlib/CameraObject.cpp +++ b/renderlib/CameraObject.cpp @@ -1,6 +1,7 @@ #include "CameraObject.hpp" #include "Logging.h" +#include "glm.h" // FloatSliderSpinnerUiInfo CameraUiDescription::m_exposure("Exposure", // "Set Exposure", @@ -110,6 +111,13 @@ CameraObject::CameraObject() new prtyCallbackWrapper(this, &CameraObject::FieldOfViewChanged)); m_cameraDataObject.FocalDistance.AddCallback( new prtyCallbackWrapper(this, &CameraObject::FocalDistanceChanged)); + + m_cameraDataObject.Position.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::TransformationChanged)); + m_cameraDataObject.Target.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::TransformationChanged)); + m_cameraDataObject.Roll.AddCallback( + new prtyCallbackWrapper(this, &CameraObject::TransformationChanged)); } void @@ -229,3 +237,25 @@ CameraObject::FocalDistanceChanged(prtyProperty* i_Property, bool i_bDirty) m_camera->m_Focus.m_FocalDistance = m_cameraDataObject.FocalDistance.GetValue(); m_camera->m_Dirty = true; } + +//-------------------------------------------------------------------- +// common code when a property related to position of light is changed +//-------------------------------------------------------------------- +void +CameraObject::TransformationChanged(prtyProperty* i_Property, bool i_bDirty) +{ + // Rotate up vector through tilt angle + glm::vec3 pos, target; + // assumes world space. + pos = m_cameraDataObject.Position.GetValue(); + target = m_cameraDataObject.Target.GetValue(); + glm::vec3 up = glm::vec3(0, 1, 0); // default up vector + // Rotate the up vector around the vector from position to target + // using the roll angle (tilt angle) + up = glm::rotate(up, DEG_TO_RAD * m_cameraDataObject.Roll.GetValue(), target - pos); + + m_camera->m_From = pos; + m_camera->m_Target = target; + m_camera->m_Up = up; + m_camera->m_Dirty = true; +} diff --git a/renderlib/CameraObject.hpp b/renderlib/CameraObject.hpp index 69a29e54..bc35a688 100644 --- a/renderlib/CameraObject.hpp +++ b/renderlib/CameraObject.hpp @@ -62,4 +62,5 @@ class CameraObject : public prtyObject void ApertureSizeChanged(prtyProperty* i_Property, bool i_bDirty); void FieldOfViewChanged(prtyProperty* i_Property, bool i_bDirty); void FocalDistanceChanged(prtyProperty* i_Property, bool i_bDirty); + void TransformationChanged(prtyProperty* i_Property, bool i_bDirty); }; From 9fd837c6dcf3086f006ad423724ed574a5d443fc Mon Sep 17 00:00:00 2001 From: dmt Date: Wed, 13 Aug 2025 20:12:54 -0700 Subject: [PATCH 54/60] clean up comments and include guards in favor of pragma once --- renderlib/core/env/envSTLHelpers.hpp | 15 +------------ renderlib/core/prty/prtyBoolean.cpp | 8 ------- renderlib/core/prty/prtyBoolean.hpp | 14 ------------ renderlib/core/prty/prtyColor.cpp | 8 ------- renderlib/core/prty/prtyColor.hpp | 14 ------------ .../core/prty/prtyColorRGBAEditUIInfo.cpp | 8 ------- .../core/prty/prtyColorRGBAEditUIInfo.hpp | 15 +------------ renderlib/core/prty/prtyEnum.cpp | 8 ------- renderlib/core/prty/prtyEnum.hpp | 14 ------------ renderlib/core/prty/prtyFloat.cpp | 8 ------- renderlib/core/prty/prtyFloat.hpp | 14 ------------ renderlib/core/prty/prtyInt32.cpp | 8 ------- renderlib/core/prty/prtyInt32.hpp | 15 +------------ renderlib/core/prty/prtyInt8.cpp | 8 ------- renderlib/core/prty/prtyInt8.hpp | 17 -------------- renderlib/core/prty/prtyInterest.cpp | 6 ----- renderlib/core/prty/prtyInterest.hpp | 12 +--------- renderlib/core/prty/prtyInterestUtil.cpp | 6 ----- renderlib/core/prty/prtyInterestUtil.hpp | 15 ++----------- renderlib/core/prty/prtyObject.cpp | 8 ------- renderlib/core/prty/prtyObject.hpp | 18 --------------- renderlib/core/prty/prtyPackage.cpp | 9 -------- renderlib/core/prty/prtyPackage.hpp | 15 +------------ renderlib/core/prty/prtyProperty.cpp | 8 ------- renderlib/core/prty/prtyProperty.hpp | 3 +-- renderlib/core/prty/prtyPropertyCallback.hpp | 16 +------------- renderlib/core/prty/prtyPropertyReference.cpp | 8 ------- renderlib/core/prty/prtyPropertyReference.hpp | 20 +++++------------ renderlib/core/prty/prtyPropertyTemplate.hpp | 8 ------- renderlib/core/prty/prtyPropertyUIInfo.cpp | 8 ------- renderlib/core/prty/prtyPropertyUIInfo.hpp | 8 ------- .../core/prty/prtyPropertyUIInfoContainer.cpp | 8 ------- .../core/prty/prtyPropertyUIInfoContainer.hpp | 14 ------------ renderlib/core/prty/prtyRotation.cpp | 8 ------- renderlib/core/prty/prtyRotation.hpp | 17 ++------------ renderlib/core/prty/prtyRotationUndo.cpp | 8 ------- renderlib/core/prty/prtyRotationUndo.hpp | 16 -------------- renderlib/core/prty/prtyText.cpp | 8 ------- renderlib/core/prty/prtyText.hpp | 17 ++------------ renderlib/core/prty/prtyUndoTemplate.cpp | 8 ------- renderlib/core/prty/prtyUndoTemplate.hpp | 16 -------------- renderlib/core/prty/prtyUnits.cpp | 8 ------- renderlib/core/prty/prtyUnits.hpp | 13 +---------- renderlib/core/prty/prtyVector3d.cpp | 8 ------- renderlib/core/prty/prtyVector3d.hpp | 14 ------------ renderlib/core/undo/undoMultipleOperation.cpp | 8 ------- renderlib/core/undo/undoMultipleOperation.hpp | 18 +++------------ .../core/undo/undoMultipleOperationBlock.hpp | 18 +++++---------- renderlib/core/undo/undoUndoInterest.cpp | 8 ------- renderlib/core/undo/undoUndoInterest.hpp | 11 ++-------- renderlib/core/undo/undoUndoMgr.cpp | 8 ------- renderlib/core/undo/undoUndoMgr.hpp | 22 +++++++------------ renderlib/core/undo/undoUndoOperation.cpp | 8 ------- renderlib/core/undo/undoUndoOperation.hpp | 14 ------------ 54 files changed, 37 insertions(+), 583 deletions(-) diff --git a/renderlib/core/env/envSTLHelpers.hpp b/renderlib/core/env/envSTLHelpers.hpp index 7c7eccf4..53ba11c3 100644 --- a/renderlib/core/env/envSTLHelpers.hpp +++ b/renderlib/core/env/envSTLHelpers.hpp @@ -1,17 +1,4 @@ -/****************************************************************************\ -** envSTLHelpers.hpp -** -** envSTLHelpers is meant to contain definitions useful when using the -** STL in our library. -** -** -** -\****************************************************************************/ - -#ifdef ENV_STLHELPERS_HPP -#error envSTLHelpers.hpp multiple included -#endif -#define ENV_STLHELPERS_HPP +#pragma once #include // for_each #include diff --git a/renderlib/core/prty/prtyBoolean.cpp b/renderlib/core/prty/prtyBoolean.cpp index 5efd33b1..aaacb84a 100644 --- a/renderlib/core/prty/prtyBoolean.cpp +++ b/renderlib/core/prty/prtyBoolean.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyBoolean.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyBoolean.hpp" // #include "core/ch/chReader.hpp" diff --git a/renderlib/core/prty/prtyBoolean.hpp b/renderlib/core/prty/prtyBoolean.hpp index af38d4bd..8ba2ecdc 100644 --- a/renderlib/core/prty/prtyBoolean.hpp +++ b/renderlib/core/prty/prtyBoolean.hpp @@ -1,20 +1,6 @@ -/****************************************************************************\ -** prtyBoolean.hpp -** -** Boolean property -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_BOOLEAN_HPP -#error prtyBoolean.hpp multiply included -#endif -#define PRTY_BOOLEAN_HPP -#ifndef PRTY_PROPERTYTEMPLATE_HPP #include "core/prty/prtyPropertyTemplate.hpp" -#endif //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyColor.cpp b/renderlib/core/prty/prtyColor.cpp index 31e1b52a..6e302065 100644 --- a/renderlib/core/prty/prtyColor.cpp +++ b/renderlib/core/prty/prtyColor.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyColor.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyColor.hpp" // #include "core/ch/chChunkParserUtil.hpp" diff --git a/renderlib/core/prty/prtyColor.hpp b/renderlib/core/prty/prtyColor.hpp index d54e5495..822e4781 100644 --- a/renderlib/core/prty/prtyColor.hpp +++ b/renderlib/core/prty/prtyColor.hpp @@ -1,20 +1,6 @@ -/****************************************************************************\ -** prtyColor.hpp -** -** Color property -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_COLOR_HPP -#error prtyColor.hpp multiply included -#endif -#define PRTY_COLOR_HPP -#ifndef PRTY_PROPERTYTEMPLATE_HPP #include "core/prty/prtyPropertyTemplate.hpp" -#endif #include "glm.h" diff --git a/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp b/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp index 6079acd9..c63da5db 100644 --- a/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp +++ b/renderlib/core/prty/prtyColorRGBAEditUIInfo.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyColorRGBAEditUIInfo.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyColorRGBAEditUIInfo.hpp" #include "core/prty/prtyProperty.hpp" diff --git a/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp b/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp index c9a3f089..435afd2d 100644 --- a/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp +++ b/renderlib/core/prty/prtyColorRGBAEditUIInfo.hpp @@ -1,19 +1,6 @@ -/****************************************************************************\ -** prtyColorRGBAEditUIInfo.hpp -** -** ColorRGBAEdit UI info -** -** -** -\****************************************************************************/ -#ifdef PRTY_COLORRGBAEDITUIINFO_HPP -#error prtyColorRGBAEditUIInfo.hpp multiply included -#endif -#define PRTY_COLORRGBAEDITUIINFO_HPP +#pragma once -#ifndef PRTY_PROPERTYUIINFO_HPP #include "core/prty/prtyPropertyUIInfo.hpp" -#endif #include diff --git a/renderlib/core/prty/prtyEnum.cpp b/renderlib/core/prty/prtyEnum.cpp index d09ce87f..c45c4049 100644 --- a/renderlib/core/prty/prtyEnum.cpp +++ b/renderlib/core/prty/prtyEnum.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyEnum.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyEnum.hpp" //---------------------------------------------------------------------------- diff --git a/renderlib/core/prty/prtyEnum.hpp b/renderlib/core/prty/prtyEnum.hpp index b81421e4..48a821e5 100644 --- a/renderlib/core/prty/prtyEnum.hpp +++ b/renderlib/core/prty/prtyEnum.hpp @@ -1,20 +1,6 @@ -/****************************************************************************\ -** prtyEnum.hpp -** -** Enum property -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_ENUM_HPP -#error prtyEnum.hpp multiply included -#endif -#define PRTY_ENUM_HPP -#ifndef PRTY_INT8_HPP #include "core/prty/prtyInt8.hpp" -#endif #include diff --git a/renderlib/core/prty/prtyFloat.cpp b/renderlib/core/prty/prtyFloat.cpp index d1ad6f49..53d52b5b 100644 --- a/renderlib/core/prty/prtyFloat.cpp +++ b/renderlib/core/prty/prtyFloat.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyFloat.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyFloat.hpp" #include "core/prty/prtyUnits.hpp" diff --git a/renderlib/core/prty/prtyFloat.hpp b/renderlib/core/prty/prtyFloat.hpp index ca494005..350e3494 100644 --- a/renderlib/core/prty/prtyFloat.hpp +++ b/renderlib/core/prty/prtyFloat.hpp @@ -1,20 +1,6 @@ -/****************************************************************************\ -** prtyFloat.hpp -** -** Float property -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_FLOAT_HPP -#error prtyFloat.hpp multiply included -#endif -#define PRTY_FLOAT_HPP -#ifndef PRTY_PROPERTYTEMPLATE_HPP #include "core/prty/prtyPropertyTemplate.hpp" -#endif //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyInt32.cpp b/renderlib/core/prty/prtyInt32.cpp index 53d64351..c14b0c06 100644 --- a/renderlib/core/prty/prtyInt32.cpp +++ b/renderlib/core/prty/prtyInt32.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyInt32.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyInt32.hpp" // #include "core/ch/chChunkParserUtil.hpp" diff --git a/renderlib/core/prty/prtyInt32.hpp b/renderlib/core/prty/prtyInt32.hpp index 7bb7756d..a7abfcde 100644 --- a/renderlib/core/prty/prtyInt32.hpp +++ b/renderlib/core/prty/prtyInt32.hpp @@ -1,19 +1,6 @@ -/****************************************************************************\ -** prtyInt32.hpp -** -** Int32 property -** -** -** -\****************************************************************************/ -#ifdef PRTY_INT32_HPP -#error prtyInt32.hpp multiply included -#endif -#define PRTY_INT32_HPP +#pragma once -#ifndef PRTY_PROPERTYTEMPLATE_HPP #include "core/prty/prtyPropertyTemplate.hpp" -#endif //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyInt8.cpp b/renderlib/core/prty/prtyInt8.cpp index 618bbdf8..bbe85620 100644 --- a/renderlib/core/prty/prtyInt8.cpp +++ b/renderlib/core/prty/prtyInt8.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyInt8.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyInt8.hpp" // #include "core/ch/chReader.hpp" diff --git a/renderlib/core/prty/prtyInt8.hpp b/renderlib/core/prty/prtyInt8.hpp index 5d73572b..182ce164 100644 --- a/renderlib/core/prty/prtyInt8.hpp +++ b/renderlib/core/prty/prtyInt8.hpp @@ -1,23 +1,6 @@ #pragma once -/****************************************************************************\ -** prtyInt8.hpp -** -** Int8 property -** -** NOTE: a possible code optimization would be to elminate the int8 and -** just use int32 and set the min and max values to be correct. -** -** -** -\****************************************************************************/ -#ifdef PRTY_INT8_HPP -#error prtyInt8.hpp multiply included -#endif -#define PRTY_INT8_HPP -#ifndef PRTY_PROPERTYTEMPLATE_HPP #include "core/prty/prtyPropertyTemplate.hpp" -#endif //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyInterest.cpp b/renderlib/core/prty/prtyInterest.cpp index effe9373..093b5514 100644 --- a/renderlib/core/prty/prtyInterest.cpp +++ b/renderlib/core/prty/prtyInterest.cpp @@ -1,9 +1,3 @@ -/****************************************************************************\ -** prtyInterest.hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyInterest.hpp" //---------------------------------------------------------------------------- diff --git a/renderlib/core/prty/prtyInterest.hpp b/renderlib/core/prty/prtyInterest.hpp index f42d8c91..c212e009 100644 --- a/renderlib/core/prty/prtyInterest.hpp +++ b/renderlib/core/prty/prtyInterest.hpp @@ -1,14 +1,4 @@ -/****************************************************************************\ -** prtyInterest.cpp -** -** -** -\****************************************************************************/ - -#ifdef PRTY_INTEREST_HPP -#error prtyInterest.hpp multiply included -#endif -#define PRTY_INTEREST_HPP +#pragma once #include diff --git a/renderlib/core/prty/prtyInterestUtil.cpp b/renderlib/core/prty/prtyInterestUtil.cpp index 2e3b5e0b..7b2b0f86 100644 --- a/renderlib/core/prty/prtyInterestUtil.cpp +++ b/renderlib/core/prty/prtyInterestUtil.cpp @@ -1,9 +1,3 @@ -/****************************************************************************\ -** prtyInterestUtil.cpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyInterestUtil.hpp" #include "core/env/envSTLHelpers.hpp" diff --git a/renderlib/core/prty/prtyInterestUtil.hpp b/renderlib/core/prty/prtyInterestUtil.hpp index 547e8822..9597547f 100644 --- a/renderlib/core/prty/prtyInterestUtil.hpp +++ b/renderlib/core/prty/prtyInterestUtil.hpp @@ -1,17 +1,6 @@ -/****************************************************************************\ -** prtyInterestUtil.hpp -** -** -** -\****************************************************************************/ -#ifdef PRTY_INTERESTUTIL_HPP -#error prtyInterestUtil.hpp multiply included -#endif -#define PRTY_INTERESTUTIL_HPP - -#ifndef PRTY_INTEREST_HPP +#pragma once + #include "core/prty/prtyInterest.hpp" -#endif #include #include diff --git a/renderlib/core/prty/prtyObject.cpp b/renderlib/core/prty/prtyObject.cpp index fd7d05ed..3c28b4d5 100644 --- a/renderlib/core/prty/prtyObject.cpp +++ b/renderlib/core/prty/prtyObject.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyObject.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyObject.hpp" #include "core/prty/prtyProperty.hpp" diff --git a/renderlib/core/prty/prtyObject.hpp b/renderlib/core/prty/prtyObject.hpp index e27732f2..0a207daf 100644 --- a/renderlib/core/prty/prtyObject.hpp +++ b/renderlib/core/prty/prtyObject.hpp @@ -1,26 +1,8 @@ -/****************************************************************************\ -** prtyObject.hpp -** -** Object base class -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_OBJECT_HPP -#error prtyObject.hpp multiply included -#endif -#define PRTY_OBJECT_HPP -#ifndef PRTY_PROPERTYUIINFO_HPP #include "core/prty/prtyPropertyUIInfo.hpp" -#endif -#ifndef PRTY_PROPERTYUIINFOCONTAINER_HPP #include "core/prty/prtyPropertyUIInfoContainer.hpp" -#endif -#ifndef PRTY_PROPERTYREFERENCE_HPP #include "core/prty/prtyPropertyReference.hpp" -#endif #include diff --git a/renderlib/core/prty/prtyPackage.cpp b/renderlib/core/prty/prtyPackage.cpp index cbbcba78..fdaac4ac 100644 --- a/renderlib/core/prty/prtyPackage.cpp +++ b/renderlib/core/prty/prtyPackage.cpp @@ -1,12 +1,3 @@ -/***************************************************************************** -** prtyPackage.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ - #include "core/prty/prtyPackage.hpp" #include "core/prty/prtyInterestUtil.hpp" diff --git a/renderlib/core/prty/prtyPackage.hpp b/renderlib/core/prty/prtyPackage.hpp index 1172dc42..2aa717bb 100644 --- a/renderlib/core/prty/prtyPackage.hpp +++ b/renderlib/core/prty/prtyPackage.hpp @@ -1,17 +1,4 @@ -/***************************************************************************** -** prtyPackage.hpp -** -** package for property classes -** -** -** -** -\****************************************************************************/ - -#ifdef PRTY_PACKAGE_HPP -#error prtyPackage.hpp multiply included -#endif -#define PRTY_PACKAGE_HPP +#pragma once //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyProperty.cpp b/renderlib/core/prty/prtyProperty.cpp index 1aa831ff..e1b12dd4 100644 --- a/renderlib/core/prty/prtyProperty.cpp +++ b/renderlib/core/prty/prtyProperty.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyProperty.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyProperty.hpp" // #include "core/dbg/dbgMsg.hpp" diff --git a/renderlib/core/prty/prtyProperty.hpp b/renderlib/core/prty/prtyProperty.hpp index 98a740bb..4c710e1a 100644 --- a/renderlib/core/prty/prtyProperty.hpp +++ b/renderlib/core/prty/prtyProperty.hpp @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************\ ** prtyProperty.hpp ** @@ -46,12 +47,10 @@ ** prtyControlMgr::DeInitialize(); ** prtyCallbackMgr::DeInitialize(); ** -** Refer to test/prty application for an example. ** ** ** \****************************************************************************/ -#pragma once #include "core/prty/prtyPropertyCallback.hpp" #include "core/undo/undoUndoOperation.hpp" diff --git a/renderlib/core/prty/prtyPropertyCallback.hpp b/renderlib/core/prty/prtyPropertyCallback.hpp index d2c88f9d..7e55f73a 100644 --- a/renderlib/core/prty/prtyPropertyCallback.hpp +++ b/renderlib/core/prty/prtyPropertyCallback.hpp @@ -1,18 +1,4 @@ -/****************************************************************************\ -** prtyPropertyCallback.hpp -** -** Template and interface for handling property changed callbacks. -** -** You create and register a callback to a member function with this syntax: -** m_Property.AddCallback(new prtyCallbackWrapper(this, &xxxObject::FunctionName)); -** -** -** -\****************************************************************************/ -#ifdef PRTY_PROPERTYCALLBACK_HPP -#error prtyPropertyCallback.hpp multiply included -#endif -#define PRTY_PROPERTYCALLBACK_HPP +#pragma once #include diff --git a/renderlib/core/prty/prtyPropertyReference.cpp b/renderlib/core/prty/prtyPropertyReference.cpp index a2ecf039..38dcd2a7 100644 --- a/renderlib/core/prty/prtyPropertyReference.cpp +++ b/renderlib/core/prty/prtyPropertyReference.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyPropertyReference.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyPropertyReference.hpp" //============================================================================ diff --git a/renderlib/core/prty/prtyPropertyReference.hpp b/renderlib/core/prty/prtyPropertyReference.hpp index d63b94e3..fac1d497 100644 --- a/renderlib/core/prty/prtyPropertyReference.hpp +++ b/renderlib/core/prty/prtyPropertyReference.hpp @@ -1,19 +1,4 @@ -/*****************************************************************************\ -** prtyPropertyReference.hpp -** -** Provides a safe way to refer to a property for undo operations. -** Derivations of this class should provide a way to access a property -** by a reference that is consistent through deletion and restoration of -** the parent property object. -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_PROPERTYREFERENCE_HPP -#error prtyPropertyReference.hpp multiply included -#endif -#define PRTY_PROPERTYREFERENCE_HPP #include @@ -26,6 +11,11 @@ class prtyProperty; // A prtyReference is a logical reference to a property that may point to // different actual prtyProperty classes at different times. This may happen // during undo and redo when an object is deleted and restored. + +// Provides a safe way to refer to a property for undo operations. +// Derivations of this class should provide a way to access a property +// by a reference that is consistent through deletion and restoration of +// the parent property object. //============================================================================ class prtyPropertyReference { diff --git a/renderlib/core/prty/prtyPropertyTemplate.hpp b/renderlib/core/prty/prtyPropertyTemplate.hpp index 78d05a7c..55952be3 100644 --- a/renderlib/core/prty/prtyPropertyTemplate.hpp +++ b/renderlib/core/prty/prtyPropertyTemplate.hpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyPropertyTemplate.hpp -** -** Template for properties -** -** -** -\****************************************************************************/ #pragma once #include "core/prty/prtyProperty.hpp" diff --git a/renderlib/core/prty/prtyPropertyUIInfo.cpp b/renderlib/core/prty/prtyPropertyUIInfo.cpp index c8744484..7bc7dd1d 100644 --- a/renderlib/core/prty/prtyPropertyUIInfo.cpp +++ b/renderlib/core/prty/prtyPropertyUIInfo.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyPropertyUIInfo.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyPropertyUIInfo.hpp" #include "core/prty/prtyProperty.hpp" diff --git a/renderlib/core/prty/prtyPropertyUIInfo.hpp b/renderlib/core/prty/prtyPropertyUIInfo.hpp index ae3cab43..765ea554 100644 --- a/renderlib/core/prty/prtyPropertyUIInfo.hpp +++ b/renderlib/core/prty/prtyPropertyUIInfo.hpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyPropertyUIInfo.hpp -** -** Property UI info -** -** -** -\****************************************************************************/ #pragma once #include diff --git a/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp b/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp index d73c2879..86091b5d 100644 --- a/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp +++ b/renderlib/core/prty/prtyPropertyUIInfoContainer.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyPropertyUIInfoContainer.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyPropertyUIInfoContainer.hpp" #include "Logging.h" diff --git a/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp b/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp index 1c2e8ea0..977f2942 100644 --- a/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp +++ b/renderlib/core/prty/prtyPropertyUIInfoContainer.hpp @@ -1,20 +1,6 @@ -/****************************************************************************\ -** prtyPropertyUIInfoContainer.hpp -** -** Container for property UI info -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_PROPERTYUIINFOCONTAINER_HPP -#error prtyPropertyUIInfoContainer.hpp multiply included -#endif -#define PRTY_PROPERTYUIINFOCONTAINER_HPP -#ifndef PRTY_PROPERTYUIINFO_HPP #include "core/prty/prtyPropertyUIInfo.hpp" -#endif #include #include diff --git a/renderlib/core/prty/prtyRotation.cpp b/renderlib/core/prty/prtyRotation.cpp index 17f9df3e..f833516c 100644 --- a/renderlib/core/prty/prtyRotation.cpp +++ b/renderlib/core/prty/prtyRotation.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyRotation.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyRotation.hpp" #include "core/prty/prtyRotationUndo.hpp" diff --git a/renderlib/core/prty/prtyRotation.hpp b/renderlib/core/prty/prtyRotation.hpp index e172c5c1..7aad3327 100644 --- a/renderlib/core/prty/prtyRotation.hpp +++ b/renderlib/core/prty/prtyRotation.hpp @@ -1,19 +1,6 @@ -/****************************************************************************\ -** prtyRotation.hpp -** -** Rotation property -** -** -** -\****************************************************************************/ -#ifdef PRTY_ROTATION_HPP -#error prtyRotation.hpp multiply included -#endif -#define PRTY_ROTATION_HPP - -#ifndef PRTY_PROPERTY_HPP +#pragma once + #include "core/prty/prtyProperty.hpp" -#endif #include "glm.h" diff --git a/renderlib/core/prty/prtyRotationUndo.cpp b/renderlib/core/prty/prtyRotationUndo.cpp index e8d9978d..f6a4e628 100644 --- a/renderlib/core/prty/prtyRotationUndo.cpp +++ b/renderlib/core/prty/prtyRotationUndo.cpp @@ -1,11 +1,3 @@ -/***************************************************************************** -** prtyRotationUndo.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyRotationUndo.hpp" #include "core/prty/prtyRotation.hpp" diff --git a/renderlib/core/prty/prtyRotationUndo.hpp b/renderlib/core/prty/prtyRotationUndo.hpp index 6649717a..235a5f6c 100644 --- a/renderlib/core/prty/prtyRotationUndo.hpp +++ b/renderlib/core/prty/prtyRotationUndo.hpp @@ -1,23 +1,7 @@ -/***************************************************************************** -** prtyRotationUndo.hpp -** -** store a state of Rotation for undo/redo -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_ROTATIONUNDO_HPP -#error prtyRotationUndo.hpp multiply included -#endif -#define PRTY_ROTATIONUNDO_HPP -#ifndef UNDO_UNDOOPERATION_HPP #include "core/undo/undoUndoOperation.hpp" -#endif -#ifndef PRTY_PROPERTYREFERENCE_HPP #include "core/prty/prtyPropertyReference.hpp" -#endif #include "glm.h" diff --git a/renderlib/core/prty/prtyText.cpp b/renderlib/core/prty/prtyText.cpp index 33039fe9..74b87231 100644 --- a/renderlib/core/prty/prtyText.cpp +++ b/renderlib/core/prty/prtyText.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyText.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyText.hpp" // #include "core/ch/chChunkParserUtil.hpp" diff --git a/renderlib/core/prty/prtyText.hpp b/renderlib/core/prty/prtyText.hpp index aa76024a..1e2fa90e 100644 --- a/renderlib/core/prty/prtyText.hpp +++ b/renderlib/core/prty/prtyText.hpp @@ -1,19 +1,6 @@ -/****************************************************************************\ -** prtyText.hpp -** -** Text property -** -** -** -\****************************************************************************/ -#ifdef PRTY_TEXT_HPP -#error prtyText.hpp multiply included -#endif -#define PRTY_TEXT_HPP - -#ifndef PRTY_PROPERTYTEMPLATE_HPP +#pragma once + #include "core/prty/prtyPropertyTemplate.hpp" -#endif //============================================================================ //============================================================================ diff --git a/renderlib/core/prty/prtyUndoTemplate.cpp b/renderlib/core/prty/prtyUndoTemplate.cpp index a01eaeee..62b803cd 100644 --- a/renderlib/core/prty/prtyUndoTemplate.cpp +++ b/renderlib/core/prty/prtyUndoTemplate.cpp @@ -1,9 +1 @@ -/***************************************************************************** -** prtyUndoTemplate.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "prtyUndoTemplate.hpp" diff --git a/renderlib/core/prty/prtyUndoTemplate.hpp b/renderlib/core/prty/prtyUndoTemplate.hpp index 75e698d2..d88fbf0e 100644 --- a/renderlib/core/prty/prtyUndoTemplate.hpp +++ b/renderlib/core/prty/prtyUndoTemplate.hpp @@ -1,23 +1,7 @@ -/***************************************************************************** -** prtyUndoTemplate.hpp -** -** store a state of Text for undo/redo -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_UNDOTEMPLATE_HPP -#error prtyUndoTemplate.hpp multiply included -#endif -#define PRTY_UNDOTEMPLATE_HPP -#ifndef UNDO_UNDOOPERATION_HPP #include "core/undo/undoUndoOperation.hpp" -#endif -#ifndef PRTY_PROPERTYREFERENCE_HPP #include "core/prty/prtyPropertyReference.hpp" -#endif #include "core/prty/prtyProperty.hpp" diff --git a/renderlib/core/prty/prtyUnits.cpp b/renderlib/core/prty/prtyUnits.cpp index 95854207..e0383c2e 100644 --- a/renderlib/core/prty/prtyUnits.cpp +++ b/renderlib/core/prty/prtyUnits.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyUnits.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyUnits.hpp" #include "Logging.h" diff --git a/renderlib/core/prty/prtyUnits.hpp b/renderlib/core/prty/prtyUnits.hpp index 498bb26b..90b41f92 100644 --- a/renderlib/core/prty/prtyUnits.hpp +++ b/renderlib/core/prty/prtyUnits.hpp @@ -1,15 +1,4 @@ -/*****************************************************************************\ -** prtyUnits.hpp -** -** Tracks the units for display of properties realted to distance. -** -** -** -\****************************************************************************/ -#ifdef PRTY_UNITS_HPP -#error prtyUnits.hpp multiply included -#endif -#define PRTY_UNITS_HPP +#pragma once #include diff --git a/renderlib/core/prty/prtyVector3d.cpp b/renderlib/core/prty/prtyVector3d.cpp index 45ffb9d7..ca0bfa8c 100644 --- a/renderlib/core/prty/prtyVector3d.cpp +++ b/renderlib/core/prty/prtyVector3d.cpp @@ -1,11 +1,3 @@ -/****************************************************************************\ -** prtyVector3d.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/prty/prtyVector3d.hpp" #include "core/prty/prtyUnits.hpp" diff --git a/renderlib/core/prty/prtyVector3d.hpp b/renderlib/core/prty/prtyVector3d.hpp index e703d0b8..80a34873 100644 --- a/renderlib/core/prty/prtyVector3d.hpp +++ b/renderlib/core/prty/prtyVector3d.hpp @@ -1,20 +1,6 @@ -/****************************************************************************\ -** prtyVector3d.hpp -** -** Vector3d property -** -** -** -\****************************************************************************/ #pragma once -#ifdef PRTY_VECTOR3D_HPP -#error prtyVector3d.hpp multiply included -#endif -#define PRTY_VECTOR3D_HPP -#ifndef PRTY_PROPERTYTEMPLATE_HPP #include "core/prty/prtyPropertyTemplate.hpp" -#endif #include "glm.h" diff --git a/renderlib/core/undo/undoMultipleOperation.cpp b/renderlib/core/undo/undoMultipleOperation.cpp index e18671e7..5fbfe1c8 100644 --- a/renderlib/core/undo/undoMultipleOperation.cpp +++ b/renderlib/core/undo/undoMultipleOperation.cpp @@ -1,11 +1,3 @@ -/***************************************************************************** -** undoMultipleOperation.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/undo/undoMultipleOperation.hpp" #include "Logging.h" diff --git a/renderlib/core/undo/undoMultipleOperation.hpp b/renderlib/core/undo/undoMultipleOperation.hpp index 86aa150d..a4ec4d0f 100644 --- a/renderlib/core/undo/undoMultipleOperation.hpp +++ b/renderlib/core/undo/undoMultipleOperation.hpp @@ -1,24 +1,12 @@ -/***************************************************************************** -** undoMultipleOperation.hpp -** -** This class can be used to group a number of single undo operations -** into one undo operation that can be undone and redone in one step. -** -** -** -\****************************************************************************/ -#ifdef UNDO_MULTIPLEOPERATION_HPP -#error undoUndoOperation.hpp multiply included -#endif -#define UNDO_MULTIPLEOPERATION_HPP +#pragma once -#ifndef UNDO_UNDOOPERATION_HPP #include "core/undo/undoUndoOperation.hpp" -#endif #include //============================================================================ +//** This class can be used to group a number of single undo operations +//** into one undo operation that can be undone and redone in one step. //============================================================================ class undoMultipleOperation : public undoUndoOperation { diff --git a/renderlib/core/undo/undoMultipleOperationBlock.hpp b/renderlib/core/undo/undoMultipleOperationBlock.hpp index 28892ba0..b6bf68a0 100644 --- a/renderlib/core/undo/undoMultipleOperationBlock.hpp +++ b/renderlib/core/undo/undoMultipleOperationBlock.hpp @@ -1,23 +1,15 @@ +#pragma once + +#include "core/undo/undoUndoMgr.hpp" + +//============================================================================ /***************************************************************************** -** undoMultipleOperationBlock.hpp ** ** A helper class for begining and ending a multiple operation ** undo block. The class begin the block on constructor and ends ** it on destructor so that exceptions don't throw off the block stack. ** -** -** \****************************************************************************/ -#ifdef UNDO_UNDOMULTIPLEOPERATIONBLOCK_HPP -#error undoMultipleOperationBlock.hpp multiply included -#endif -#define UNDO_UNDOMULTIPLEOPERATIONBLOCK_HPP - -#ifndef UNDO_UNDOMGR_HPP -#include "core/undo/undoUndoMgr.hpp" -#endif - -//============================================================================ //============================================================================ class undoMultipleOperationBlock { diff --git a/renderlib/core/undo/undoUndoInterest.cpp b/renderlib/core/undo/undoUndoInterest.cpp index ca46f3e4..699ab48e 100644 --- a/renderlib/core/undo/undoUndoInterest.cpp +++ b/renderlib/core/undo/undoUndoInterest.cpp @@ -1,9 +1 @@ -/****************************************************************************\ -** undoUndoInterest.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/undo/undoUndoInterest.hpp" diff --git a/renderlib/core/undo/undoUndoInterest.hpp b/renderlib/core/undo/undoUndoInterest.hpp index b8763235..3ab690b9 100644 --- a/renderlib/core/undo/undoUndoInterest.hpp +++ b/renderlib/core/undo/undoUndoInterest.hpp @@ -1,18 +1,11 @@ +#pragma once +//============================================================================ /****************************************************************************\ -** undoUndoInterest.hpp ** ** An Undo Interest is something that cares about the undo system ** changing. ** -** -** \****************************************************************************/ -#ifdef UNDO_UNDOINTEREST_HPP -#error undoUndoInterest.hpp multiply included -#endif -#define UNDO_UNDOINTEREST_HPP - -//============================================================================ //============================================================================ class undoUndoInterest { diff --git a/renderlib/core/undo/undoUndoMgr.cpp b/renderlib/core/undo/undoUndoMgr.cpp index 0a9db9c2..21662635 100644 --- a/renderlib/core/undo/undoUndoMgr.cpp +++ b/renderlib/core/undo/undoUndoMgr.cpp @@ -1,11 +1,3 @@ -/***************************************************************************** -** undoUndoMgr.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/undo/undoUndoMgr.hpp" #include "core/undo/undoMultipleOperation.hpp" diff --git a/renderlib/core/undo/undoUndoMgr.hpp b/renderlib/core/undo/undoUndoMgr.hpp index b9bea890..5c138b0c 100644 --- a/renderlib/core/undo/undoUndoMgr.hpp +++ b/renderlib/core/undo/undoUndoMgr.hpp @@ -1,17 +1,4 @@ -/***************************************************************************** -** undoUndoMgr.hpp -** -** An UndoOperation should be created each time a step is -** taken that can be undone. The UndoMgr keeps track of the -** last few operations. -** -** -** -\****************************************************************************/ -#ifdef UNDO_UNDOMGR_HPP -#error undoUndoMgr.hpp multiply included -#endif -#define UNDO_UNDOMGR_HPP +#pragma once #include #include @@ -22,6 +9,13 @@ class undoUndoInterest; class undoUndoOperation; //============================================================================ +/***************************************************************************** +** +** An UndoOperation should be created each time a step is +** taken that can be undone. The UndoMgr keeps track of the +** last few operations. +** +\****************************************************************************/ //============================================================================ namespace undoUndoMgr { //-------------------------------------------------------------------- diff --git a/renderlib/core/undo/undoUndoOperation.cpp b/renderlib/core/undo/undoUndoOperation.cpp index ab0229bf..d9c0599e 100644 --- a/renderlib/core/undo/undoUndoOperation.cpp +++ b/renderlib/core/undo/undoUndoOperation.cpp @@ -1,11 +1,3 @@ -/***************************************************************************** -** undoUndoOperation.cpp -** -** see .hpp -** -** -** -\****************************************************************************/ #include "core/undo/undoUndoOperation.hpp" //-------------------------------------------------------------------- diff --git a/renderlib/core/undo/undoUndoOperation.hpp b/renderlib/core/undo/undoUndoOperation.hpp index a9aeaae1..1db4c62e 100644 --- a/renderlib/core/undo/undoUndoOperation.hpp +++ b/renderlib/core/undo/undoUndoOperation.hpp @@ -1,19 +1,5 @@ -/***************************************************************************** -** undoUndoOperation.hpp -** -** This is the abstract base class for operations that can -** be undone -** -** -** -\****************************************************************************/ #pragma once -#ifdef UNDO_UNDOOPERATION_HPP -#error undoUndoOperation.hpp multiply included -#endif -#define UNDO_UNDOOPERATION_HPP - #include //============================================================================ From 73a8a96841afd80c98feda3f2a45e641a48d695f Mon Sep 17 00:00:00 2001 From: dmt Date: Thu, 14 Aug 2025 20:05:16 -0700 Subject: [PATCH 55/60] cleanup --- renderlib/AppearanceObject.cpp | 25 +++++---- renderlib/core/prty/prtyProperty.hpp | 51 +++++++++---------- renderlib/core/undo/undoMultipleOperation.hpp | 4 +- 3 files changed, 39 insertions(+), 41 deletions(-) diff --git a/renderlib/AppearanceObject.cpp b/renderlib/AppearanceObject.cpp index 4d5cbc52..a641cb32 100644 --- a/renderlib/AppearanceObject.cpp +++ b/renderlib/AppearanceObject.cpp @@ -56,16 +56,17 @@ AppearanceObject::AppearanceObject() : prtyObject() { + std::string category("Rendering"); m_renderSettings = std::make_shared(); - m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, "Appearance", "Renderer Type"); + m_rendererType = new ComboBoxUiInfo(&m_appearanceDataObject.RendererType, category, "Renderer Type"); m_rendererType->SetToolTip("Select volume rendering type"); m_rendererType->SetStatusTip("Select volume rendering type"); AddProperty(m_rendererType); - m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, "Appearance", "Shading Type"); + m_shadingType = new ComboBoxUiInfo(&m_appearanceDataObject.ShadingType, category, "Shading Type"); m_shadingType->SetToolTip("Select volume shading style"); m_shadingType->SetStatusTip("Select volume shading style"); AddProperty(m_shadingType); - m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, "Appearance", "Density Scale"); + m_densityScale = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.DensityScale, category, "Density Scale"); m_densityScale->SetToolTip("Set scattering density for volume"); m_densityScale->SetStatusTip("Set scattering density for volume"); m_densityScale->min = 0.001f; @@ -75,8 +76,7 @@ AppearanceObject::AppearanceObject() m_densityScale->numTickMarks = 10; // numTickMarks m_densityScale->suffix = ""; // suffix AddProperty(m_densityScale); - m_gradientFactor = - new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.GradientFactor, "Appearance", "Gradient Factor"); + m_gradientFactor = new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.GradientFactor, category, "Gradient Factor"); m_gradientFactor->SetToolTip("Mix between BRDF and Phase shading"); m_gradientFactor->SetStatusTip("Mix between BRDF and Phase shading"); m_gradientFactor->min = 0.0f; @@ -87,7 +87,7 @@ AppearanceObject::AppearanceObject() m_gradientFactor->suffix = ""; // suffix AddProperty(m_gradientFactor); m_stepSizePrimaryRay = - new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizePrimaryRay, "Appearance", "Step Size Primary Ray"); + new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizePrimaryRay, category, "Step Size Primary Ray"); m_stepSizePrimaryRay->SetToolTip("Set volume ray march step size for camera rays"); m_stepSizePrimaryRay->SetStatusTip("Set volume ray march step size for camera rays"); m_stepSizePrimaryRay->min = 1.0f; @@ -98,7 +98,7 @@ AppearanceObject::AppearanceObject() m_stepSizePrimaryRay->suffix = ""; // suffix AddProperty(m_stepSizePrimaryRay); m_stepSizeSecondaryRay = - new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizeSecondaryRay, "Appearance", "Step Size Secondary Ray"); + new FloatSliderSpinnerUiInfo(&m_appearanceDataObject.StepSizeSecondaryRay, category, "Step Size Secondary Ray"); m_stepSizeSecondaryRay->SetToolTip("Set volume ray march step size for scattered rays"); m_stepSizeSecondaryRay->SetStatusTip("Set volume ray march step size for scattered rays"); m_stepSizeSecondaryRay->min = 1.0f; @@ -108,24 +108,23 @@ AppearanceObject::AppearanceObject() m_stepSizeSecondaryRay->numTickMarks = 10; // numTickMarks m_stepSizeSecondaryRay->suffix = ""; // suffix AddProperty(m_stepSizeSecondaryRay); - m_interpolate = new CheckBoxUiInfo(&m_appearanceDataObject.Interpolate, "Appearance", "Interpolate"); + m_interpolate = new CheckBoxUiInfo(&m_appearanceDataObject.Interpolate, category, "Interpolate"); m_interpolate->SetToolTip("Interpolated volume sampling"); m_interpolate->SetStatusTip("Interpolated volume sampling"); AddProperty(m_interpolate); - m_backgroundColor = new ColorPickerUiInfo(&m_appearanceDataObject.BackgroundColor, "Appearance", "Background Color"); + m_backgroundColor = new ColorPickerUiInfo(&m_appearanceDataObject.BackgroundColor, category, "Background Color"); m_backgroundColor->SetToolTip("Set background color"); m_backgroundColor->SetStatusTip("Set background color"); AddProperty(m_backgroundColor); - m_showBoundingBox = new CheckBoxUiInfo(&m_appearanceDataObject.ShowBoundingBox, "Appearance", "Show Bounding Box"); + m_showBoundingBox = new CheckBoxUiInfo(&m_appearanceDataObject.ShowBoundingBox, category, "Show Bounding Box"); m_showBoundingBox->SetToolTip("Show/hide bounding box"); m_showBoundingBox->SetStatusTip("Show/hide bounding box"); AddProperty(m_showBoundingBox); - m_boundingBoxColor = - new ColorPickerUiInfo(&m_appearanceDataObject.BoundingBoxColor, "Appearance", "Bounding Box Color"); + m_boundingBoxColor = new ColorPickerUiInfo(&m_appearanceDataObject.BoundingBoxColor, category, "Bounding Box Color"); m_boundingBoxColor->SetToolTip("Set bounding box color"); m_boundingBoxColor->SetStatusTip("Set bounding box color"); AddProperty(m_boundingBoxColor); - m_showScaleBar = new CheckBoxUiInfo(&m_appearanceDataObject.ShowScaleBar, "Appearance", "Show Scale Bar"); + m_showScaleBar = new CheckBoxUiInfo(&m_appearanceDataObject.ShowScaleBar, category, "Show Scale Bar"); m_showScaleBar->SetToolTip("Show/hide scale bar"); m_showScaleBar->SetStatusTip("Show/hide scale bar"); AddProperty(m_showScaleBar); diff --git a/renderlib/core/prty/prtyProperty.hpp b/renderlib/core/prty/prtyProperty.hpp index 4c710e1a..ef78dce4 100644 --- a/renderlib/core/prty/prtyProperty.hpp +++ b/renderlib/core/prty/prtyProperty.hpp @@ -1,6 +1,30 @@ #pragma once + +#include "core/prty/prtyPropertyCallback.hpp" +#include "core/undo/undoUndoOperation.hpp" + +#include +#include +#include +#include + +//============================================================================ +// forward references +//============================================================================ +class prtyProperty; +class prtyPropertyReference; +class chReader; +class chWriter; + +//============================================================================ +// typedefs +//============================================================================ +namespace { +typedef std::vector property_list; +}; + +//============================================================================ /****************************************************************************\ -** prtyProperty.hpp ** ** A property corresponds to a value, singular or compound. ** (int, float, vector, matrix, color, etc.) @@ -51,31 +75,6 @@ ** ** \****************************************************************************/ - -#include "core/prty/prtyPropertyCallback.hpp" -#include "core/undo/undoUndoOperation.hpp" - -#include -#include -#include -#include - -//============================================================================ -// forward references -//============================================================================ -class prtyProperty; -class prtyPropertyReference; -class chReader; -class chWriter; - -//============================================================================ -// typedefs -//============================================================================ -namespace { -typedef std::vector property_list; -}; - -//============================================================================ //============================================================================ class prtyProperty { diff --git a/renderlib/core/undo/undoMultipleOperation.hpp b/renderlib/core/undo/undoMultipleOperation.hpp index a4ec4d0f..498ec1a3 100644 --- a/renderlib/core/undo/undoMultipleOperation.hpp +++ b/renderlib/core/undo/undoMultipleOperation.hpp @@ -5,8 +5,8 @@ #include //============================================================================ -//** This class can be used to group a number of single undo operations -//** into one undo operation that can be undone and redone in one step. +// This class can be used to group a number of single undo operations +// into one undo operation that can be undone and redone in one step. //============================================================================ class undoMultipleOperation : public undoUndoOperation { From fd552fd8c40dd0bcb5f12b7994e767d1ed2ea25f Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Wed, 3 Sep 2025 17:05:19 -0700 Subject: [PATCH 56/60] fix cmake problem --- agave_app/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/agave_app/CMakeLists.txt b/agave_app/CMakeLists.txt index 13281672..618035c7 100644 --- a/agave_app/CMakeLists.txt +++ b/agave_app/CMakeLists.txt @@ -33,10 +33,6 @@ target_sources(agaveapp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/cgiparser.h" "${CMAKE_CURRENT_SOURCE_DIR}/commandBuffer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/commandBuffer.h" - "${CMAKE_CURRENT_SOURCE_DIR}/Film.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/Film.h" - "${CMAKE_CURRENT_SOURCE_DIR}/Focus.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/Focus.h" "${CMAKE_CURRENT_SOURCE_DIR}/GLView3D.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/GLView3D.h" "${CMAKE_CURRENT_SOURCE_DIR}/loadDialog.cpp" From 5a8df9f69485fc30fdaedfebd54d21eec6039ea1 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Wed, 3 Sep 2025 17:20:20 -0700 Subject: [PATCH 57/60] reinstate tensorstore version --- renderlib/io/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/renderlib/io/CMakeLists.txt b/renderlib/io/CMakeLists.txt index ef2e6d15..e9706fe9 100644 --- a/renderlib/io/CMakeLists.txt +++ b/renderlib/io/CMakeLists.txt @@ -36,8 +36,10 @@ if(APPLE) endif(APPLE) FetchContent_Declare( tensorstore - URL "https://github.com/google/tensorstore/archive/refs/tags/v0.1.75.tar.gz" - URL_HASH SHA256=82f8a170bd6635147315036dcad4e5f32c4d5374a3faa7cdd4e958a15b9cba2e + # URL "https://github.com/google/tensorstore/archive/refs/tags/v0.1.75.tar.gz" + # URL_HASH SHA256=82f8a170bd6635147315036dcad4e5f32c4d5374a3faa7cdd4e958a15b9cba2e + URL "https://github.com/google/tensorstore/tarball/9e1feb7215ee876d3b62b8d84c03c9c2a1eec0c2" + URL_HASH SHA256=baeb9e1eafe1d8244d37c614711a8125467404801274e35979ba2896c8abdf29 ) FetchContent_MakeAvailable(tensorstore) From f355dfed4fb7ae4c17149148b41a7ed9d8828474 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Wed, 3 Sep 2025 17:33:20 -0700 Subject: [PATCH 58/60] fix include --- agave_app/CameraWidget.h | 1 - 1 file changed, 1 deletion(-) diff --git a/agave_app/CameraWidget.h b/agave_app/CameraWidget.h index 35ed6fdb..2bb56e31 100644 --- a/agave_app/CameraWidget.h +++ b/agave_app/CameraWidget.h @@ -1,6 +1,5 @@ #pragma once -#include "Camera.h" #include "qtControls/Controls.h" // #include "renderlib/core/prty/prtyProperty.h" From 2e410566d366b19b3749d796f2f035cfe4bf6c45 Mon Sep 17 00:00:00 2001 From: Dan Toloudis Date: Wed, 3 Sep 2025 17:35:13 -0700 Subject: [PATCH 59/60] fix cmake --- agave_app/qtControls/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/agave_app/qtControls/CMakeLists.txt b/agave_app/qtControls/CMakeLists.txt index 506089fd..8e8f55a0 100644 --- a/agave_app/qtControls/CMakeLists.txt +++ b/agave_app/qtControls/CMakeLists.txt @@ -3,6 +3,8 @@ target_include_directories(agaveapp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ) target_sources(agaveapp PRIVATE +"${CMAKE_CURRENT_SOURCE_DIR}/controlFactory.cpp" +"${CMAKE_CURRENT_SOURCE_DIR}/controlFactory.h" "${CMAKE_CURRENT_SOURCE_DIR}/Controls.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Controls.h" "${CMAKE_CURRENT_SOURCE_DIR}/RangeWidget.cpp" From 514fc1c6673ecb9f75fc0f472049b83a46f12b6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 10:55:06 +0000 Subject: [PATCH 60/60] Bump js-yaml from 4.1.0 to 4.1.1 in /webclient Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- webclient/package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/webclient/package-lock.json b/webclient/package-lock.json index 7cecd184..cf8e2775 100644 --- a/webclient/package-lock.json +++ b/webclient/package-lock.json @@ -6144,10 +6144,11 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" },