source: trunk/examples/animation/stickman/lifecycle.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "lifecycle.h"
43#include "stickman.h"
44#include "node.h"
45#include "animation.h"
46#include "graphicsview.h"
47
48#include <QtCore>
49#include <QtGui>
50
51class KeyPressTransition: public QSignalTransition
52{
53public:
54 KeyPressTransition(GraphicsView *receiver, Qt::Key key)
55 : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
56 {
57 }
58 KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target)
59 : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
60 {
61 setTargetState(target);
62 }
63
64 virtual bool eventTest(QEvent *e)
65 {
66 if (QSignalTransition::eventTest(e)) {
67 QVariant key = static_cast<QStateMachine::SignalEvent*>(e)->arguments().at(0);
68 return (key.toInt() == int(m_key));
69 }
70
71 return false;
72 }
73private:
74 Qt::Key m_key;
75};
76
77//! [4]
78class LightningStrikesTransition: public QEventTransition
79{
80public:
81 LightningStrikesTransition(QAbstractState *target)
82 : QEventTransition(this, QEvent::Timer)
83 {
84 setTargetState(target);
85 qsrand((uint)QDateTime::currentDateTime().toTime_t());
86 startTimer(1000);
87 }
88
89 virtual bool eventTest(QEvent *e)
90 {
91 return QEventTransition::eventTest(e) && ((qrand() % 50) == 0);
92 }
93};
94//! [4]
95
96LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver)
97 : m_stickMan(stickMan), m_keyReceiver(keyReceiver)
98{
99 // Create animation group to be used for all transitions
100 m_animationGroup = new QParallelAnimationGroup();
101 const int stickManNodeCount = m_stickMan->nodeCount();
102 for (int i=0; i<stickManNodeCount; ++i) {
103 QPropertyAnimation *pa = new QPropertyAnimation(m_stickMan->node(i), "pos");
104 m_animationGroup->addAnimation(pa);
105 }
106
107 // Set up intial state graph
108//! [3]
109 m_machine = new QStateMachine();
110 m_machine->addDefaultAnimation(m_animationGroup);
111//! [3]
112
113 m_alive = new QState(m_machine);
114 m_alive->setObjectName("alive");
115
116 // Make it blink when lightning strikes before entering dead animation
117 QState *lightningBlink = new QState(m_machine);
118 lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::white);
119 lightningBlink->assignProperty(m_stickMan, "penColor", Qt::black);
120 lightningBlink->assignProperty(m_stickMan, "fillColor", Qt::white);
121 lightningBlink->assignProperty(m_stickMan, "isDead", true);
122
123//! [5]
124 QTimer *timer = new QTimer(lightningBlink);
125 timer->setSingleShot(true);
126 timer->setInterval(100);
127 QObject::connect(lightningBlink, SIGNAL(entered()), timer, SLOT(start()));
128 QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop()));
129//! [5]
130
131 m_dead = new QState(m_machine);
132 m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::black);
133 m_dead->assignProperty(m_stickMan, "penColor", Qt::white);
134 m_dead->assignProperty(m_stickMan, "fillColor", Qt::black);
135 m_dead->setObjectName("dead");
136
137 // Idle state (sets no properties)
138 m_idle = new QState(m_alive);
139 m_idle->setObjectName("idle");
140
141 m_alive->setInitialState(m_idle);
142
143 // Lightning strikes at random
144 m_alive->addTransition(new LightningStrikesTransition(lightningBlink));
145//! [0]
146 lightningBlink->addTransition(timer, SIGNAL(timeout()), m_dead);
147//! [0]
148
149 m_machine->setInitialState(m_alive);
150}
151
152void LifeCycle::setDeathAnimation(const QString &fileName)
153{
154 QState *deathAnimation = makeState(m_dead, fileName);
155 m_dead->setInitialState(deathAnimation);
156}
157
158void LifeCycle::start()
159{
160 m_machine->start();
161}
162
163void LifeCycle::addActivity(const QString &fileName, Qt::Key key)
164{
165 QState *state = makeState(m_alive, fileName);
166 m_alive->addTransition(new KeyPressTransition(m_keyReceiver, key, state));
167}
168
169QState *LifeCycle::makeState(QState *parentState, const QString &animationFileName)
170{
171 QState *topLevel = new QState(parentState);
172
173 Animation animation;
174 {
175 QFile file(animationFileName);
176 if (file.open(QIODevice::ReadOnly))
177 animation.load(&file);
178 }
179
180 const int frameCount = animation.totalFrames();
181 QState *previousState = 0;
182 for (int i=0; i<frameCount; ++i) {
183 animation.setCurrentFrame(i);
184
185//! [1]
186 QState *frameState = new QState(topLevel);
187 const int nodeCount = animation.nodeCount();
188 for (int j=0; j<nodeCount; ++j)
189 frameState->assignProperty(m_stickMan->node(j), "pos", animation.nodePos(j));
190//! [1]
191
192 frameState->setObjectName(QString::fromLatin1("frame %0").arg(i));
193 if (previousState == 0)
194 topLevel->setInitialState(frameState);
195 else
196//! [2]
197 previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), frameState);
198//! [2]
199
200 previousState = frameState;
201 }
202
203 // Loop
204 previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), topLevel->initialState());
205
206 return topLevel;
207
208}
209
210LifeCycle::~LifeCycle()
211{
212 delete m_machine;
213 delete m_animationGroup;
214}
Note: See TracBrowser for help on using the repository browser.