source: trunk/demos/qtdemo/itemcircleanimation.cpp@ 224

Last change on this file since 224 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 15.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the demonstration applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "itemcircleanimation.h"
43#include "demoitemanimation.h"
44#include "colors.h"
45#include "menumanager.h"
46#include "mainwindow.h"
47#include "menumanager.h"
48
49static QGraphicsScene *sscene;
50
51//////////////////// POST EFFECT STUFF ////////////////////////////////////////
52
53class TickerPostEffect
54{
55public:
56 virtual ~TickerPostEffect(){};
57 virtual void tick(float){};
58 virtual void transform(DemoItem *, QPointF &){};
59};
60
61class PostRotateXY : public TickerPostEffect
62{
63public:
64 float currRotX, currRotY;
65 float speedx, speedy, curvx, curvy;
66
67 PostRotateXY(float speedx, float speedy, float curvx, float curvy)
68 : currRotX(0), currRotY(0),
69 speedx(speedx), speedy(speedy),
70 curvx(curvx), curvy(curvy){};
71
72 void tick(float adjust)
73 {
74 currRotX += speedx * adjust;
75 currRotY += speedy * adjust;
76 }
77
78 void transform(DemoItem *item, QPointF &pos)
79 {
80 DemoItem *parent = (DemoItem *) item->parentItem();
81 QPointF center = parent->boundingRect().center();
82 pos.setX(center.x() + (pos.x() - center.x()) * cos(currRotX + pos.x() * curvx));
83 pos.setY(center.y() + (pos.y() - center.y()) * cos(currRotY + pos.y() * curvy));
84 }
85};
86
87class PostRotateXYTwist : public TickerPostEffect
88{
89public:
90 float currRotX, currRotY;
91 float speedx, speedy, curvx, curvy;
92
93 PostRotateXYTwist(float speedx, float speedy, float curvx, float curvy)
94 : currRotX(0), currRotY(0),
95 speedx(speedx), speedy(speedy),
96 curvx(curvx), curvy(curvy){};
97
98 void tick(float adjust)
99 {
100 currRotX += speedx * adjust;
101 currRotY += speedy * adjust;
102 }
103
104 void transform(DemoItem *item, QPointF &pos)
105 {
106 DemoItem *parent = (DemoItem *) item->parentItem();
107 QPointF center = parent->boundingRect().center();
108 pos.setX(center.x() + (pos.x() - center.x()) * cos(currRotX + pos.y() * curvx));
109 pos.setY(center.y() + (pos.y() - center.y()) * cos(currRotY + pos.x() * curvy));
110 }
111};
112
113//////////////////// TICKER EFFECT STUFF //////////////////////////////////////
114
115class TickerEffect
116{
117 TickerPostEffect *postEffect;
118public:
119 enum EffectStatus{Normal, Intro, Outro} status;
120 LetterList *letters;
121 float morphSpeed, moveSpeed;
122 float normalMorphSpeed, normalMoveSpeed;
123 bool useSheepDog, morphBetweenModels;
124
125 TickerEffect(LetterList *letters)
126 : postEffect(new TickerPostEffect()), status(Intro), letters(letters),
127 morphSpeed(Colors::tickerMorphSpeed), moveSpeed(Colors::tickerMoveSpeed),
128 normalMorphSpeed(Colors::tickerMorphSpeed), normalMoveSpeed(Colors::tickerMoveSpeed),
129 useSheepDog(true), morphBetweenModels(!Colors::noTickerMorph){}
130
131 void setPostEffect(TickerPostEffect *effect)
132 {
133 delete postEffect;
134 postEffect = effect;
135 }
136
137 virtual ~TickerEffect()
138 {
139 delete postEffect;
140 }
141
142 void slowDownAfterIntro(float adjust)
143 {
144 if (morphBetweenModels){
145 if (status == Intro){
146 float dec = 0.1 * adjust;
147 moveSpeed -= dec;
148 if (moveSpeed < Colors::tickerMoveSpeed){
149 moveSpeed = normalMoveSpeed;
150 morphSpeed = normalMorphSpeed;
151 status = Normal;
152 }
153 }
154 }
155 }
156
157 void moveLetters(float adjust)
158 {
159 float adaptedMoveSpeed = this->moveSpeed * adjust;
160 float adaptedMorphSpeed = this->morphSpeed * adjust;
161 postEffect->tick(adjust);
162
163 for (int i=0; i<letters->size(); i++){
164 LetterItem *letter = letters->at(i);
165 letter->guideAdvance(this->morphBetweenModels ? adaptedMoveSpeed : Colors::tickerMoveSpeed);
166 letter->guideMove(this->morphBetweenModels ? adaptedMorphSpeed : -1);
167
168 QPointF pos = letter->getGuidedPos();
169 postEffect->transform(letter, pos);
170
171 if (useSheepDog)
172 letter->setPosUsingSheepDog(pos, QRectF(0, 0, 800, 600));
173 else
174 letter->setPos(pos);
175 }
176 }
177
178 virtual void tick(float adjust)
179 {
180 slowDownAfterIntro(adjust);
181 moveLetters(adjust);
182 }
183
184};
185
186class EffectWhirlWind : public TickerEffect
187{
188public:
189 EffectWhirlWind(LetterList *letters) : TickerEffect(letters)
190 {
191 moveSpeed = 50;
192 for (int i=0; i<this->letters->size(); i++){
193 LetterItem *letter = this->letters->at(i);
194 letter->setGuidedPos(QPointF(0, 100));
195 }
196 }
197};
198
199class EffectSnake : public TickerEffect
200{
201public:
202 EffectSnake(LetterList *letters) : TickerEffect(letters)
203 {
204 moveSpeed = 40;
205 for (int i=0; i<this->letters->size(); i++){
206 LetterItem *letter = this->letters->at(i);
207 letter->setGuidedPos(QPointF(0, -250 - (i * 5)));
208 }
209 }
210};
211
212class EffectScan : public TickerEffect
213{
214public:
215 EffectScan(LetterList *letters) : TickerEffect(letters)
216 {
217 for (int i=0; i<this->letters->size(); i++){
218 LetterItem *letter = this->letters->at(i);
219 letter->setGuidedPos(QPointF(100, -300));
220 }
221 }
222};
223
224class EffectRaindrops : public TickerEffect
225{
226public:
227 EffectRaindrops(LetterList *letters) : TickerEffect(letters)
228 {
229 for (int i=0; i<this->letters->size(); i++){
230 LetterItem *letter = this->letters->at(i);
231 letter->setGuidedPos(QPointF(-100 + rand() % 200, - 200.0f - rand() % 1300));
232 }
233 }
234};
235
236class EffectLine : public TickerEffect
237{
238public:
239 EffectLine(LetterList *letters) : TickerEffect(letters)
240 {
241 for (int i=0; i<this->letters->size(); i++){
242 LetterItem *letter = this->letters->at(i);
243 letter->setGuidedPos(QPointF(100, 500.0f + i * 20));
244 }
245 }
246};
247
248//////////////////// TICKER STUFF /////////////////////////////////////////////
249
250ItemCircleAnimation::ItemCircleAnimation(QGraphicsScene *scene, QGraphicsItem *parent)
251 : DemoItem(scene, parent)
252{
253 sscene = scene;
254 this->letterCount = Colors::tickerLetterCount;
255 this->scale = 1;
256 this->showCount = -1;
257 this->tickOnPaint = false;
258 this->paused = false;
259 this->doIntroTransitions = true;
260 this->setAcceptsHoverEvents(true);
261 this->setCursor(Qt::OpenHandCursor);
262 this->setupGuides();
263 this->setupLetters();
264 this->useGuideQt();
265 this->effect = 0;//new TickerEffect(this->letterList);
266}
267
268ItemCircleAnimation::~ItemCircleAnimation()
269{
270 delete this->letterList;
271 delete this->qtGuide1;
272 delete this->qtGuide2;
273 delete this->qtGuide3;
274 delete this->effect;
275}
276
277void ItemCircleAnimation::createLetter(char c)
278{
279 LetterItem *letter = new LetterItem(c, sscene, this);
280 this->letterList->append(letter);
281}
282
283void ItemCircleAnimation::setupLetters()
284{
285 this->letterList = new LetterList();
286
287 QString s = Colors::tickerText;
288 int len = s.length();
289 int i = 0;
290 for (; i < this->letterCount - len; i += len)
291 for (int l=0; l<len; l++)
292 createLetter(s[l].toLatin1());
293
294 // Fill inn with blanks:
295 for (; i < this->letterCount; ++i)
296 createLetter(' ');
297}
298
299void ItemCircleAnimation::setupGuides()
300{
301 int x = 0;
302 int y = 20;
303
304 this->qtGuide1 = new GuideCircle(QRectF(x, y, 260, 260), -36, 342);
305 new GuideLine(QPointF(x + 240, y + 268), this->qtGuide1);
306 new GuideLine(QPointF(x + 265, y + 246), this->qtGuide1);
307 new GuideLine(QPointF(x + 158, y + 134), this->qtGuide1);
308 new GuideLine(QPointF(x + 184, y + 109), this->qtGuide1);
309 new GuideLine(QPointF(x + 160, y + 82), this->qtGuide1);
310 new GuideLine(QPointF(x + 77, y + 163), this->qtGuide1); // T-top
311 new GuideLine(QPointF(x + 100, y + 190), this->qtGuide1);
312 new GuideLine(QPointF(x + 132, y + 159), this->qtGuide1);
313 new GuideLine(QPointF(x + 188, y + 211), this->qtGuide1);
314 new GuideCircle(QRectF(x + 30, y + 30, 200, 200), -30, 336, GuideCircle::CW, this->qtGuide1);
315 new GuideLine(QPointF(x + 238, y + 201), this->qtGuide1);
316
317 y = 30;
318 this->qtGuide2 = new GuideCircle(QRectF(x + 30, y + 30, 200, 200), 135, 270, GuideCircle::CCW);
319 new GuideLine(QPointF(x + 222, y + 38), this->qtGuide2);
320 new GuideCircle(QRectF(x, y, 260, 260), 135, 270, GuideCircle::CW, this->qtGuide2);
321 new GuideLine(QPointF(x + 59, y + 59), this->qtGuide2);
322
323 x = 115;
324 y = 10;
325 this->qtGuide3 = new GuideLine(QLineF(x, y, x + 30, y));
326 new GuideLine(QPointF(x + 30, y + 170), this->qtGuide3);
327 new GuideLine(QPointF(x, y + 170), this->qtGuide3);
328 new GuideLine(QPointF(x, y), this->qtGuide3);
329
330 this->qtGuide1->setFence(QRectF(0, 0, 800, 600));
331 this->qtGuide2->setFence(QRectF(0, 0, 800, 600));
332 this->qtGuide3->setFence(QRectF(0, 0, 800, 600));
333}
334
335void ItemCircleAnimation::useGuide(Guide *guide, int firstLetter, int lastLetter)
336{
337 float padding = guide->lengthAll() / float(lastLetter - firstLetter);
338 for (int i=firstLetter; i<lastLetter; i++){
339 LetterItem *letter = this->letterList->at(i);
340 letter->useGuide(guide, (i - firstLetter) * padding);
341 }
342}
343
344void ItemCircleAnimation::useGuideQt()
345{
346 if (this->currGuide != this->qtGuide1){
347 this->useGuide(qtGuide1, 0, this->letterCount);
348 this->currGuide = qtGuide1;
349 }
350}
351
352void ItemCircleAnimation::useGuideTt()
353{
354 if (this->currGuide != this->qtGuide2){
355 int split = int(this->letterCount * 5.0 / 7.0);
356 this->useGuide(qtGuide2, 0, split);
357 this->useGuide(qtGuide3, split, this->letterCount);
358 this->currGuide = qtGuide2;
359 }
360}
361
362QRectF ItemCircleAnimation::boundingRect() const
363{
364 return QRectF(0, 0, 300, 320);
365}
366
367void ItemCircleAnimation::prepare()
368{
369}
370
371void ItemCircleAnimation::switchToNextEffect()
372{
373 ++this->showCount;
374 delete this->effect;
375
376 switch (this->showCount){
377 case 1:
378 this->effect = new EffectSnake(this->letterList);
379 break;
380 case 2:
381 this->effect = new EffectLine(this->letterList);
382 this->effect->setPostEffect(new PostRotateXYTwist(0.01f, 0.0f, 0.003f, 0.0f));
383 break;
384 case 3:
385 this->effect = new EffectRaindrops(this->letterList);
386 this->effect->setPostEffect(new PostRotateXYTwist(0.01f, 0.005f, 0.003f, 0.003f));
387 break;
388 case 4:
389 this->effect = new EffectScan(this->letterList);
390 this->effect->normalMoveSpeed = 0;
391 this->effect->setPostEffect(new PostRotateXY(0.008f, 0.0f, 0.005f, 0.0f));
392 break;
393 default:
394 this->showCount = 0;
395 this->effect = new EffectWhirlWind(this->letterList);
396 }
397}
398
399void ItemCircleAnimation::animationStarted(int id)
400{
401 if (id == DemoItemAnimation::ANIM_IN){
402 if (this->doIntroTransitions){
403 // Make all letters dissapear
404 for (int i=0; i<this->letterList->size(); i++){
405 LetterItem *letter = this->letterList->at(i);
406 letter->setPos(1000, 0);
407 }
408 this->switchToNextEffect();
409 this->useGuideQt();
410 this->scale = 1;
411 // The first time we run, we have a rather large
412 // delay to perform benchmark before the ticker shows.
413 // But now, since we are showing, use a more appropriate value:
414 this->currentAnimation->startDelay = 1500;
415 }
416 }
417 else if (this->effect)
418 this->effect->useSheepDog = false;
419
420 this->tickTimer = QTime::currentTime();
421}
422
423void ItemCircleAnimation::animationStopped(int)
424{
425 // Nothing to do.
426}
427
428void ItemCircleAnimation::swapModel(){
429 if (this->currGuide == this->qtGuide2)
430 this->useGuideQt();
431 else
432 this->useGuideTt();
433}
434
435void ItemCircleAnimation::hoverEnterEvent(QGraphicsSceneHoverEvent *)
436{
437// Skip swap here to enhance ticker dragging
438// this->swapModel();
439}
440
441void ItemCircleAnimation::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
442{
443 this->swapModel();
444}
445
446void ItemCircleAnimation::setTickerScale(float s)
447{
448 this->scale = s;
449 qtGuide1->setScale(this->scale, this->scale);
450 qtGuide2->setScale(this->scale, this->scale);
451 qtGuide3->setScale(this->scale, this->scale);
452}
453
454void ItemCircleAnimation::mousePressEvent(QGraphicsSceneMouseEvent *event)
455{
456 this->mouseMoveLastPosition = event->scenePos();
457 if (event->button() == Qt::LeftButton)
458 this->setCursor(Qt::ClosedHandCursor);
459 else
460 this->switchToNextEffect();
461}
462
463void ItemCircleAnimation::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
464{
465 if (event->button() == Qt::LeftButton)
466 this->setCursor(Qt::OpenHandCursor);
467}
468
469void ItemCircleAnimation::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
470{
471 QPointF newPosition = event->scenePos();
472 this->setPosUsingSheepDog(this->pos() + newPosition - this->mouseMoveLastPosition, QRectF(-260, -280, 1350, 1160));
473 this->mouseMoveLastPosition = newPosition;
474}
475
476void ItemCircleAnimation::wheelEvent(QGraphicsSceneWheelEvent *event)
477{
478 this->effect->moveSpeed = this->effect->moveSpeed + (event->delta() > 0 ? -0.20 : 0.20);
479 if (this->effect->moveSpeed < 0)
480 this->effect->moveSpeed = 0;
481}
482
483void ItemCircleAnimation::pause(bool on)
484{
485 this->paused = on;
486 this->tickTimer = QTime::currentTime();
487}
488
489void ItemCircleAnimation::tick()
490{
491 if (this->paused || !this->effect)
492 return;
493
494 float t = this->tickTimer.msecsTo(QTime::currentTime());
495 this->tickTimer = QTime::currentTime();
496 this->effect->tick(t/10.0f);
497}
498
499void ItemCircleAnimation::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
500{
501 if (this->tickOnPaint)
502 tick();
503}
504
505
506
507
Note: See TracBrowser for help on using the repository browser.