examples/animation/stickman/lifecycle.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    51 class KeyPressTransition: public QSignalTransition
       
    52 {
       
    53 public:
       
    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     }
       
    73 private:
       
    74     Qt::Key m_key;
       
    75 };
       
    76 
       
    77 //! [4]
       
    78 class LightningStrikesTransition: public QEventTransition
       
    79 {
       
    80 public:
       
    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 
       
    96 LifeCycle::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 
       
   152 void LifeCycle::setDeathAnimation(const QString &fileName)
       
   153 {
       
   154     QState *deathAnimation = makeState(m_dead, fileName);
       
   155     m_dead->setInitialState(deathAnimation);
       
   156 }
       
   157 
       
   158 void LifeCycle::start()
       
   159 {
       
   160     m_machine->start();
       
   161 }
       
   162 
       
   163 void 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 
       
   169 QState *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(polished()), frameState);
       
   198 //! [2]
       
   199         
       
   200         previousState = frameState;
       
   201     }
       
   202 
       
   203     // Loop
       
   204     previousState->addTransition(previousState, SIGNAL(polished()), topLevel->initialState());
       
   205 
       
   206     return topLevel;
       
   207 
       
   208 }
       
   209 
       
   210 LifeCycle::~LifeCycle()
       
   211 {
       
   212     delete m_machine;
       
   213     delete m_animationGroup;
       
   214 }