aboutsummaryrefslogtreecommitdiffstats
path: root/src/particles/qquickwander.cpp
blob: 648a2e409717ead49896c9ab18353fb4c610fd19 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// 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 "qquickwander_p.h"
#include "qquickparticlesystem_p.h"//for ParticlesVertices
#include <QRandomGenerator>
QT_BEGIN_NAMESPACE
/*!
    \qmltype Wander
    \instantiates QQuickWanderAffector
    \inqmlmodule QtQuick.Particles
    \ingroup qtquick-particles
    \inherits Affector
    \brief For applying random particle trajectory.

*/
/*!
    \qmlproperty real QtQuick.Particles::Wander::pace

    Maximum attribute change per second.
*/
/*!
    \qmlproperty real QtQuick.Particles::Wander::xVariance

    Maximum attribute x value (as a result of Wander).

    If unset, Wander will not affect x values.
*/
/*!
    \qmlproperty real QtQuick.Particles::Wander::yVariance

    Maximum attribute y value (as a result of Wander).

    If unset, Wander will not affect y values.
*/
/*!
    \qmlproperty AffectableParameter QtQuick.Particles::Wander::affectedParameter

    What attribute of particles is directly affected.
    \list
    \li PointAttractor.Position
    \li PointAttractor.Velocity
    \li PointAttractor.Acceleration
    \endlist
*/

QQuickWanderAffector::QQuickWanderAffector(QQuickItem *parent) :
    QQuickParticleAffector(parent), m_xVariance(0), m_yVariance(0), m_pace(0)
    , m_affectedParameter(Velocity)
{
    m_needsReset = true;
}

QQuickWanderAffector::~QQuickWanderAffector()
{
    for (QHash<int, WanderData*>::const_iterator iter=m_wanderData.constBegin();
        iter != m_wanderData.constEnd(); ++iter)
        delete (*iter);
}

WanderData* QQuickWanderAffector::getData(int idx)
{
    if (m_wanderData.contains(idx))
        return m_wanderData[idx];
    WanderData* d = new WanderData;
    d->x_vel = 0;
    d->y_vel = 0;
    d->x_peak = m_xVariance;
    d->y_peak = m_yVariance;
    d->x_var = m_pace * QRandomGenerator::global()->generateDouble();
    d->y_var = m_pace * QRandomGenerator::global()->generateDouble();

    m_wanderData.insert(idx, d);
    return d;
}

// TODO: see below
//void QQuickWanderAffector::reset(int systemIdx)
//{
//    if (m_wanderData.contains(systemIdx))
//        delete m_wanderData[systemIdx];
//    m_wanderData.remove(systemIdx);
//}

bool QQuickWanderAffector::affectParticle(QQuickParticleData* data, qreal dt)
{
    /*TODO: Add a mode which does basically this - picking a direction, going in it (random velocity) and then going back
    WanderData* d = getData(data->systemIndex);
    if (m_xVariance != 0.) {
        if ((d->x_vel > d->x_peak && d->x_var > 0.0) || (d->x_vel < -d->x_peak && d->x_var < 0.0)) {
            d->x_var = -d->x_var;
            d->x_peak = m_xVariance + m_xVariance * QRandomGenerator::global()->generateDouble();
        }
        d->x_vel += d->x_var * dt;
    }
    qreal dx = dt * d->x_vel;

    if (m_yVariance != 0.) {
        if ((d->y_vel > d->y_peak && d->y_var > 0.0) || (d->y_vel < -d->y_peak && d->y_var < 0.0)) {
            d->y_var = -d->y_var;
            d->y_peak = m_yVariance + m_yVariance * QRandomGenerator::global()->generateDouble();
        }
        d->y_vel += d->y_var * dt;
    }
    qreal dy = dt * d->x_vel;

    //### Should we be amending vel instead?
    ParticleVertex* p = &(data->pv);
    p->x += dx;

    p->y += dy;
    return true;
    */
    qreal dx = dt * m_pace * (2 * QRandomGenerator::global()->generateDouble() - 1);
    qreal dy = dt * m_pace * (2 * QRandomGenerator::global()->generateDouble() - 1);
    qreal newX, newY;
    switch (m_affectedParameter){
    case Position:
        newX = data->curX(m_system) + dx;
        if (m_xVariance > qAbs(newX) )
            data->x += dx;
        newY = data->curY(m_system) + dy;
        if (m_yVariance > qAbs(newY) )
            data->y += dy;
        break;
    default:
    case Velocity:
        newX = data->curVX(m_system) + dx;
        if (m_xVariance > qAbs(newX))
            data->setInstantaneousVX(newX, m_system);
        newY = data->curVY(m_system) + dy;
        if (m_yVariance > qAbs(newY))
            data->setInstantaneousVY(newY, m_system);
        break;
    case Acceleration:
        newX = data->ax + dx;
        if (m_xVariance > qAbs(newX))
            data->setInstantaneousAX(newX, m_system);
        newY = data->ay + dy;
        if (m_yVariance > qAbs(newY))
            data->setInstantaneousAY(newY, m_system);
        break;
    }
    return true;
}
QT_END_NAMESPACE

#include "moc_qquickwander_p.cpp"