mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
profile: move axis animation code to ProfileView
This feels quite a bit slower than the non-QtQuick version. This makes sense, as there is an additional level of indirection. Instead of painting directly, we paint into an QImage and turn that into a QSGTexture. Ultimately one would think that we should render directly using QtQuick. Alas, we can't, since that would mean no more printing/ exporting of profiles. How sad. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
15ea0440ad
commit
196a33ba4b
4 changed files with 58 additions and 49 deletions
|
@ -19,37 +19,9 @@
|
||||||
#include "core/subsurface-string.h"
|
#include "core/subsurface-string.h"
|
||||||
#include "core/settings/qPrefDisplay.h"
|
#include "core/settings/qPrefDisplay.h"
|
||||||
#include "qt-models/diveplannermodel.h"
|
#include "qt-models/diveplannermodel.h"
|
||||||
#include <QAbstractAnimation>
|
|
||||||
|
|
||||||
static const double diveComputerTextBorder = 1.0;
|
static const double diveComputerTextBorder = 1.0;
|
||||||
|
|
||||||
// Class for animations (if any). Might want to do our own.
|
|
||||||
class ProfileAnimation : public QAbstractAnimation {
|
|
||||||
ProfileScene &scene;
|
|
||||||
// For historical reasons, speed is actually the duration
|
|
||||||
// (i.e. the reciprocal of speed). Ouch, that hurts.
|
|
||||||
int speed;
|
|
||||||
|
|
||||||
int duration() const override
|
|
||||||
{
|
|
||||||
return speed;
|
|
||||||
}
|
|
||||||
void updateCurrentTime(int time) override
|
|
||||||
{
|
|
||||||
// Note: we explicitly pass 1.0 at the end, so that
|
|
||||||
// the callee can do a simple float comparison for "end".
|
|
||||||
scene.anim(time == speed ? 1.0
|
|
||||||
: static_cast<double>(time) / speed);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
ProfileAnimation(ProfileScene &scene, int animSpeed) :
|
|
||||||
scene(scene),
|
|
||||||
speed(animSpeed)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, class... Args>
|
template<typename T, class... Args>
|
||||||
T *ProfileScene::createItem(const DiveCartesianAxis &vAxis, DataAccessor accessor, int z, Args&&... args)
|
T *ProfileScene::createItem(const DiveCartesianAxis &vAxis, DataAccessor accessor, int z, Args&&... args)
|
||||||
{
|
{
|
||||||
|
@ -404,8 +376,8 @@ static double max_gas(const plot_info &pi, double gas_pressures::*gas)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsModel *plannerModel,
|
void ProfileScene::plotDive(const struct dive *dIn, int dcIn, int animSpeed, DivePlannerPointsModel *plannerModel,
|
||||||
bool inPlanner, bool instant, bool keepPlotInfo, bool calcMax, double zoom, double zoomedPosition)
|
bool inPlanner, bool keepPlotInfo, bool calcMax, double zoom, double zoomedPosition)
|
||||||
{
|
{
|
||||||
d = dIn;
|
d = dIn;
|
||||||
dc = dcIn;
|
dc = dcIn;
|
||||||
|
@ -439,8 +411,6 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
|
||||||
keepPlotInfo = false;
|
keepPlotInfo = false;
|
||||||
empty = false;
|
empty = false;
|
||||||
|
|
||||||
int animSpeed = instant || printMode ? 0 : qPrefDisplay::animation_speed();
|
|
||||||
|
|
||||||
// A non-null planner_ds signals to create_plot_info_new that the dive is currently planned.
|
// A non-null planner_ds signals to create_plot_info_new that the dive is currently planned.
|
||||||
struct deco_state *planner_ds = inPlanner && plannerModel ? &plannerModel->final_deco_state : nullptr;
|
struct deco_state *planner_ds = inPlanner && plannerModel ? &plannerModel->final_deco_state : nullptr;
|
||||||
|
|
||||||
|
@ -589,12 +559,6 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
|
||||||
if (nr > 1)
|
if (nr > 1)
|
||||||
dcText += tr(" (#%1 of %2)").arg(dc + 1).arg(nr);
|
dcText += tr(" (#%1 of %2)").arg(dc + 1).arg(nr);
|
||||||
diveComputerText->set(dcText, getColor(TIME_TEXT, isGrayscale));
|
diveComputerText->set(dcText, getColor(TIME_TEXT, isGrayscale));
|
||||||
|
|
||||||
// Reset animation.
|
|
||||||
if (animSpeed <= 0)
|
|
||||||
animation.reset();
|
|
||||||
else
|
|
||||||
animation = std::make_unique<ProfileAnimation>(*this, animSpeed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileScene::anim(double fraction)
|
void ProfileScene::anim(double fraction)
|
||||||
|
@ -609,7 +573,7 @@ void ProfileScene::draw(QPainter *painter, const QRect &pos,
|
||||||
{
|
{
|
||||||
QSize size = pos.size();
|
QSize size = pos.size();
|
||||||
resize(QSizeF(size));
|
resize(QSizeF(size));
|
||||||
plotDive(d, dc, plannerModel, inPlanner, true, false, true);
|
plotDive(d, dc, 0, plannerModel, inPlanner, false, true);
|
||||||
|
|
||||||
QImage image(pos.size(), QImage::Format_ARGB32);
|
QImage image(pos.size(), QImage::Format_ARGB32);
|
||||||
image.fill(getColor(::BACKGROUND, isGrayscale));
|
image.fill(getColor(::BACKGROUND, isGrayscale));
|
||||||
|
|
|
@ -27,7 +27,6 @@ class DiveReportedCeiling;
|
||||||
class DiveTemperatureItem;
|
class DiveTemperatureItem;
|
||||||
class DiveTextItem;
|
class DiveTextItem;
|
||||||
class PartialPressureGasItem;
|
class PartialPressureGasItem;
|
||||||
class ProfileAnimation;
|
|
||||||
class TankItem;
|
class TankItem;
|
||||||
|
|
||||||
class ProfileScene : public QGraphicsScene {
|
class ProfileScene : public QGraphicsScene {
|
||||||
|
@ -42,8 +41,8 @@ public:
|
||||||
// Can be compared with literal 1.0 to determine "end" state.
|
// Can be compared with literal 1.0 to determine "end" state.
|
||||||
|
|
||||||
// If a plannerModel is passed, the deco-information is taken from there.
|
// If a plannerModel is passed, the deco-information is taken from there.
|
||||||
void plotDive(const struct dive *d, int dc, DivePlannerPointsModel *plannerModel = nullptr, bool inPlanner = false,
|
void plotDive(const struct dive *d, int dc, int animSpeed, DivePlannerPointsModel *plannerModel = nullptr, bool inPlanner = false,
|
||||||
bool instant = false, bool keepPlotInfo = false, bool calcMax = true, double zoom = 1.0, double zoomedPosition = 0.0);
|
bool keepPlotInfo = false, bool calcMax = true, double zoom = 1.0, double zoomedPosition = 0.0);
|
||||||
|
|
||||||
void draw(QPainter *painter, const QRect &pos,
|
void draw(QPainter *painter, const QRect &pos,
|
||||||
const struct dive *d, int dc,
|
const struct dive *d, int dc,
|
||||||
|
@ -61,7 +60,6 @@ private:
|
||||||
void updateVisibility(bool diveHasHeartBeat, bool simplified); // Update visibility of non-interactive chart features according to preferences
|
void updateVisibility(bool diveHasHeartBeat, bool simplified); // Update visibility of non-interactive chart features according to preferences
|
||||||
void updateAxes(bool diveHasHeartBeat, bool simplified); // Update axes according to preferences
|
void updateAxes(bool diveHasHeartBeat, bool simplified); // Update axes according to preferences
|
||||||
|
|
||||||
friend class ProfileWidget2; // For now, give the ProfileWidget full access to the objects on the scene
|
|
||||||
double dpr; // Device Pixel Ratio. A DPR of one corresponds to a "standard" PC screen.
|
double dpr; // Device Pixel Ratio. A DPR of one corresponds to a "standard" PC screen.
|
||||||
bool printMode;
|
bool printMode;
|
||||||
bool isGrayscale;
|
bool isGrayscale;
|
||||||
|
@ -101,7 +99,6 @@ private:
|
||||||
DivePercentageItem *percentageItem;
|
DivePercentageItem *percentageItem;
|
||||||
TankItem *tankItem;
|
TankItem *tankItem;
|
||||||
std::shared_ptr<const DivePixmaps> pixmaps;
|
std::shared_ptr<const DivePixmaps> pixmaps;
|
||||||
std::unique_ptr<ProfileAnimation> animation;
|
|
||||||
std::vector<DiveCartesianAxis *> animatedAxes;
|
std::vector<DiveCartesianAxis *> animatedAxes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,40 @@
|
||||||
#include "core/errorhelper.h"
|
#include "core/errorhelper.h"
|
||||||
#include "core/pref.h"
|
#include "core/pref.h"
|
||||||
#include "core/settings/qPrefTechnicalDetails.h"
|
#include "core/settings/qPrefTechnicalDetails.h"
|
||||||
|
#include "core/settings/qPrefDisplay.h"
|
||||||
#include "qt-quick/chartitem.h"
|
#include "qt-quick/chartitem.h"
|
||||||
|
|
||||||
|
#include <QAbstractAnimation>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
// Class for animations (if any). Might want to do our own.
|
||||||
|
class ProfileAnimation : public QAbstractAnimation {
|
||||||
|
ProfileView &view;
|
||||||
|
// For historical reasons, speed is actually the duration
|
||||||
|
// (i.e. the reciprocal of speed). Ouch, that hurts.
|
||||||
|
int speed;
|
||||||
|
|
||||||
|
int duration() const override
|
||||||
|
{
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
void updateCurrentTime(int time) override
|
||||||
|
{
|
||||||
|
// Note: we explicitly pass 1.0 at the end, so that
|
||||||
|
// the callee can do a simple float comparison for "end".
|
||||||
|
view.anim(time == speed ? 1.0
|
||||||
|
: static_cast<double>(time) / speed);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
ProfileAnimation(ProfileView &view, int animSpeed) :
|
||||||
|
view(view),
|
||||||
|
speed(animSpeed)
|
||||||
|
{
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static double calcZoom(int zoomLevel)
|
static double calcZoom(int zoomLevel)
|
||||||
{
|
{
|
||||||
// Base of exponential zoom function: one wheel-click will increase the zoom by 15%.
|
// Base of exponential zoom function: one wheel-click will increase the zoom by 15%.
|
||||||
|
@ -97,16 +126,16 @@ void ProfileView::plotDive(const struct dive *dIn, int dcIn, int flags)
|
||||||
DivePlannerPointsModel *model = nullptr;
|
DivePlannerPointsModel *model = nullptr;
|
||||||
bool inPlanner = flags & RenderFlags::PlanMode;
|
bool inPlanner = flags & RenderFlags::PlanMode;
|
||||||
|
|
||||||
QColor backgroundColor = inPlanner ? QColor("#D7E3EF")
|
|
||||||
: getColor(::BACKGROUND, false);
|
|
||||||
|
|
||||||
double zoom = calcZoom(zoomLevel);
|
double zoom = calcZoom(zoomLevel);
|
||||||
|
|
||||||
|
int animSpeed = flags & RenderFlags::Instant ? 0 : qPrefDisplay::animation_speed();
|
||||||
|
|
||||||
profileScene->resize(size());
|
profileScene->resize(size());
|
||||||
profileScene->plotDive(d, dc, model, inPlanner, true, //flags & RenderFlags::Instant,
|
profileScene->plotDive(d, dc, animSpeed, model, inPlanner,
|
||||||
flags & RenderFlags::DontRecalculatePlotInfo,
|
flags & RenderFlags::DontRecalculatePlotInfo,
|
||||||
shouldCalculateMax, zoom, zoomedPosition);
|
shouldCalculateMax, zoom, zoomedPosition);
|
||||||
profileItem->draw(size(), backgroundColor, *profileScene);
|
background = inPlanner ? QColor("#D7E3EF") : getColor(::BACKGROUND, false);
|
||||||
|
profileItem->draw(size(), background, *profileScene);
|
||||||
|
|
||||||
//rulerItem->setVisible(prefs.rulergraph && currentState != PLAN && currentState != EDIT);
|
//rulerItem->setVisible(prefs.rulergraph && currentState != PLAN && currentState != EDIT);
|
||||||
//toolTipItem->setPlotInfo(profileScene->plotInfo);
|
//toolTipItem->setPlotInfo(profileScene->plotInfo);
|
||||||
|
@ -136,4 +165,19 @@ void ProfileView::plotDive(const struct dive *dIn, int dcIn, int flags)
|
||||||
qPrefTechnicalDetails::set_calcndltts(false);
|
qPrefTechnicalDetails::set_calcndltts(false);
|
||||||
report_error("%s", qPrintable(tr("Show NDL / TTS was disabled because of excessive processing time")));
|
report_error("%s", qPrintable(tr("Show NDL / TTS was disabled because of excessive processing time")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset animation.
|
||||||
|
if (animSpeed <= 0)
|
||||||
|
animation.reset();
|
||||||
|
else
|
||||||
|
animation = std::make_unique<ProfileAnimation>(*this, animSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileView::anim(double fraction)
|
||||||
|
{
|
||||||
|
if (!profileScene || !profileItem)
|
||||||
|
return;
|
||||||
|
profileScene->anim(fraction);
|
||||||
|
profileItem->draw(size(), background, *profileScene);
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class ChartGraphicsSceneItem;
|
class ChartGraphicsSceneItem;
|
||||||
|
class ProfileAnimation;
|
||||||
class ProfileScene;
|
class ProfileScene;
|
||||||
|
|
||||||
class ProfileView : public ChartView {
|
class ProfileView : public ChartView {
|
||||||
|
@ -25,6 +26,7 @@ public:
|
||||||
|
|
||||||
void plotDive(const struct dive *d, int dc, int flags = RenderFlags::None);
|
void plotDive(const struct dive *d, int dc, int flags = RenderFlags::None);
|
||||||
void clear();
|
void clear();
|
||||||
|
void anim(double fraction);
|
||||||
private:
|
private:
|
||||||
const struct dive *d;
|
const struct dive *d;
|
||||||
int dc;
|
int dc;
|
||||||
|
@ -32,8 +34,10 @@ private:
|
||||||
double zoomedPosition; // Position when zoomed: 0.0 = beginning, 1.0 = end.
|
double zoomedPosition; // Position when zoomed: 0.0 = beginning, 1.0 = end.
|
||||||
bool empty; // No dive shown.
|
bool empty; // No dive shown.
|
||||||
bool shouldCalculateMax; // Calculate maximum time and depth (default). False when dragging handles.
|
bool shouldCalculateMax; // Calculate maximum time and depth (default). False when dragging handles.
|
||||||
|
QColor background;
|
||||||
std::unique_ptr<ProfileScene> profileScene;
|
std::unique_ptr<ProfileScene> profileScene;
|
||||||
ChartItemPtr<ChartGraphicsSceneItem> profileItem;
|
ChartItemPtr<ChartGraphicsSceneItem> profileItem;
|
||||||
|
std::unique_ptr<ProfileAnimation> animation;
|
||||||
|
|
||||||
void plotAreaChanged(const QSizeF &size) override;
|
void plotAreaChanged(const QSizeF &size) override;
|
||||||
void resetPointers() override;
|
void resetPointers() override;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue