1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qquicksprite_p.h"
41#include "qquickimagebase_p.h"
42#include <qqml.h>
43#include <QDebug>
44#include <QRandomGenerator>
45
46QT_BEGIN_NAMESPACE
47
48/*!
49 \qmltype Sprite
50 \instantiates QQuickSprite
51 \inqmlmodule QtQuick
52 \ingroup qtquick-visual-utility
53 \brief Specifies sprite animations.
54
55 Sprite defines a series of one or more frames to be animated and rendered by SpriteSequence.
56 The sprites can be in the middle of an image file, or split along multiple rows, as long as they form
57 a contiguous line wrapping to the next row of the file from the left edge of the file.
58
59 For full details, see the \l{Sprite Animations} overview.
60*/
61/*!
62 \qmlproperty int QtQuick::Sprite::duration
63
64 Duration of the animation. Values below 0 are invalid.
65
66 If frameRate is valid then it will be used to calculate the duration of the frames.
67 If not, and frameDuration is valid, then frameDuration will be used. Otherwise duration is used.
68*/
69/*!
70 \qmlproperty int QtQuick::Sprite::durationVariation
71
72 The duration of the animation can vary by up to this amount. Variation will never decrease the
73 length of the animation to less than 0.
74
75 durationVariation will only take effect if duration is
76 used to calculate the duration of frames.
77
78 Default is 0.
79*/
80
81/*!
82 \qmlproperty qreal QtQuick::Sprite::frameRate
83
84 Frames per second to show in the animation. Values below 0 are invalid.
85
86 If frameRate is valid then it will be used to calculate the duration of the frames.
87 If not, and frameDuration is valid , then frameDuration will be used. Otherwise duration is used.
88*/
89/*!
90 \qmlproperty qreal QtQuick::Sprite::frameRateVariation
91
92 The frame rate between animations can vary by up to this amount. Variation will never decrease the
93 length of the animation to less than 0.
94
95 frameRateVariation will only take effect if frameRate is
96 used to calculate the duration of frames.
97
98 Default is 0.
99*/
100
101/*!
102 \qmlproperty int QtQuick::Sprite::frameDuration
103
104 Duration of each frame of the animation in milliseconds. Values below 0 are invalid.
105
106 If frameRate is valid then it will be used to calculate the duration of the frames.
107 If not, and frameDuration is valid, then frameDuration will be used. Otherwise duration is used.
108*/
109/*!
110 \qmlproperty int QtQuick::Sprite::frameDurationVariation
111
112 The duration of a frame in the animation can vary by up to this amount. Variation will never decrease the
113 length of the animation to less than 0.
114
115 frameDurationVariation will only take effect if frameDuration is
116 used to calculate the duration of frames.
117
118 Default is 0.
119*/
120
121/*!
122 \qmlproperty string QtQuick::Sprite::name
123
124 The name of this sprite, for use in the to property of other sprites.
125*/
126/*!
127 \qmlproperty QVariantMap QtQuick::Sprite::to
128
129 A list of other sprites and weighted transitions to them,
130 for example {"a":1, "b":2, "c":0} would specify that one-third should
131 transition to sprite "a" when this sprite is done, and two-thirds should
132 transition to sprite "b" when this sprite is done. As the transitions are
133 chosen randomly, these proportions will not be exact. With "c":0 in the list,
134 no sprites will randomly transition to "c", but it wll be a valid path if a sprite
135 goal is set.
136
137 If no list is specified, or the sum of weights in the list is zero, then the sprite
138 will repeat itself after completing.
139*/
140/*!
141 \qmlproperty int QtQuick::Sprite::frameCount
142
143 Number of frames in this sprite.
144*/
145/*!
146 \qmlproperty int QtQuick::Sprite::frameHeight
147
148 Height of a single frame in this sprite.
149*/
150/*!
151 \qmlproperty int QtQuick::Sprite::frameWidth
152
153 Width of a single frame in this sprite.
154*/
155/*!
156 \qmlproperty int QtQuick::Sprite::frameX
157
158 The X coordinate in the image file of the first frame of the sprite.
159*/
160/*!
161 \qmlproperty int QtQuick::Sprite::frameY
162
163 The Y coordinate in the image file of the first frame of the sprite.
164*/
165/*!
166 \qmlproperty url QtQuick::Sprite::source
167
168 The image source for the animation.
169
170 If frameHeight and frameWidth are not specified, it is assumed to be a single long row of square frames.
171 Otherwise, it can be multiple contiguous rows or rectangluar frames, when one row runs out the next will be used.
172
173 If frameX and frameY are specified, the row of frames will be taken with that x/y coordinate as the upper left corner.
174*/
175
176/*!
177 \qmlproperty bool QtQuick::Sprite::reverse
178
179 If true, then the animation will be played in reverse.
180
181 Default is false.
182*/
183
184/*!
185 \qmlproperty bool QtQuick::Sprite::randomStart
186
187 If true, then the animation will start its first animation with a random amount of its duration skipped.
188 This allows them to not look like they all just started when the animation begins.
189
190 This only affects the very first animation played. Transitioning to another animation, or the same
191 animation again, will not trigger this.
192
193 Default is false.
194*/
195
196/*!
197 \qmlproperty bool QtQuick::Sprite::frameSync
198
199 If true, then the animation will have no duration. Instead, the animation will advance
200 one frame each time a frame is rendered to the screen. This synchronizes it with the painting
201 rate as opposed to elapsed time.
202
203 If frameSync is set to true, it overrides all of duration, frameRate and frameDuration.
204
205 Default is false.
206*/
207
208static const int unsetDuration = -2;//-1 means perframe for duration
209QQuickSprite::QQuickSprite(QObject *parent)
210 : QQuickStochasticState(parent)
211 , m_generatedCount(0)
212 , m_framesPerRow(0)
213 , m_rowY(0)
214 , m_rowStartX(0)
215 , m_reverse(false)
216 , m_frameHeight(0)
217 , m_frameWidth(0)
218 , m_frames(1)
219 , m_frameX(0)
220 , m_frameY(0)
221 , m_frameRate(unsetDuration)
222 , m_frameRateVariation(0)
223 , m_frameDuration(unsetDuration)
224 , m_frameDurationVariation(0)
225 , m_frameSync(false)
226 , m_devicePixelRatio(1.0)
227{
228}
229
230/*! \internal */
231QQuickSprite::~QQuickSprite()
232{
233}
234
235int QQuickSprite::variedDuration() const //Deals with precedence when multiple durations are set
236{
237 if (m_frameSync)
238 return 0;
239
240 if (m_frameRate != unsetDuration) {
241 qreal fpms = (m_frameRate
242 + (m_frameRateVariation * QRandomGenerator::global()->generateDouble() * 2)
243 - m_frameRateVariation) / 1000.0;
244 return qMax(a: qreal(0.0) , b: m_frames / fpms);
245 } else if (m_frameDuration != unsetDuration) {
246 int mspf = m_frameDuration
247 + (m_frameDurationVariation * QRandomGenerator::global()->generateDouble() * 2)
248 - m_frameDurationVariation;
249 return qMax(a: 0, b: m_frames * mspf);
250 } else if (duration() >= 0) {
251 qWarning() << "Sprite::duration is changing meaning to the full animation duration.";
252 qWarning() << "Use Sprite::frameDuration for the old meaning, of per frame duration.";
253 qWarning() << "As an interim measure, duration/durationVariation means the same as frameDuration/frameDurationVariation, and you'll get this warning spewed out everywhere to motivate you.";
254 //Note that the spammyness is due to this being the best location to detect, but also called once each animation loop
255 return QQuickStochasticState::variedDuration() * m_frames;
256 }
257 return 1000; //When nothing set
258}
259
260void QQuickSprite::startImageLoading()
261{
262 m_pix.clear(this);
263 if (!m_source.isEmpty()) {
264 QQmlEngine *e = qmlEngine(this);
265 if (!e) { //If not created in QML, you must set the QObject parent to the QML element so this can work
266 e = qmlEngine(parent());
267 if (!e)
268 qWarning() << "QQuickSprite: Cannot find QQmlEngine - this class is only for use in QML and may not work";
269 }
270 QUrl loadUrl = m_source;
271 QQuickImageBase::resolve2xLocalFile(url: m_source, targetDevicePixelRatio: m_devicePixelRatio, sourceUrl: &loadUrl, sourceDevicePixelRatio: &m_devicePixelRatio);
272
273 m_pix.load(e, loadUrl);
274 }
275}
276
277QT_END_NAMESPACE
278
279#include "moc_qquicksprite_p.cpp"
280

source code of qtdeclarative/src/quick/items/qquicksprite.cpp