/* QSoloCards is a collection of Solitaire card games written using Qt Copyright (C) 2009 Steve Moore This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "StackToStackFlipAni.h" #include "CardAnimationLock.h" #include "CardPixmaps.h" #include #include #include const qreal StackToStackFlipAni::ExposedPrecentShownCards=.18; const qreal StackToStackFlipAni::ExposedPrecentHiddenCards=.02; /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// StackToStackFlipAni::StackToStackFlipAni() :m_pDst(NULL), m_pSrc(NULL), m_cardVector(), m_firstCardToShow(0), m_flipPtReached(false), m_moveRecord(), m_pTimeLine(NULL), m_pItemAni(NULL), m_pPixmapItem(NULL), m_aniRunning(false) { } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// StackToStackFlipAni::~StackToStackFlipAni() { } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void StackToStackFlipAni::moveCards(CardStack * pDst,CardStack * pSrc, int numCards,int cardsShown, int duration) { // first if we have an animation running stop it. this->stopAni(); // setup the next animation. m_pDst=pDst; m_pSrc=pSrc; m_cardVector.clear(); m_moveRecord.clear(); m_flipPtReached=false; while( !m_pSrc->isEmpty() && numCards>0) { PlayingCard card(m_pSrc->removeTopCard(m_moveRecord)); m_cardVector.insert(m_cardVector.begin(),card); numCards--; } // by default we will show all cards m_firstCardToShow=0; // if we are not showing all cards starting with index 0 // then figure out the index of the first card that will // be shown. if (m_cardVector.size()>0 && cardsShown>=0 && cardsShown<(int)m_cardVector.size()) { // ok if the value is 0 or 1. We will just show // the last card. 0 doesn't make any sense if you // are flipping cards. So, we will assume one for // that case as well. if (cardsShown<=1) { m_firstCardToShow=m_cardVector.size()-1; } else { m_firstCardToShow=m_cardVector.size()-cardsShown; } } // if animation is off just immediately add the cards to the new // stack. Call updateStack to redraw the stacks. And emit the // signal that the cards have been moved. if (!CardAnimationLock::getInst().animationsEnabled()) { this->flipCards(); m_pSrc->updateStack(); m_pDst->addCards(m_cardVector,m_moveRecord); m_pDst->updateStack(); emit cardsMoved(m_moveRecord); } else { CardAnimationLock::getInst().lock(); runAnimation(duration); } } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void StackToStackFlipAni::slotAniFinished(bool emitSignal) { if (m_aniRunning) { m_aniRunning=false; this->m_pTimeLine->stop(); m_pDst->addCards(m_cardVector,m_moveRecord); m_pDst->updateStack(); // remove the animation object m_pSrc->scene()->removeItem(m_pPixmapItem); delete m_pPixmapItem; m_pPixmapItem=NULL; CardAnimationLock::getInst().unlock(); if (emitSignal) { emit cardsMoved(m_moveRecord); } } } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void StackToStackFlipAni::slotAniProgress(qreal currProgress) { if (currProgress>=.6 && !m_flipPtReached) { m_flipPtReached=true; this->flipCards(); QPixmap * pPixmap=this->getAniPixmap(); if (pPixmap) { m_pPixmapItem->setPixmap(*pPixmap); delete pPixmap; } } } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void StackToStackFlipAni::runAnimation(int duration) { m_aniRunning=true; delete m_pTimeLine; delete m_pItemAni; delete m_pPixmapItem; m_pTimeLine=new QTimeLine(duration); m_pItemAni=new QGraphicsItemAnimation; m_pPixmapItem=new QGraphicsPixmapItem; QPixmap * pPixmap=this->getAniPixmap(); if (pPixmap) { m_pPixmapItem->setPixmap(*pPixmap); delete pPixmap; } // set the z value to 2 so it will be on top of the // stacks. m_pPixmapItem->setZValue(2); // add the item to the scene and move it over the stack in the // place of the cards we are going to move m_pSrc->scene()->addItem(m_pPixmapItem); m_pPixmapItem->setPos(m_pSrc->getGlobalLastCardPt()); // setup the animation m_pItemAni->setItem(m_pPixmapItem); m_pItemAni->setTimeLine(m_pTimeLine); // set the start and end point m_pItemAni->setPosAt (0, m_pSrc->getGlobalLastCardPt()); m_pItemAni->setPosAt (1, m_pDst->getGlobalCardAddPt()); // set the scaling to give the flipping effect. m_pItemAni->setScaleAt( 0, 1, 1 ); m_pItemAni->setScaleAt( 0.6, 0, 1 ); m_pItemAni->setScaleAt( 1, 1, 1 ); // connect up the slot so we will know when it is finished. this->connect(m_pTimeLine,SIGNAL(finished()), this,SLOT(slotAniFinished())); this->connect(m_pTimeLine,SIGNAL(valueChanged(qreal)), this,SLOT(slotAniProgress(qreal))); // update the src stack behind the flip item we just added m_pSrc->updateStack(); m_pTimeLine->start(); } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// QPixmap * StackToStackFlipAni::getAniPixmap() { QPixmap * pPixmap=NULL; if (m_cardVector.size()>0) { unsigned int i; pPixmap =new QPixmap(this->calcPixmapSize()); // for linux the transparent fill must be done before // we associate the pixmap with the painter pPixmap->fill(Qt::transparent); QPainter painter(pPixmap); QPoint pt(0,0); for (i=0;i=m_firstCardToShow && m_cardVector[index].isFaceUp()) { increment=CardPixmaps::getInst().getCardSize().width()*ExposedPrecentShownCards; } else { increment=CardPixmaps::getInst().getCardSize().width()*ExposedPrecentHiddenCards; } } return increment; } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void StackToStackFlipAni::flipCards() { if (m_cardVector.size()>0) { int i; PlayingCardVector flipVector; for(i=m_cardVector.size()-1;i>=0;i--) { m_cardVector[i].setFaceUp(!m_cardVector[i].isFaceUp()); flipVector.push_back(m_cardVector[i]); } m_cardVector.clear(); m_cardVector=flipVector; } }