Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickparticlepainter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qtconfigmacros.h>
5#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
6
8#include <QQuickWindow>
9#include <QDebug>
11/*!
12 \qmltype ParticlePainter
13 \nativetype QQuickParticlePainter
14 \inqmlmodule QtQuick.Particles
15 \inherits Item
16 \brief For specifying how to paint particles.
17 \ingroup qtquick-particles
18
19 The default implementation paints nothing. See the subclasses if you want to
20 paint something visible.
21
22*/
23/*!
24 \qmlproperty ParticleSystem QtQuick.Particles::ParticlePainter::system
25 This is the system whose particles can be painted by the element.
26 If the ParticlePainter is a direct child of a ParticleSystem, it will automatically be associated with it.
27*/
28/*!
29 \qmlproperty list<string> QtQuick.Particles::ParticlePainter::groups
30 Which logical particle groups will be painted.
31
32 If empty, it will paint the default particle group ("").
33*/
34QQuickParticlePainter::QQuickParticlePainter(QQuickItem *parent)
35 : QQuickItem(parent)
36 , m_system(nullptr)
37 , m_count(0)
38 , m_pleaseReset(true)
39 , m_window(nullptr)
40 , m_windowChanged(false)
41 , m_groupIdsNeedRecalculation(false)
42{
43}
44
45QQuickParticlePainter::~QQuickParticlePainter()
46{
47 if (m_system)
48 m_system->unregisterParticlePainter(this);
49}
50
51void QQuickParticlePainter::itemChange(ItemChange change, const ItemChangeData &data)
52{
53 if (change == QQuickItem::ItemSceneChange) {
54 if (m_window) {
55 disconnect(m_window, &QQuickWindow::sceneGraphInvalidated,
56 this, &QQuickParticlePainter::sceneGraphInvalidated);
57 }
58 m_window = data.window;
59 m_windowChanged = true;
60 if (m_window) {
61 connect(m_window, &QQuickWindow::sceneGraphInvalidated,
62 this, &QQuickParticlePainter::sceneGraphInvalidated, Qt::DirectConnection);
63 }
64 }
65 QQuickItem::itemChange(change, data);
66}
67
68void QQuickParticlePainter::componentComplete()
69{
70 if (!m_system && qobject_cast<QQuickParticleSystem*>(parentItem()))
71 setSystem(qobject_cast<QQuickParticleSystem*>(parentItem()));
72 QQuickItem::componentComplete();
73}
74
75void QQuickParticlePainter::recalculateGroupIds() const
76{
77 if (!m_system) {
78 m_groupIds.clear();
79 return;
80 }
81
82 m_groupIdsNeedRecalculation = false;
83 m_groupIds.clear();
84
85 const auto groupList = groups();
86 for (const QString &str : groupList) {
87 QQuickParticleGroupData::ID groupId = m_system->groupIds.value(str, QQuickParticleGroupData::InvalidID);
88 if (groupId == QQuickParticleGroupData::InvalidID) {
89 // invalid data, not finished setting up, or whatever. Fallback: do not cache.
90 m_groupIdsNeedRecalculation = true;
91 } else {
92 m_groupIds.append(groupId);
93 }
94 }
95}
96
97void QQuickParticlePainter::setSystem(QQuickParticleSystem *arg)
98{
99 if (m_system != arg) {
100 if (m_system)
101 m_system->unregisterParticlePainter(this);
102 m_system = arg;
103 m_groupIdsNeedRecalculation = true;
104 if (m_system){
105 m_system->registerParticlePainter(this);
106 reset();
107 }
108 emit systemChanged(arg);
109 }
110}
111
112void QQuickParticlePainter::setGroups(const QStringList &arg)
113{
114 if (m_groups == arg)
115 return;
116 m_groups = arg;
117 m_groupIdsNeedRecalculation = true;
118
119 if (m_system) {
120 QMetaObject::invokeMethod(
121 m_system,
122 [self = QPointer<QQuickParticlePainter>(this)]() {
123 if (self)
124 self->m_system->loadPainter(self);
125 },
126 Qt::QueuedConnection);
127 }
128
129 Q_EMIT groupsChanged(arg);
130}
131
132void QQuickParticlePainter::load(QQuickParticleData* d)
133{
134 initialize(d->groupId, d->index);
135 if (m_pleaseReset)
136 return;
137 m_pendingCommits << std::make_pair(d->groupId, d->index);
138}
139
140void QQuickParticlePainter::reload(QQuickParticleData* d)
141{
142 if (m_pleaseReset)
143 return;
144 m_pendingCommits << std::make_pair(d->groupId, d->index);
145}
146
147void QQuickParticlePainter::reset()
148{
149 m_pendingCommits.clear();
150 m_pleaseReset = true;
151}
152
153void QQuickParticlePainter::setCount(int c)//### TODO: some resizeing so that particles can reallocate on size change instead of recreate
154{
155 Q_ASSERT(c >= 0); //XXX
156 if (c == m_count)
157 return;
158 m_count = c;
159 emit countChanged();
160 reset();
161}
162
163void QQuickParticlePainter::calcSystemOffset(bool resetPending)
164{
165 if (!m_system || !parentItem())
166 return;
167 QPointF lastOffset = m_systemOffset;
168 m_systemOffset = -1 * this->mapFromItem(m_system, QPointF(0.0, 0.0));
169 if (lastOffset != m_systemOffset && !resetPending){
170 //Reload all particles//TODO: Necessary?
171 foreach (const QString &g, m_groups){
172 int gId = m_system->groupIds[g];
173 foreach (QQuickParticleData* d, m_system->groupData[gId]->data)
174 reload(d);
175 }
176 }
177}
178typedef std::pair<int,int> intPair;
179void QQuickParticlePainter::performPendingCommits()
180{
181 calcSystemOffset();
182 foreach (intPair p, m_pendingCommits)
183 commit(p.first, p.second);
184 m_pendingCommits.clear();
185}
186
187QT_END_NAMESPACE
188
189#include "moc_qquickparticlepainter_p.cpp"
Combined button and popup list for selecting options.
std::pair< int, int > intPair