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

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "lifecycle.h"
42#include "stickman.h"
43#include "node.h"
44#include "animation.h"
45#include "graphicsview.h"
46
47#include <QtCore>
48#include <QtGui>
49
50class KeyPressTransition: public QSignalTransition
51{
52public:
53 KeyPressTransition(GraphicsView *receiver, Qt::Key key)
54 : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
55 {
56 }
57 KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target)
58 : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
59 {
60 setTargetState(target);
61 }
62
63 virtual bool eventTest(QEvent *e)
64 {
65 if (QSignalTransition::eventTest(e)) {
66 QVariant key = static_cast<QStateMachine::SignalEvent*>(e)->arguments().at(0);
67 return (key.toInt() == int(m_key));
68 }
69
70 return false;
71 }
72private:
73 Qt::Key m_key;
74};
75
76//! [4]
77class LightningStrikesTransition: public QEventTransition
78{
79public:
80 LightningStrikesTransition(QAbstractState *target)
81 : QEventTransition(this, QEvent::Timer)
82 {
83 setTargetState(target);
84 qsrand((uint)QDateTime::currentDateTime().toTime_t());
85 startTimer(1000);
86 }
87
88 virtual bool eventTest(QEvent *e)
89 {
90 return QEventTransition::eventTest(e) && ((qrand() % 50) == 0);
91 }
92};
93//! [4]
94
95LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver)
96 : m_stickMan(stickMan), m_keyReceiver(keyReceiver)
97{
98 // Create animation group to be used for all transitions
99 m_animationGroup = new QParallelAnimationGroup();
100 const int stickManNodeCount = m_stickMan->nodeCount();
101 for (int i=0; i<stickManNodeCount; ++i) {
102 QPropertyAnimation *pa = new QPropertyAnimation(m_stickMan->node(i), "pos");
103 m_animationGroup->addAnimation(pa);
104 }
105
106 // Set up initial state graph
107//! [3]
108 m_machine = new QStateMachine();
109 m_machine->addDefaultAnimation(m_animationGroup);
110//! [3]
111
112 m_alive = new QState(m_machine);
113 m_alive->setObjectName("alive");
114
115 // Make it blink when lightning strikes before entering dead animation
116 QState *lightningBlink = new QState(m_machine);
117 lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::white);
118 lightningBlink->assignProperty(m_stickMan, "penColor", Qt::black);
119 lightningBlink->assignProperty(m_stickMan, "fillColor", Qt::white);
120 lightningBlink->assignProperty(m_stickMan, "isDead", true);
121
122//! [5]
123 QTimer *timer = new QTimer(lightningBlink);
124 timer->setSingleShot(true);
125 timer->setInterval(100);
126 QObject::connect(lightningBlink, SIGNAL(entered()), timer, SLOT(start()));
127 QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop()));
128//! [5]
129
130 m_dead = new QState(m_machine);
131 m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::black);
132 m_dead->assignProperty(m_stickMan, "penColor", Qt::white);
133 m_dead->assignProperty(m_stickMan, "fillColor", Qt::black);
134 m_dead->setObjectName("dead");
135
136 // Idle state (sets no properties)
137 m_idle = new QState(m_alive);
138 m_idle->setObjectName("idle");
139
140 m_alive->setInitialState(m_idle);
141
142 // Lightning strikes at random
143 m_alive->addTransition(new LightningStrikesTransition(lightningBlink));
144//! [0]
145 lightningBlink->addTransition(timer, SIGNAL(timeout()), m_dead);
146//! [0]
147
148 m_machine->setInitialState(m_alive);
149}
150
151void LifeCycle::setDeathAnimation(const QString &fileName)
152{
153 QState *deathAnimation = makeState(m_dead, fileName);
154 m_dead->setInitialState(deathAnimation);
155}
156
157void LifeCycle::start()
158{
159 m_machine->start();
160}
161
162void LifeCycle::addActivity(const QString &fileName, Qt::Key key)
163{
164 QState *state = makeState(m_alive, fileName);
165 m_alive->addTransition(new KeyPressTransition(m_keyReceiver, key, state));
166}
167
168QState *LifeCycle::makeState(QState *parentState, const QString &animationFileName)
169{
170 QState *topLevel = new QState(parentState);
171
172 Animation animation;
173 {
174 QFile file(animationFileName);
175 if (file.open(QIODevice::ReadOnly))
176 animation.load(&file);
177 }
178
179 const int frameCount = animation.totalFrames();
180 QState *previousState = 0;
181 for (int i=0; i<frameCount; ++i) {
182 animation.setCurrentFrame(i);
183
184//! [1]
185 QState *frameState = new QState(topLevel);
186 const int nodeCount = animation.nodeCount();
187 for (int j=0; j<nodeCount; ++j)
188 frameState->assignProperty(m_stickMan->node(j), "pos", animation.nodePos(j));
189//! [1]
190
191 frameState->setObjectName(QString::fromLatin1("frame %0").arg(i));
192 if (previousState == 0)
193 topLevel->setInitialState(frameState);
194 else
195//! [2]
196 previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), frameState);
197//! [2]
198
199 previousState = frameState;
200 }
201
202 // Loop
203 previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), topLevel->initialState());
204
205 return topLevel;
206
207}
208
209LifeCycle::~LifeCycle()
210{
211 delete m_machine;
212 delete m_animationGroup;
213}
Note: See TracBrowser for help on using the repository browser.