diff --git a/Shared/LocationController.cpp b/Shared/LocationController.cpp index 0f70ba20..5ae71898 100644 --- a/Shared/LocationController.cpp +++ b/Shared/LocationController.cpp @@ -31,6 +31,7 @@ // C++ API headers #include "GraphicsOverlay.h" #include "ModelSceneSymbol.h" +#include "PictureMarkerSymbol.h" #include "Point.h" #include "SceneQuickView.h" #include "SimpleRenderer.h" @@ -108,7 +109,6 @@ void LocationController::initPositionInfoSource() m_lastKnownHeading = heading; emit headingChanged(heading); - emit relativeHeadingChanged(heading - m_lastViewHeading); }); } else @@ -358,25 +358,6 @@ void LocationController::setGpxFilePath(const QString& gpxFilePath) emit propertyChanged(GPX_FILE_PROPERTYNAME, m_gpxFilePath); } -/*! - \brief Sets the \a sceneView to use for relative heading changes. - */ -void LocationController::setRelativeHeadingSceneView(SceneQuickView* sceneView) -{ - connect(sceneView, &SceneQuickView::viewpointChanged, this, [this, sceneView]() - { - const auto sceneViewHeading = sceneView->currentViewpointCamera().heading(); - if (std::abs(m_lastViewHeading - sceneViewHeading) < 0.1) - return; - - m_lastViewHeading = sceneViewHeading; - - // keep the orientation correct if we're not doing any updates - if (!m_enabled) - emit relativeHeadingChanged(m_lastKnownHeading + m_lastViewHeading); - }); -} - /*! \internal */ @@ -388,17 +369,13 @@ void LocationController::updateGeoView() geoView->graphicsOverlays()->append(m_locationDisplay3d->locationOverlay()); constexpr float symbolSize = 25.0; - constexpr double rangeMultiplier = 1.04; // the closer to 1.0, the smoother the transitions - constexpr double maxRange = 10000000.0; - - const QUrl modelPath = modelSymbolPath(); - ModelSceneSymbol* modelSceneSymbol = new ModelSceneSymbol(modelPath, this); - modelSceneSymbol->setWidth(symbolSize); - modelSceneSymbol->setDepth(symbolSize); - modelSceneSymbol->setSymbolSizeUnits(SymbolSizeUnits::DIPs); - - m_locationDisplay3d->setDefaultSymbol(modelSceneSymbol); + auto pictureMarkerSymbol = new PictureMarkerSymbol(iconImage(), this); + pictureMarkerSymbol->setWidth(symbolSize); + pictureMarkerSymbol->setHeight(symbolSize); + pictureMarkerSymbol->setRotationType(RotationType::Geographic); + pictureMarkerSymbol->setAngleAlignment(SymbolAngleAlignment::Map); + m_locationDisplay3d->setDefaultSymbol(pictureMarkerSymbol); } } @@ -415,47 +392,14 @@ void LocationController::setIconDataPath(const QString& dataPath) } /*! - \brief Returns the URL of the model symbol used for location display. + \brief Returns the QImage of the navigation icon used for location display. */ -QUrl LocationController::modelSymbolPath() const +QImage LocationController::iconImage() const { - // both files are needed: LocationDisplay.dae - // and navigation.png and both must be local (not resources) - QString modelPath = m_iconDataPath + "/LocationDisplay.dae"; - QString imagePath = m_iconDataPath + "/navigation.png"; - - if (QFile::exists(modelPath) && QFile::exists(imagePath)) - return QUrl::fromLocalFile(modelPath); - - const QString tempPath = QDir::tempPath(); - modelPath = tempPath + "/LocationDisplay.dae"; - imagePath = tempPath + "/navigation.png"; - - // check if we've already copied them to temp - if (QFile::exists(modelPath) && QFile::exists(imagePath)) - return QUrl::fromLocalFile(modelPath); - - // if they're not both available, save both from resources to temp - // and access from there - QFile modelResource(":Resources/LocationDisplay.dae"); - QFile imageResource(":Resources/icons/xhdpi/navigation.png"); - - modelResource.open(QIODevice::ReadOnly); - imageResource.open(QIODevice::ReadOnly); + const QString imagePath = m_iconDataPath + "/navigation.png"; - QFile modelFileTemp(modelPath); - QFile imageFileTemp(imagePath); - - modelFileTemp.open(QIODevice::WriteOnly); - imageFileTemp.open(QIODevice::WriteOnly); - - modelFileTemp.write(modelResource.readAll()); - imageFileTemp.write(imageResource.readAll()); - - for (QFile* file : { &modelResource, &imageResource, &modelFileTemp, &imageFileTemp }) - file->close(); - - return QUrl::fromLocalFile(modelPath); + return (QFile::exists(imagePath)) ? QImage(imagePath) + : QImage(":Resources/icons/xhdpi/navigation.png"); } } // Dsa @@ -498,4 +442,3 @@ QUrl LocationController::modelSymbolPath() const An \a errorMessage and \a additionalMessage are passed through as parameters, describing the error that occurred. */ - diff --git a/Shared/LocationController.h b/Shared/LocationController.h index a2bff154..b0ce39ad 100644 --- a/Shared/LocationController.h +++ b/Shared/LocationController.h @@ -79,14 +79,6 @@ class LocationController : public Esri::ArcGISRuntime::Toolkit::AbstractTool QString iconDataPath() const { return m_iconDataPath; } void setIconDataPath(const QString& dataPath); - // if using GraphicsRenderingMode::Dynamic for rendering, then we need to massage - // the heading value to make sure it's correct when the scene is rotated. - // Set the sceneView here and connect to relativeHeadingChanged and that will - // be handled automatically. - // Note: this is only needed for PictureMarkerSymbol. ModelSceneSybol already - // takes this into account - void setRelativeHeadingSceneView(Esri::ArcGISRuntime::SceneQuickView* sceneView); - signals: void locationChanged(const Esri::ArcGISRuntime::Point& newLocation); void headingChanged(double newHeading); @@ -96,23 +88,19 @@ class LocationController : public Esri::ArcGISRuntime::Toolkit::AbstractTool void simulationEnabledChanged(); void toolErrorOccurred(const QString& errorMessage, const QString& additionalMessage); - // see setRelativeHeadingSceneView - void relativeHeadingChanged(double relativeHeading); - private slots: void updateGeoView(); private: void initPositionInfoSource(); void clearPositionInfoSource(); - QUrl modelSymbolPath() const; + QImage iconImage() const; QGeoPositionInfoSource* m_positionSource = nullptr; QCompass* m_compass = nullptr; LocationDisplay3d* m_locationDisplay3d = nullptr; bool m_enabled = false; bool m_simulated = false; - double m_lastViewHeading = 0.0; double m_lastKnownHeading = 0.0; Esri::ArcGISRuntime::Point m_currentLocation; QString m_gpxFilePath; diff --git a/Shared/LocationDisplay3d.cpp b/Shared/LocationDisplay3d.cpp index 9167a0a9..f365b6fa 100644 --- a/Shared/LocationDisplay3d.cpp +++ b/Shared/LocationDisplay3d.cpp @@ -24,6 +24,7 @@ // C++ API headers #include "GraphicsOverlay.h" +#include "PictureMarkerSymbol.h" #include "SimpleRenderer.h" // Qt headers @@ -36,8 +37,6 @@ using namespace Esri::ArcGISRuntime; namespace Dsa { -static const QString s_headingAttribute{"heading"}; - /*! \class Dsa::LocationDisplay3d \inmodule Dsa @@ -57,11 +56,9 @@ LocationDisplay3d::LocationDisplay3d(QObject* parent) : m_locationGraphic(new Graphic(this)) { m_locationOverlay->setOverlayId(QStringLiteral("SCENEVIEWLOCATIONOVERLAY")); - m_locationOverlay->setSceneProperties(LayerSceneProperties(SurfacePlacement::Relative)); + m_locationOverlay->setSceneProperties(LayerSceneProperties(SurfacePlacement::DrapedFlat)); m_locationOverlay->setRenderingMode(GraphicsRenderingMode::Dynamic); m_locationOverlay->setVisible(false); - - m_locationGraphic->attributes()->insertAttribute(s_headingAttribute, 0.0); m_locationOverlay->graphics()->append(m_locationGraphic); } @@ -164,7 +161,7 @@ void LocationDisplay3d::setPositionSource(QGeoPositionInfoSource* positionSource m_headingConnection = connect(gpxLocationSimulator, &GPXLocationSimulator::headingChanged, this, [this](double heading) { - m_locationGraphic->attributes()->replaceAttribute(s_headingAttribute, heading); + m_defaultSymbol->setAngle(static_cast(-heading)); }); } @@ -202,7 +199,7 @@ void LocationDisplay3d::setCompass(QCompass* compass) if (!reading) return; - m_locationGraphic->attributes()->replaceAttribute(s_headingAttribute, static_cast(reading->azimuth())); + m_defaultSymbol->setAngle(static_cast(-reading->azimuth())); emit headingChanged(); }); @@ -229,7 +226,7 @@ Graphic* LocationDisplay3d::locationGraphic() const /*! \brief Returns the default symbol for the location display. */ -Symbol* LocationDisplay3d::defaultSymbol() const +PictureMarkerSymbol* LocationDisplay3d::defaultSymbol() const { return m_defaultSymbol; } @@ -237,17 +234,13 @@ Symbol* LocationDisplay3d::defaultSymbol() const /*! \brief Sets the default symbol for the location display to \a defaultSymbol. */ -void LocationDisplay3d::setDefaultSymbol(Symbol* defaultSymbol) +void LocationDisplay3d::setDefaultSymbol(PictureMarkerSymbol* defaultSymbol) { m_defaultSymbol = defaultSymbol; if (!m_locationRenderer) { m_locationRenderer = new SimpleRenderer(defaultSymbol, this); - RendererSceneProperties renderProperties = m_locationRenderer->sceneProperties(); - renderProperties.setHeadingExpression(QString("[%1]").arg(s_headingAttribute)); - m_locationRenderer->setSceneProperties(renderProperties); - m_locationOverlay->setRenderer(m_locationRenderer); } else diff --git a/Shared/LocationDisplay3d.h b/Shared/LocationDisplay3d.h index 22de8166..3dafe3c5 100644 --- a/Shared/LocationDisplay3d.h +++ b/Shared/LocationDisplay3d.h @@ -27,6 +27,7 @@ namespace Esri { namespace ArcGISRuntime { class Graphic; class GraphicsOverlay; + class PictureMarkerSymbol; class Symbol; class SimpleRenderer; }} @@ -58,8 +59,8 @@ class LocationDisplay3d : public QObject Esri::ArcGISRuntime::Graphic* locationGraphic() const; - Esri::ArcGISRuntime::Symbol* defaultSymbol() const; - void setDefaultSymbol(Esri::ArcGISRuntime::Symbol* defaultSymbol); + Esri::ArcGISRuntime::PictureMarkerSymbol* defaultSymbol() const; + void setDefaultSymbol(Esri::ArcGISRuntime::PictureMarkerSymbol* defaultSymbol); signals: void locationChanged(const Esri::ArcGISRuntime::Point& location); @@ -73,7 +74,7 @@ class LocationDisplay3d : public QObject mutable Esri::ArcGISRuntime::GraphicsOverlay* m_locationOverlay = nullptr; Esri::ArcGISRuntime::SimpleRenderer* m_locationRenderer = nullptr; Esri::ArcGISRuntime::Graphic* m_locationGraphic = nullptr; - Esri::ArcGISRuntime::Symbol* m_defaultSymbol = nullptr; + Esri::ArcGISRuntime::PictureMarkerSymbol* m_defaultSymbol = nullptr; QGeoPositionInfoSource* m_geoPositionInfoSource = nullptr; QCompass* m_compass = nullptr; Esri::ArcGISRuntime::Point m_lastKnownLocation; diff --git a/Shared/messages/MessageFeedsController.cpp b/Shared/messages/MessageFeedsController.cpp index 8aa770d8..c27f7089 100644 --- a/Shared/messages/MessageFeedsController.cpp +++ b/Shared/messages/MessageFeedsController.cpp @@ -371,7 +371,7 @@ SurfacePlacement MessageFeedsController::toSurfacePlacement(const QString& surfa if (surfacePlacement.compare("absolute", Qt::CaseInsensitive) == 0) return SurfacePlacement::Absolute; - return SurfacePlacement::DrapedFlat; // default + return SurfacePlacement::DrapedBillboarded; // default } /*! diff --git a/Shared/messages/MessagesOverlay.cpp b/Shared/messages/MessagesOverlay.cpp index dee9685c..59fbec26 100644 --- a/Shared/messages/MessagesOverlay.cpp +++ b/Shared/messages/MessagesOverlay.cpp @@ -46,7 +46,7 @@ namespace Dsa { \brief Constructor taking a \a geoView and an optional \a parent. */ MessagesOverlay::MessagesOverlay(GeoView* geoView, QObject* parent) : - MessagesOverlay(geoView, nullptr, QString(), SurfacePlacement::DrapedFlat, parent) + MessagesOverlay(geoView, nullptr, QString(), SurfacePlacement::DrapedBillboarded, parent) { }