/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquick3dparticletargetdirection_p.h"
#include "qquick3dparticlerandomizer_p.h"
#include "qquick3dparticlesystem_p.h"

QT_BEGIN_NAMESPACE

/*!
    \qmltype TargetDirection3D
    \inherits Direction3D
    \inqmlmodule QtQuick3D.Particles3D
    \brief For specifying a direction towards the target position.
    \since 6.2

    This element sets emitted particle velocity towards the target position.

    For example, to emit particles towards position (100, 0, 0) with
    random magnitude between 10..20:

    \qml
    ParticleEmitter3D {
        ...
        velocity: TargetDirection3D {
            position: Qt.vector3d(100, 0, 0)
            normalized: true
            magnitude: 15.0
            magnitudeVariation: 5.0
        }
    }
    \endqml
*/

QQuick3DParticleTargetDirection::QQuick3DParticleTargetDirection(QObject *parent)
    : QQuick3DParticleDirection(parent)
{
}

/*!
    \qmlproperty vector3d TargetDirection3D::position

    This property defines the position for particles target.

    The default value is \c (0, 0, 0) (the center of the emitter).

    \sa positionVariation
*/
QVector3D QQuick3DParticleTargetDirection::position() const
{
    return m_position;
}

/*!
    \qmlproperty vector3d TargetDirection3D::positionVariation

    This property defines the position variation for particles target.

    The default value is \c (0, 0, 0) (no variation).

    \sa position
*/
QVector3D QQuick3DParticleTargetDirection::positionVariation() const
{
    return m_positionVariation;
}

void QQuick3DParticleTargetDirection::setPosition(const QVector3D &position)
{
    if (m_position == position)
        return;

    m_position = position;
    Q_EMIT positionChanged();
}

void QQuick3DParticleTargetDirection::setPositionVariation(const QVector3D &positionVariation)
{
    if (m_positionVariation == positionVariation)
        return;

    m_positionVariation = positionVariation;
    Q_EMIT positionVariationChanged();
}

/*!
    \qmlproperty bool TargetDirection3D::normalized

    This property defines if the distance to \l position should be considered as normalized or not.
    When this is false, distance to the \l position affects the magnitude of the particles velocity.
    When set to true, distance is normalized and velocity amount comes only from \l magnitude and
    \l magnitudeVariation.

    The default value is \c false.

    \sa magnitude, magnitudeVariation
*/
bool QQuick3DParticleTargetDirection::normalized() const
{
    return m_normalized;
}

void QQuick3DParticleTargetDirection::setNormalized(bool normalized)
{
    if (m_normalized == normalized)
        return;

    m_normalized = normalized;
    Q_EMIT normalizedChanged();
}

/*!
    \qmlproperty real TargetDirection3D::magnitude

    This property defines the magnitude in position change per second. Negative magnitude
    accelerates the opposite way from the \l {TargetDirection3D::position}{position}.
    When the \l normalized is false, this is multiplied with the distance to the target position.

    The default value is \c 1.0.

    \sa magnitudeVariation
*/
float QQuick3DParticleTargetDirection::magnitude() const
{
    return m_magnitude;
}

void QQuick3DParticleTargetDirection::setMagnitude(float magnitude)
{
    if (qFuzzyCompare(m_magnitude, magnitude))
        return;

    m_magnitude = magnitude;
    Q_EMIT magnitudeChanged();
}

/*!
    \qmlproperty real TargetDirection3D::magnitudeVariation

    This property defines the magnitude variation in position change per second.
    When the \l normalized is false, this is multiplied with the distance to the target position.

    The default value is \c 0.0.

    \sa magnitude
*/
float QQuick3DParticleTargetDirection::magnitudeVariation() const
{
    return m_magnitudeVariation;
}

void QQuick3DParticleTargetDirection::setMagnitudeVariation(float magnitudeVariation)
{
    if (qFuzzyCompare(m_magnitudeVariation, magnitudeVariation))
        return;

    m_magnitudeVariation = magnitudeVariation;
    Q_EMIT magnitudeChangedVariation();
}

QVector3D QQuick3DParticleTargetDirection::sample(const QQuick3DParticleData &d)
{
    QVector3D ret = m_position - d.startPosition;
    if (!m_system)
        return ret;
    auto rand = m_system->rand();

    ret.setX(ret.x() - m_positionVariation.x() + rand->get(d.index, QPRand::TDirPosXV) * m_positionVariation.x() * 2.0f);
    ret.setY(ret.y() - m_positionVariation.y() + rand->get(d.index, QPRand::TDirPosYV) * m_positionVariation.y() * 2.0f);
    ret.setZ(ret.z() - m_positionVariation.z() + rand->get(d.index, QPRand::TDirPosZV) * m_positionVariation.z() * 2.0f);
    if (m_normalized)
        ret.normalize();
    ret *= (m_magnitude - m_magnitudeVariation + rand->get(d.index, QPRand::TDirMagV) * m_magnitudeVariation * 2.0f);
    return ret;
}

QT_END_NAMESPACE
