aboutsummaryrefslogtreecommitdiffstats
path: root/src/particles/qquicktargetdirection.cpp
blob: e650e50b6c015a3656e5669c680602410b81d5ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "qquicktargetdirection_p.h"
#include "qquickparticleemitter_p.h"
#include <cmath>
#include <QDebug>
#include <QRandomGenerator>

QT_BEGIN_NAMESPACE
/*!
    \qmltype TargetDirection
    \instantiates QQuickTargetDirection
    \inqmlmodule QtQuick.Particles
    \ingroup qtquick-particles
    \inherits Direction
    \brief For specifying a direction towards the target point.

*/
/*!
    \qmlproperty real QtQuick.Particles::TargetDirection::targetX
*/
/*!
    \qmlproperty real QtQuick.Particles::TargetDirection::targetY
*/
/*!
    \qmlproperty Item QtQuick.Particles::TargetDirection::targetItem
    If specified, this will take precedence over targetX and targetY.
    The targeted point will be the center of the specified Item
*/
/*!
    \qmlproperty real QtQuick.Particles::TargetDirection::targetVariation
*/
/*!
    \qmlproperty real QtQuick.Particles::TargetDirection::magnitude
*/
/*!
    \qmlproperty real QtQuick.Particles::TargetDirection::magnitudeVariation
*/
/*!
    \qmlproperty bool QtQuick.Particles::TargetDirection::proportionalMagnitude

    If true, then the value of magnitude and magnitudeVariation shall be interpreted as multiples
    of the distance between the source point and the target point, per second.

    If false(default), then the value of magnitude and magnitudeVariation shall be interpreted as
    pixels per second.
*/

QQuickTargetDirection::QQuickTargetDirection(QObject *parent) :
    QQuickDirection(parent)
  , m_targetX(0)
  , m_targetY(0)
  , m_targetVariation(0)
  , m_proportionalMagnitude(false)
  , m_magnitude(0)
  , m_magnitudeVariation(0)
  , m_targetItem(nullptr)
{
}

QPointF QQuickTargetDirection::sample(const QPointF &from)
{
    //###This approach loses interpolating the last position of the target (like we could with the emitter) is it worthwhile?
    QPointF ret;
    qreal targetX;
    qreal targetY;
    if (m_targetItem){
        QQuickParticleEmitter* parentEmitter = qobject_cast<QQuickParticleEmitter*>(parent());
        targetX = m_targetItem->width()/2;
        targetY = m_targetItem->height()/2;
        if (!parentEmitter){
            qWarning() << "Directed vector is not a child of the emitter. Mapping of target item coordinates may fail.";
            targetX += m_targetItem->x();
            targetY += m_targetItem->y();
        }else{
            ret = parentEmitter->mapFromItem(m_targetItem, QPointF(targetX, targetY));
            targetX = ret.x();
            targetY = ret.y();
        }
    }else{
        targetX = m_targetX;
        targetY = m_targetY;
    }
    targetX += 0 - from.x() - m_targetVariation + QRandomGenerator::global()->generateDouble() * m_targetVariation*2;
    targetY += 0 - from.y() - m_targetVariation + QRandomGenerator::global()->generateDouble() * m_targetVariation*2;
    qreal theta = std::atan2(targetY, targetX);
    qreal mag = m_magnitude + QRandomGenerator::global()->generateDouble() * m_magnitudeVariation * 2 - m_magnitudeVariation;
    if (m_proportionalMagnitude)
        mag *= qHypot(targetX, targetY);
    ret.setX(mag * std::cos(theta));
    ret.setY(mag * std::sin(theta));
    return ret;
}

QT_END_NAMESPACE

#include "moc_qquicktargetdirection_p.cpp"