// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QQUICK3DPPARTICLESYSTEM_H #define QQUICK3DPPARTICLESYSTEM_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QQuick3DParticleSpriteParticle; class QQuick3DParticleModelParticle; class QQuick3DParticleModelBlendParticle; class QQuick3DParticleEmitter; class QQuick3DParticleTrailEmitter; class QQuick3DParticleAffector; class QQuick3DParticleStatelessAffector; class QQuick3DParticle; class QQuick3DParticleSystemAnimation; class QQuick3DParticleSystemUpdate; class QQuick3DParticleInstanceTable; class Q_QUICK3DPARTICLES_EXPORT QQuick3DParticleSystem : public QQuick3DNode { Q_OBJECT Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged) Q_PROPERTY(int time READ time WRITE setTime NOTIFY timeChanged) Q_PROPERTY(bool useRandomSeed READ useRandomSeed WRITE setUseRandomSeed NOTIFY useRandomSeedChanged) Q_PROPERTY(int seed READ seed WRITE setSeed NOTIFY seedChanged) Q_PROPERTY(bool logging READ logging WRITE setLogging NOTIFY loggingChanged) Q_PROPERTY(QQuick3DParticleSystemLogging *loggingData READ loggingData NOTIFY loggingDataChanged) QML_NAMED_ELEMENT(ParticleSystem3D) QML_ADDED_IN_VERSION(6, 2) public: QQuick3DParticleSystem(QQuick3DNode *parent = nullptr); ~QQuick3DParticleSystem() override; bool isRunning() const; bool isPaused() const; int startTime() const; int time() const; bool useRandomSeed() const; int seed() const; // Return the total amount of particles int particleCount() const; bool logging() const; QQuick3DParticleSystemLogging *loggingData() const; // Registering of different components into system void registerParticle(QQuick3DParticle *particle); void unRegisterParticle(QQuick3DParticle *particle); void registerParticleEmitter(QQuick3DParticleEmitter* e); void unRegisterParticleEmitter(QQuick3DParticleEmitter* e); void registerParticleAffector(QQuick3DParticleAffector* a); void unRegisterParticleAffector(QQuick3DParticleAffector* a); void updateCurrentTime(int currentTime); QPRand *rand(); bool isShared(const QQuick3DParticle *particle) const; int currentTime() const; struct TrailEmits { QQuick3DParticleTrailEmitter *emitter = nullptr; int amount = 0; }; Q_INVOKABLE void reset(); public Q_SLOTS: void setRunning(bool running); void setPaused(bool paused); void setStartTime(int startTime); void setTime(int time); void setUseRandomSeed(bool randomize); void setSeed(int seed); void setLogging(bool logging); void setEditorTime(int time); Q_SIGNALS: void runningChanged(); void pausedChanged(); void timeChanged(); void startTimeChanged(); void useRandomSeedChanged(); void seedChanged(); void loggingChanged(); void loggingDataChanged(); protected: void componentComplete() override; private: void registerParticleModel(QQuick3DParticleModelParticle* m); void registerParticleSprite(QQuick3DParticleSpriteParticle* m); void updateLoggingData(); void resetLoggingVariables(); void doSeedRandomization(); void refresh(); void markDirty(); void processModelParticle(QQuick3DParticleModelParticle *modelParticle, const QVector &trailEmits, float timeS); void processSpriteParticle(QQuick3DParticleSpriteParticle *spriteParticle, const QVector &trailEmits, float timeS); void processModelBlendParticle(QQuick3DParticleModelBlendParticle *particle, const QVector &trailEmits, float timeS); void processParticleCommon(QQuick3DParticleDataCurrent ¤tData, const QQuick3DParticleData *d, float particleTimeS); void processParticleFadeInOut(QQuick3DParticleDataCurrent ¤tData, const QQuick3DParticle *particle, float particleTimeS, float particleTimeLeftS); void processParticleAlignment(QQuick3DParticleDataCurrent ¤tData, const QQuick3DParticle *particle, const QQuick3DParticleData *d); static bool isGloballyDisabled(); static bool isEditorModeOn(); private: friend class QQuick3DParticleEmitter; friend class QQuick3DParticleTrailEmitter; friend class QQuick3DParticleSystemUpdate; friend class QQuick3DParticleSystemAnimation; friend class QQuick3DParticleModelBlendParticle; bool m_running; bool m_paused; bool m_initialized; bool m_componentComplete; // This animation runs the system, progressing time with pause, continue etc. QQuick3DParticleSystemAnimation *m_animation = nullptr; // This animation handles system dirty updates and runs always. // It makes sure that updates are done in sync with other animations and only once per frame. QQuick3DParticleSystemUpdate *m_updateAnimation = nullptr; QList m_particles; QList m_emitters; QList m_trailEmitters; QList m_affectors; QMap m_connections; int m_startTime = 0; // Current time in ms int m_time = 0; int m_currentTime = 0; // This overrides the time when editor mode is on int m_editorTime = 0; QElapsedTimer m_perfTimer; QTimer m_loggingTimer; qint64 m_timeAnimation = 0; int m_particlesMax = 0; int m_particlesUsed = 0; int m_updates = 0; bool m_useRandomSeed = true; int m_seed = 0; bool m_logging; QQuick3DParticleSystemLogging *m_loggingData = nullptr; QPRand m_rand; int m_particleIdIndex = 0; }; class QQuick3DParticleSystemAnimation : public QAbstractAnimation { Q_OBJECT public: QQuick3DParticleSystemAnimation(QQuick3DParticleSystem *system) : QAbstractAnimation(static_cast(system)), m_system(system) { } protected: void updateCurrentTime(int t) override { // Keep the time property up-to-date if (!m_system->isEditorModeOn() && !m_system->isGloballyDisabled()) m_system->setTime(t); m_system->updateCurrentTime(t + m_system->startTime()); } int duration() const override { return -1; } private: QQuick3DParticleSystem *m_system; }; class QQuick3DParticleSystemUpdate : public QAbstractAnimation { Q_OBJECT public: QQuick3DParticleSystemUpdate(QQuick3DParticleSystem *system) : QAbstractAnimation(static_cast(system)), m_system(system) { } void setDirty(bool dirty) { m_dirty = dirty; } protected: void updateCurrentTime(int t) override { Q_UNUSED(t); if (m_dirty) m_system->refresh(); } int duration() const override { return -1; } private: QQuick3DParticleSystem *m_system; bool m_dirty = false; }; QT_END_NAMESPACE #endif // QQUICK3DPPARTICLESYSTEM_H