diff --git a/src/app/3d/qgs3ddebugwidget.h b/src/app/3d/qgs3ddebugwidget.h index 9964354d3a8f..8f073e329f00 100644 --- a/src/app/3d/qgs3ddebugwidget.h +++ b/src/app/3d/qgs3ddebugwidget.h @@ -21,8 +21,9 @@ class Qgs3DMapCanvas; #include #include "qgs3dmapsettings.h" +#include "qgis_app.h" -class Qgs3DDebugWidget : public QWidget, Ui::Q3DDebugWidget +class APP_EXPORT Qgs3DDebugWidget : public QWidget, Ui::Q3DDebugWidget { Q_OBJECT public: diff --git a/src/app/3d/qgs3dmapconfigwidget.cpp b/src/app/3d/qgs3dmapconfigwidget.cpp index 71dd1481f6b9..ccc77356a1af 100644 --- a/src/app/3d/qgs3dmapconfigwidget.cpp +++ b/src/app/3d/qgs3dmapconfigwidget.cpp @@ -46,7 +46,6 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas setupUi( this ); Q_ASSERT( map ); - Q_ASSERT( mainCanvas ); const QgsSettings settings; @@ -231,7 +230,10 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas groupExtent->setOutputCrs( mMap->crs() ); groupExtent->setCurrentExtent( mMap->extent(), mMap->crs() ); groupExtent->setOutputExtentFromCurrent(); - groupExtent->setMapCanvas( mMainCanvas ); + if ( mMainCanvas ) + { + groupExtent->setMapCanvas( mMainCanvas ); + } // checkbox to display the extent in the 2D Map View mShowExtentIn2DViewCheckbox = new QCheckBox( tr( "Show in 2D map view" ) ); diff --git a/src/app/3d/qgs3dmapconfigwidget.h b/src/app/3d/qgs3dmapconfigwidget.h index 4f1ac998d6eb..0ca0860e7fd1 100644 --- a/src/app/3d/qgs3dmapconfigwidget.h +++ b/src/app/3d/qgs3dmapconfigwidget.h @@ -19,6 +19,7 @@ #include #include +#include "qgis_app.h" class QCheckBox; class Qgs3DMapSettings; @@ -29,7 +30,7 @@ class QgsShadowRenderingSettingsWidget; class Qgs3DMapCanvas; class QgsSkyboxSettings; -class Qgs3DMapConfigWidget : public QWidget, private Ui::Map3DConfigWidget +class APP_EXPORT Qgs3DMapConfigWidget : public QWidget, private Ui::Map3DConfigWidget { Q_OBJECT public: diff --git a/tests/src/3d/sandbox/qgis_3d_sandbox.cpp b/tests/src/3d/sandbox/qgis_3d_sandbox.cpp index d6f4f46979ca..5df777d5edfb 100644 --- a/tests/src/3d/sandbox/qgis_3d_sandbox.cpp +++ b/tests/src/3d/sandbox/qgis_3d_sandbox.cpp @@ -17,25 +17,36 @@ #include -#include "qgsapplication.h" #include "qgs3d.h" +#include "qgs3ddebugwidget.h" +#include "qgs3dmapcanvas.h" +#include "qgs3dmapconfigwidget.h" +#include "qgs3dmapscene.h" +#include "qgs3dmapsettings.h" +#include "qgs3dutils.h" +#include "qgsapplication.h" +#include "qgsflatterraingenerator.h" +#include "qgsgui.h" +#include "qgshelp.h" #include "qgslayertree.h" +#include "qgsmapcanvas.h" #include "qgsmapsettings.h" +#include "qgsmessagebaritem.h" #include "qgspointcloudlayer.h" #include "qgspointcloudlayer3drenderer.h" +#include "qgspointlightsettings.h" #include "qgsproject.h" -#include "qgsflatterraingenerator.h" -#include "qgs3dmapscene.h" -#include "qgs3dmapsettings.h" -#include "qgs3dmapcanvas.h" #include "qgsprojectelevationproperties.h" #include "qgsprojectviewsettings.h" -#include "qgspointlightsettings.h" #include "qgsterrainprovider.h" #include "qgstiledscenelayer.h" #include "qgstiledscenelayer3drenderer.h" +#include +#include +#include #include +#include void initCanvas3D( Qgs3DMapCanvas *canvas ) { @@ -106,6 +117,64 @@ void initCanvas3D( Qgs3DMapCanvas *canvas ) qDebug() << "pending jobs:" << canvas->scene()->totalPendingJobsCount(); } +QDialog *createConfigDialog( Qgs3DMapCanvas *canvas ) +{ + const QPointer configDialog = new QDialog; + configDialog->setWindowTitle( QStringLiteral( "3D Configuration" ) ); + configDialog->setObjectName( QStringLiteral( "3DConfigurationDialog" ) ); + configDialog->setMinimumSize( 600, 460 ); + QgsGui::enableAutoGeometryRestore( configDialog ); + + Qgs3DMapSettings *map = canvas->mapSettings(); + Qgs3DMapConfigWidget *w = new Qgs3DMapConfigWidget( map, nullptr, canvas, configDialog ); + QDialogButtonBox *buttons = new QDialogButtonBox( QDialogButtonBox::Apply | QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help, configDialog ); + + auto applyConfig = [ = ] + { + const QgsVector3D oldOrigin = map->origin(); + const QgsCoordinateReferenceSystem oldCrs = map->crs(); + const QgsCameraPose oldCameraPose = canvas->cameraController()->cameraPose(); + const QgsVector3D oldLookingAt = oldCameraPose.centerPoint(); + + // update map + w->apply(); + + const QgsVector3D p = Qgs3DUtils::transformWorldCoordinates( + oldLookingAt, + oldOrigin, oldCrs, + map->origin(), map->crs(), QgsProject::instance()->transformContext() ); + + if ( p != oldLookingAt ) + { + // apply() call has moved origin of the world so let's move camera so we look still at the same place + QgsCameraPose newCameraPose = oldCameraPose; + newCameraPose.setCenterPoint( p ); + canvas->cameraController()->setCameraPose( newCameraPose ); + } + }; + + QObject::connect( buttons, &QDialogButtonBox::rejected, configDialog, &QDialog::reject ); + QObject::connect( buttons, &QDialogButtonBox::clicked, configDialog, [ = ]( const QAbstractButton * button ) + { + if ( button == buttons->button( QDialogButtonBox::Apply ) || button == buttons->button( QDialogButtonBox::Ok ) ) + applyConfig(); + if ( button == buttons->button( QDialogButtonBox::Ok ) ) + configDialog->accept(); + } ); + QObject::connect( buttons, &QDialogButtonBox::helpRequested, w, []() { QgsHelp::openHelp( QStringLiteral( "map_views/3d_map_view.html#scene-configuration" ) ); } ); + + QObject::connect( w, &Qgs3DMapConfigWidget::isValidChanged, configDialog, [ = ]( const bool valid ) + { + buttons->button( QDialogButtonBox::Apply )->setEnabled( valid ); + buttons->button( QDialogButtonBox::Ok )->setEnabled( valid ); + } ); + + QVBoxLayout *layout = new QVBoxLayout( configDialog ); + layout->addWidget( w, 1 ); + layout->addWidget( buttons ); + return configDialog; +} + int main( int argc, char *argv[] ) { QgsApplication myApp( argc, argv, true, QString(), QStringLiteral( "desktop" ) ); @@ -151,8 +220,63 @@ int main( int argc, char *argv[] ) Qgs3DMapCanvas *canvas = new Qgs3DMapCanvas; initCanvas3D( canvas ); - canvas->resize( 800, 600 ); - canvas->show(); + + // set up the UI + QWidget *windowWidget = new QWidget; + + QToolBar *toolBar = new QToolBar( windowWidget ); + toolBar->setIconSize( QgsGuiUtils::iconSize() ); + toolBar->addAction( QIcon( QgsApplication::iconPath( "mActionZoomFullExtent.svg" ) ), QStringLiteral( "Reset camera to default position" ), windowWidget, [canvas] + { + canvas->resetView(); + } ); + QAction *toggleDebugPanel = toolBar->addAction( + QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/general.svg" ) ), + QStringLiteral( "Toggle on-screen Debug panel" ) ); + toggleDebugPanel->setCheckable( true ); + QAction *configureAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "mActionOptions.svg" ) ), + QStringLiteral( "Configureā€¦" ), windowWidget ); + QDialog *configDialog = createConfigDialog( canvas ); + QObject::connect( configureAction, &QAction::triggered, windowWidget, [configDialog] + { + configDialog->setVisible( true ); + } ); + toolBar->addAction( configureAction ); + + QWidget *container = QWidget::createWindowContainer( canvas ); + container->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); + Qgs3DDebugWidget *debugWidget = new Qgs3DDebugWidget( canvas ); + debugWidget->setMapSettings( canvas->mapSettings() ); + debugWidget->setVisible( false ); + QObject::connect( canvas->mapSettings(), &Qgs3DMapSettings::showDebugPanelChanged, windowWidget, [ = ]( const bool enabled ) + { + debugWidget->setVisible( enabled ); + } ); + + // Connect the camera to the debug widget. + QObject::connect( canvas->cameraController(), &QgsCameraController::cameraChanged, debugWidget, &Qgs3DDebugWidget::updateFromCamera ); + QObject::connect( canvas->cameraController()->camera(), &Qt3DRender::QCamera::nearPlaneChanged, debugWidget, &Qgs3DDebugWidget::updateFromCamera ); + QObject::connect( canvas->cameraController()->camera(), &Qt3DRender::QCamera::farPlaneChanged, debugWidget, &Qgs3DDebugWidget::updateFromCamera ); + QObject::connect( toggleDebugPanel, &QAction::toggled, windowWidget, [ = ]( const bool enabled ) + { + debugWidget->setVisible( enabled ); + } ); + + // construct the layout of sandbox + QVBoxLayout *vLayout = new QVBoxLayout; + vLayout->setContentsMargins( 0, 0, 0, 0 ); + vLayout->setSpacing( 0 ); + vLayout->addWidget( toolBar ); + QHBoxLayout *hLayout = new QHBoxLayout; + vLayout->addLayout( hLayout ); + hLayout->setContentsMargins( 0, 0, 0, 0 ); + hLayout->addWidget( container ); + hLayout->addWidget( debugWidget ); + + + windowWidget->resize( 800, debugWidget->height() ); + windowWidget->setLayout( vLayout ); + windowWidget->show(); return myApp.exec(); }