From f4da2d748f1b51a0d792011ac01a90df52c05050 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Sep 2024 10:55:53 +0200 Subject: [PATCH] #11693 Store camera position for each associated case A top level view can change the connected grid case. Add option to store the camera position for each grid case. Add option Store View Settings for Case , default off. --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/Rim3dView.h | 4 +- .../ProjectDataModel/RimCameraPosition.cpp | 87 +++++++++++++++++++ .../ProjectDataModel/RimCameraPosition.h | 54 ++++++++++++ .../ProjectDataModel/RimEclipseView.cpp | 73 +++++++++++++++- .../ProjectDataModel/RimEclipseView.h | 7 +- 6 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 ApplicationLibCode/ProjectDataModel/RimCameraPosition.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/RimCameraPosition.h diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index abefbff49e..67bccb2642 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -133,6 +133,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimEmCase.h ${CMAKE_CURRENT_LIST_DIR}/RimEclipseViewCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseEnsemble.h + ${CMAKE_CURRENT_LIST_DIR}/RimCameraPosition.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -266,6 +267,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimPolylinePickerInterface.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEclipseViewCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseEnsemble.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimCameraPosition.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.h b/ApplicationLibCode/ProjectDataModel/Rim3dView.h index 7272e8ea8a..dca057a54b 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.h +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.h @@ -266,6 +266,7 @@ class Rim3dView : public RimViewWindow, public RiuViewerToViewInterface, public QWidget* createViewWidget( QWidget* mainWindowParent ) override; void setCameraPosition( const cvf::Mat4d& cameraPosition ) override; + void setCameraPointOfInterest( const cvf::Vec3d& cameraPointOfInterest ) override; protected: // Timestep Field. Children clamps this differently @@ -295,9 +296,6 @@ class Rim3dView : public RimViewWindow, public RiuViewerToViewInterface, public // Implementation of RimNameConfigHolderInterface void performAutoNameUpdate() final; - // Implementation of RiuViewerToViewInterface - void setCameraPointOfInterest( const cvf::Vec3d& cameraPointOfInterest ) override; - void endAnimation() override; caf::PdmObjectHandle* implementingPdmObject() override; diff --git a/ApplicationLibCode/ProjectDataModel/RimCameraPosition.cpp b/ApplicationLibCode/ProjectDataModel/RimCameraPosition.cpp new file mode 100644 index 0000000000..81ac3199b4 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimCameraPosition.cpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimCameraPosition.h" + +#include "RimEclipseCase.h" + +CAF_PDM_SOURCE_INIT( RimCameraPosition, "RimCameraPosition" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCameraPosition::RimCameraPosition() +{ + CAF_PDM_InitObject( "Camera Position for Case" ); + + CAF_PDM_InitFieldNoDefault( &m_eclipseCase, "EclipseCase", "Eclipse Case" ); + + CAF_PDM_InitField( &m_cameraPosition, "CameraPosition", cvf::Mat4d::IDENTITY, "" ); + m_cameraPosition.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitField( &m_cameraPointOfInterest, "CameraPointOfInterest", cvf::Vec3d::ZERO, "" ); + m_cameraPointOfInterest.uiCapability()->setUiHidden( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase* RimCameraPosition::eclipseCase() const +{ + return m_eclipseCase(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCameraPosition::setEclipseCase( RimEclipseCase* eclipseCase ) +{ + m_eclipseCase = eclipseCase; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Mat4d RimCameraPosition::cameraPosition() const +{ + return m_cameraPosition(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCameraPosition::setCameraPosition( const cvf::Mat4d& cameraPosition ) +{ + m_cameraPosition = cameraPosition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d RimCameraPosition::cameraPointOfInterest() const +{ + return m_cameraPointOfInterest(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCameraPosition::setCameraPointOfInterest( const cvf::Vec3d& cameraPointOfInterest ) +{ + m_cameraPointOfInterest = cameraPointOfInterest; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimCameraPosition.h b/ApplicationLibCode/ProjectDataModel/RimCameraPosition.h new file mode 100644 index 0000000000..6a6d652121 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimCameraPosition.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmObject.h" + +#include "cafPdmField.h" +#include "cafPdmFieldCvfMat4d.h" +#include "cafPdmFieldCvfVec3d.h" +#include "cafPdmPtrField.h" + +class RimEclipseCase; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimCameraPosition : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimCameraPosition(); + + RimEclipseCase* eclipseCase() const; + void setEclipseCase( RimEclipseCase* eclipseCase ); + + cvf::Mat4d cameraPosition() const; + void setCameraPosition( const cvf::Mat4d& cameraPosition ); + + cvf::Vec3d cameraPointOfInterest() const; + void setCameraPointOfInterest( const cvf::Vec3d& cameraPointOfInterest ); + +private: + caf::PdmPtrField m_eclipseCase; + caf::PdmField m_cameraPosition; + caf::PdmField m_cameraPointOfInterest; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 9618024d72..33c7e0ebcb 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -47,6 +47,7 @@ #include "Rim3dOverlayInfoConfig.h" #include "RimAnnotationCollection.h" #include "RimAnnotationInViewCollection.h" +#include "RimCameraPosition.h" #include "RimCellEdgeColors.h" #include "RimCellFilterCollection.h" #include "RimEclipseCase.h" @@ -147,6 +148,7 @@ RimEclipseView::RimEclipseView() CAF_PDM_InitFieldNoDefault( &m_customEclipseCase_OBSOLETE, "CustomEclipseCase", "Custom Case" ); CAF_PDM_InitScriptableFieldNoDefault( &m_eclipseCase, "EclipseCase", "Eclipse Case" ); + CAF_PDM_InitField( &m_storeViewSettingsPerCase, "StoreViewSettingsPerCase", false, "Store View Settings for Case" ); CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &m_cellResult, "GridCellResult", "CellResult", "Cell Result", ":/CellResult.png" ); m_cellResult = new RimEclipseCellColors(); @@ -218,6 +220,8 @@ RimEclipseView::RimEclipseView() m_cellResult()->setAdditionalUiTreeObjects( { m_additionalResultsForResultInfo() } ); + CAF_PDM_InitFieldNoDefault( &m_cameraPositions, "CameraPositions", "Camera Positions for Cases" ); + setDeletable( true ); updateAnimations.connect( this, &RimEclipseView::onAnimationsUpdate ); @@ -394,6 +398,55 @@ void RimEclipseView::propagateEclipseCaseToChildObjects() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::storeCurrentAndApplyNewCameraPosition( RimEclipseCase* currentCase, RimEclipseCase* newCase ) +{ + auto settingsForCases = m_cameraPositions.childrenByType(); + + // Propagate viewer UI settings to RimEclipseView before accessing camera positions + setupBeforeSave(); + + auto findSettingsForCase = [&]( RimEclipseCase* eclipseCase ) -> RimCameraPosition* + { + for ( auto settingsForCase : settingsForCases ) + { + if ( settingsForCase->eclipseCase() == eclipseCase ) + { + return settingsForCase; + } + } + return nullptr; + }; + + if ( currentCase ) + { + RimCameraPosition* settingsForCurrentCase = findSettingsForCase( currentCase ); + if ( !settingsForCurrentCase ) + { + settingsForCurrentCase = new RimCameraPosition; + settingsForCurrentCase->setEclipseCase( currentCase ); + m_cameraPositions.push_back( settingsForCurrentCase ); + } + + settingsForCurrentCase->setCameraPosition( cameraPosition() ); + settingsForCurrentCase->setCameraPointOfInterest( cameraPointOfInterest() ); + } + + if ( newCase ) + { + if ( RimCameraPosition* settingsForNewCase = findSettingsForCase( newCase ) ) + { + viewer()->mainCamera()->setViewMatrix( settingsForNewCase->cameraPosition() ); + viewer()->setPointOfInterest( settingsForNewCase->cameraPointOfInterest() ); + return; + } + } + + zoomAll(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -410,7 +463,15 @@ void RimEclipseView::fieldChangedByUi( const caf::PdmFieldHandle* changedField, updateGridBoxData(); updateAnnotationItems(); - zoomAll(); + if ( m_storeViewSettingsPerCase() ) + { + auto currentEclipseCase = dynamic_cast( oldValue.value>().rawPtr() ); + storeCurrentAndApplyNewCameraPosition( currentEclipseCase, m_eclipseCase ); + } + else + { + zoomAll(); + } return; } @@ -1564,6 +1625,8 @@ void RimEclipseView::updateLegendRangesTextAndVisibility( RimRegularLegendConfig //-------------------------------------------------------------------------------------------------- void RimEclipseView::setEclipseCase( RimEclipseCase* reservoir ) { + // TODO: How should we manage the view settings? See storeCurrentAndApplyNewCameraPosition() + m_eclipseCase = reservoir; propagateEclipseCaseToChildObjects(); @@ -1900,7 +1963,13 @@ const std::vector& RimEclipseView::visibleGridParts() const void RimEclipseView::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { // Only show case option when not under a case in the project tree. - if ( !firstAncestorOrThisOfType() ) uiOrdering.add( &m_eclipseCase ); + if ( !firstAncestorOrThisOfType() ) + { + caf::PdmUiGroup* dataSourceGroup = uiOrdering.addNewGroup( "Data Source" ); + + dataSourceGroup->add( &m_eclipseCase ); + dataSourceGroup->add( &m_storeViewSettingsPerCase ); + } Rim3dView::defineUiOrdering( uiConfigName, uiOrdering ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h index a5730e9a4b..a3fd53385b 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h @@ -69,6 +69,7 @@ class RimStreamlineInViewCollection; class RimMultipleEclipseResults; class RigEclipseResultAddress; class RimFaultReactivationModelCollection; +class RimCameraPosition; namespace cvf { @@ -220,10 +221,13 @@ class RimEclipseView : public RimGridView void setVisibleGridPartsWatertight(); void propagateEclipseCaseToChildObjects(); + void storeCurrentAndApplyNewCameraPosition( RimEclipseCase* previousCase, RimEclipseCase* newCase ); protected: - cvf::ref m_faultReactVizModel; + cvf::ref m_faultReactVizModel; + caf::PdmPtrField m_eclipseCase; + caf::PdmField m_storeViewSettingsPerCase; private: caf::PdmField m_showInvalidCells; @@ -255,4 +259,5 @@ class RimEclipseView : public RimGridView std::vector m_visibleGridParts; caf::PdmChildField m_additionalResultsForResultInfo; + caf::PdmChildArrayField m_cameraPositions; };