From 767908e019dd38f8761c4ccad07eab954eece19f Mon Sep 17 00:00:00 2001
From: toloudis <danielt@alleninstitute.org>
Date: Thu, 30 Nov 2023 17:15:23 -0800
Subject: [PATCH] add a "keep settings" button for load dialog

---
 agave_app/AppearanceDockWidget.h       |  4 +-
 agave_app/AppearanceSettingsWidget.cpp |  2 +-
 agave_app/AppearanceSettingsWidget.h   |  2 +-
 agave_app/agaveGui.cpp                 | 18 +++--
 agave_app/agaveGui.h                   |  4 +-
 agave_app/loadDialog.cpp               |  5 ++
 agave_app/loadDialog.h                 | 12 ++--
 renderlib/AppScene.cpp                 | 99 ++++++++++++++++----------
 renderlib/AppScene.h                   |  2 +
 9 files changed, 95 insertions(+), 53 deletions(-)

diff --git a/agave_app/AppearanceDockWidget.h b/agave_app/AppearanceDockWidget.h
index 79ab4bc4..3ad8ffd6 100644
--- a/agave_app/AppearanceDockWidget.h
+++ b/agave_app/AppearanceDockWidget.h
@@ -14,7 +14,7 @@ class QAppearanceWidget : public QWidget
 public:
   QAppearanceWidget(QWidget* pParent = NULL, QRenderSettings* qrs = nullptr, RenderSettings* rs = nullptr);
 
-  void onNewImage(Scene* s) { m_AppearanceSettingsWidget.onNewImage(s); }
+  void onNewImage(Scene* s, bool keepCurrentSettings) { m_AppearanceSettingsWidget.onNewImage(s, keepCurrentSettings); }
 
 protected:
   QGridLayout m_MainLayout;
@@ -28,7 +28,7 @@ class QAppearanceDockWidget : public QDockWidget
 public:
   QAppearanceDockWidget(QWidget* pParent = NULL, QRenderSettings* qrs = nullptr, RenderSettings* rs = nullptr);
 
-  void onNewImage(Scene* s) { m_VolumeAppearanceWidget.onNewImage(s); }
+  void onNewImage(Scene* s, bool keepCurrentSettings) { m_VolumeAppearanceWidget.onNewImage(s, keepCurrentSettings); }
 
 protected:
   QAppearanceWidget m_VolumeAppearanceWidget;
diff --git a/agave_app/AppearanceSettingsWidget.cpp b/agave_app/AppearanceSettingsWidget.cpp
index b0d20582..9289e075 100644
--- a/agave_app/AppearanceSettingsWidget.cpp
+++ b/agave_app/AppearanceSettingsWidget.cpp
@@ -1164,7 +1164,7 @@ QAppearanceSettingsWidget::initLightingControls(Scene* scene)
 }
 
 void
-QAppearanceSettingsWidget::onNewImage(Scene* scene)
+QAppearanceSettingsWidget::onNewImage(Scene* scene, bool keepCurrentSettings)
 {
   // Don't forget that most ui updating triggered in this function should
   // NOT signal changes to the scene.
diff --git a/agave_app/AppearanceSettingsWidget.h b/agave_app/AppearanceSettingsWidget.h
index e2f24c3a..f53afcf7 100644
--- a/agave_app/AppearanceSettingsWidget.h
+++ b/agave_app/AppearanceSettingsWidget.h
@@ -26,7 +26,7 @@ class QAppearanceSettingsWidget : public QGroupBox
 public:
   QAppearanceSettingsWidget(QWidget* pParent = NULL, QRenderSettings* qrs = nullptr, RenderSettings* rs = nullptr);
 
-  void onNewImage(Scene* scene);
+  void onNewImage(Scene* scene, bool keepCurrentSettings);
 
 public slots:
   void OnRenderBegin(void);
diff --git a/agave_app/agaveGui.cpp b/agave_app/agaveGui.cpp
index cacff27b..00897f58 100644
--- a/agave_app/agaveGui.cpp
+++ b/agave_app/agaveGui.cpp
@@ -465,7 +465,9 @@ agaveGui::onImageLoaded(std::shared_ptr<ImageXYZC> image,
                         const LoadSpec& loadSpec,
                         uint32_t sizeT,
                         const Serialize::ViewerState* vs,
-                        std::shared_ptr<IFileReader> reader)
+                        std::shared_ptr<IFileReader> reader,
+                        // only used if vs is null
+                        bool keepCurrentUISettings)
 {
   m_loadSpec = loadSpec;
 
@@ -490,8 +492,11 @@ agaveGui::onImageLoaded(std::shared_ptr<ImageXYZC> image,
   // this is deref'ing the previous _volume shared_ptr.
   m_appScene.m_volume = image;
 
-  m_appScene.initSceneFromImg(image);
-  m_glView->initCameraFromImage(&m_appScene);
+  m_appScene.initBoundsFromImg(image);
+  if (!keepCurrentUISettings) {
+    m_appScene.initSceneFromImg(image);
+    m_glView->initCameraFromImage(&m_appScene);
+  }
 
   // initialize _appScene from ViewerState
   if (vs) {
@@ -506,7 +511,7 @@ agaveGui::onImageLoaded(std::shared_ptr<ImageXYZC> image,
   std::string filename = loadSpec.getFilename();
   m_tabs->setTabText(0, QString::fromStdString(filename));
 
-  m_appearanceDockWidget->onNewImage(&m_appScene);
+  m_appearanceDockWidget->onNewImage(&m_appScene, keepCurrentUISettings);
   m_timelinedock->onNewImage(&m_appScene, loadSpec, reader);
 
   // set up status view with some stats.
@@ -576,12 +581,15 @@ agaveGui::open(const std::string& file, const Serialize::ViewerState* vs)
     return false;
   }
 
+  bool keepCurrentUISettings = true;
+
   if (!vs) {
 
     LoadDialog* loadDialog = new LoadDialog(file, multiscaledims, sceneToLoad, this);
     if (loadDialog->exec() == QDialog::Accepted) {
       loadSpec = loadDialog->getLoadSpec();
       dims = multiscaledims[loadDialog->getMultiscaleLevelIndex()].getVolumeDimensions();
+      keepCurrentUISettings = loadDialog->getKeepSettings();
     } else {
       LOG_INFO << "Canceled load dialog.";
       return true;
@@ -607,7 +615,7 @@ agaveGui::open(const std::string& file, const Serialize::ViewerState* vs)
     showOpenFailedMessageBox(QString::fromStdString(file));
     return false;
   }
-  onImageLoaded(image, loadSpec, dims.sizeT, vs, reader);
+  onImageLoaded(image, loadSpec, dims.sizeT, vs, reader, keepCurrentUISettings);
   return true;
 }
 
diff --git a/agave_app/agaveGui.h b/agave_app/agaveGui.h
index ed0b0457..1ef934e7 100644
--- a/agave_app/agaveGui.h
+++ b/agave_app/agaveGui.h
@@ -38,7 +38,9 @@ class agaveGui : public QMainWindow
                      const LoadSpec& loadSpec,
                      uint32_t sizeT,
                      const Serialize::ViewerState* vs,
-                     std::shared_ptr<IFileReader> reader);
+                     std::shared_ptr<IFileReader> reader,
+                     // only used if vs is null
+                     bool keepCurrentUISettings);
 
 private slots:
   void open();
diff --git a/agave_app/loadDialog.cpp b/agave_app/loadDialog.cpp
index 83b37f49..500b137a 100644
--- a/agave_app/loadDialog.cpp
+++ b/agave_app/loadDialog.cpp
@@ -144,6 +144,9 @@ LoadDialog::LoadDialog(std::string path, const std::vector<MultiscaleDims>& dims
 
   updateMultiresolutionLevel(mSelectedLevel);
 
+  m_keepSettingsCheckbox = new QCheckBox(this);
+  m_keepSettingsCheckbox->setChecked(true);
+
   QFormLayout* layout = new QFormLayout(this);
   layout->setLabelAlignment(Qt::AlignLeft);
   layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
@@ -172,6 +175,8 @@ LoadDialog::LoadDialog(std::string path, const std::vector<MultiscaleDims>& dims
   layout->addItem(new QSpacerItem(0, spacing, QSizePolicy::Expanding, QSizePolicy::Expanding));
   layout->addRow(mMemoryEstimateLabel);
   layout->addItem(new QSpacerItem(0, spacing, QSizePolicy::Expanding, QSizePolicy::Expanding));
+  layout->addRow("Keep current AGAVE settings", m_keepSettingsCheckbox);
+  layout->addItem(new QSpacerItem(0, spacing, QSizePolicy::Expanding, QSizePolicy::Expanding));
   layout->addRow(buttonBox);
 
   setLayout(layout);
diff --git a/agave_app/loadDialog.h b/agave_app/loadDialog.h
index b608f921..1c80f811 100644
--- a/agave_app/loadDialog.h
+++ b/agave_app/loadDialog.h
@@ -34,6 +34,7 @@ class LoadDialog : public QDialog
 
   LoadSpec getLoadSpec() const;
   int getMultiscaleLevelIndex() const { return mSelectedLevel; }
+  bool getKeepSettings() const { return m_keepSettingsCheckbox->isChecked(); }
 
   QSize sizeHint() const override { return QSize(400, 100); }
 
@@ -52,22 +53,21 @@ private slots:
   int mSelectedLevel;
 
   QSpinBox* mSceneInput;
+  // show multiresolutions
   QComboBox* mMultiresolutionInput;
+  // start with a single timepoint
   QIntSlider* m_TimeSlider;
+  // select any set of channels
   QListWidget* mChannels;
   Section* mChannelsSection;
-  QTreeWidget* mMetadataTree;
   QLabel* mVolumeLabel;
   QLabel* mMemoryEstimateLabel;
+  // select region of interest in zyx
   RangeWidget* m_roiX;
   RangeWidget* m_roiY;
   RangeWidget* m_roiZ;
   Section* m_roiSection;
-  // show multiresolutions
-
-  // select region of interest in zyx
-  // select any set of channels
-  // start with a single timepoint
+  QCheckBox* m_keepSettingsCheckbox;
 
   void updateMemoryEstimate();
   void updateMultiresolutionInput();
diff --git a/renderlib/AppScene.cpp b/renderlib/AppScene.cpp
index d9d906ad..2b02ba9a 100644
--- a/renderlib/AppScene.cpp
+++ b/renderlib/AppScene.cpp
@@ -6,43 +6,6 @@
 
 #include <glm/gtx/color_space.hpp>
 
-void
-Scene::initLights()
-{
-  Light BackgroundLight;
-
-  BackgroundLight.m_T = 1;
-  float inten = 1.0f;
-
-  float topr = 0.5f;
-  float topg = 0.5f;
-  float topb = 0.5f;
-  float midr = 0.5f;
-  float midg = 0.5f;
-  float midb = 0.5f;
-  float botr = 0.5f;
-  float botg = 0.5f;
-  float botb = 0.5f;
-
-  BackgroundLight.m_ColorTop = inten * glm::vec3(topr, topg, topb);
-  BackgroundLight.m_ColorMiddle = inten * glm::vec3(midr, midg, midb);
-  BackgroundLight.m_ColorBottom = inten * glm::vec3(botr, botg, botb);
-
-  m_lighting.AddLight(BackgroundLight);
-
-  Light AreaLight;
-
-  AreaLight.m_T = 0;
-  AreaLight.m_Theta = 0.0f;
-  AreaLight.m_Phi = HALF_PI_F;
-  AreaLight.m_Width = 0.15f;
-  AreaLight.m_Height = 0.15f;
-  AreaLight.m_Distance = 1.5f;
-  AreaLight.m_Color = 10.0f * glm::vec3(1.0f, 1.0f, 1.0f);
-
-  m_lighting.AddLight(AreaLight);
-}
-
 inline std::vector<float>
 rndColors(int count)
 {
@@ -83,6 +46,68 @@ rndColors(int count)
   return colors;
 }
 
+VolumeDisplay::VolumeDisplay()
+{
+  std::vector<float> colors = rndColors(MAX_CPU_CHANNELS);
+
+  for (uint32_t i = 0; i < MAX_CPU_CHANNELS; ++i) {
+    // enable first N channels!
+    m_enabled[i] = (i < ImageXYZC::FIRST_N_CHANNELS);
+
+    m_diffuse[i * 3] = colors[i * 3];
+    m_diffuse[i * 3 + 1] = colors[i * 3 + 1];
+    m_diffuse[i * 3 + 2] = colors[i * 3 + 2];
+
+    m_specular[i * 3] = 0.0;
+    m_specular[i * 3 + 1] = 0.0;
+    m_specular[i * 3 + 2] = 0.0;
+
+    m_emissive[i * 3] = 0.0;
+    m_emissive[i * 3 + 1] = 0.0;
+    m_emissive[i * 3 + 2] = 0.0;
+
+    m_opacity[i] = 1.0;
+    m_roughness[i] = 1.0;
+  }
+}
+
+void
+Scene::initLights()
+{
+  Light BackgroundLight;
+
+  BackgroundLight.m_T = 1;
+  float inten = 1.0f;
+
+  float topr = 0.5f;
+  float topg = 0.5f;
+  float topb = 0.5f;
+  float midr = 0.5f;
+  float midg = 0.5f;
+  float midb = 0.5f;
+  float botr = 0.5f;
+  float botg = 0.5f;
+  float botb = 0.5f;
+
+  BackgroundLight.m_ColorTop = inten * glm::vec3(topr, topg, topb);
+  BackgroundLight.m_ColorMiddle = inten * glm::vec3(midr, midg, midb);
+  BackgroundLight.m_ColorBottom = inten * glm::vec3(botr, botg, botb);
+
+  m_lighting.AddLight(BackgroundLight);
+
+  Light AreaLight;
+
+  AreaLight.m_T = 0;
+  AreaLight.m_Theta = 0.0f;
+  AreaLight.m_Phi = HALF_PI_F;
+  AreaLight.m_Width = 0.15f;
+  AreaLight.m_Height = 0.15f;
+  AreaLight.m_Distance = 1.5f;
+  AreaLight.m_Color = 10.0f * glm::vec3(1.0f, 1.0f, 1.0f);
+
+  m_lighting.AddLight(AreaLight);
+}
+
 // set up a couple of lights relative to the img's bounding box
 void
 Scene::initSceneFromImg(std::shared_ptr<ImageXYZC> img)
diff --git a/renderlib/AppScene.h b/renderlib/AppScene.h
index fc17a4c6..23e49589 100644
--- a/renderlib/AppScene.h
+++ b/renderlib/AppScene.h
@@ -35,6 +35,8 @@ struct VolumeDisplay
   bool m_enabled[MAX_CPU_CHANNELS];
 
   GradientData m_gradientData[MAX_CPU_CHANNELS];
+
+  VolumeDisplay();
 };
 
 // MUST NOT OUTLIVE ITS LIGHT