2010-12-31 14:56:24 +08:00
/****************************************************************************
2014-01-07 11:25:07 +08:00
Copyright ( c ) 2008 - 2010 Ricardo Quesada
2012-09-24 21:22:20 +08:00
Copyright ( c ) 2010 - 2012 cocos2d - x . org
2011-07-01 16:11:31 +08:00
Copyright ( c ) 2011 Zynga Inc .
2014-01-07 11:25:07 +08:00
CopyRight ( c ) 2013 - 2014 Chukong Technologies Inc .
2010-12-31 14:56:24 +08:00
http : //www.cocos2d-x.org
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-05-01 10:09:13 +08:00
# include "2d/CCAnimationCache.h"
2014-04-30 08:37:36 +08:00
# include "base/ccMacros.h"
2014-05-01 10:09:13 +08:00
# include "2d/CCAnimation.h"
2014-04-27 01:11:22 +08:00
# include "2d/CCSpriteFrame.h"
# include "2d/CCSpriteFrameCache.h"
2014-05-17 05:36:00 +08:00
# include "platform/CCFileUtils.h"
2014-05-01 10:09:13 +08:00
# include "deprecated/CCString.h"
2010-12-31 14:56:24 +08:00
2012-03-16 13:42:53 +08:00
using namespace std ;
2010-12-31 14:56:24 +08:00
2012-03-16 13:42:53 +08:00
NS_CC_BEGIN
2010-12-31 14:56:24 +08:00
2013-12-18 17:47:20 +08:00
AnimationCache * AnimationCache : : s_sharedAnimationCache = nullptr ;
2010-12-31 14:56:24 +08:00
2013-07-12 06:24:23 +08:00
AnimationCache * AnimationCache : : getInstance ( )
2012-03-16 13:42:53 +08:00
{
2013-12-18 17:47:20 +08:00
if ( ! s_sharedAnimationCache )
2012-04-19 14:35:52 +08:00
{
2013-12-18 17:47:20 +08:00
s_sharedAnimationCache = new AnimationCache ( ) ;
s_sharedAnimationCache - > init ( ) ;
2012-04-19 14:35:52 +08:00
}
2010-12-31 14:56:24 +08:00
2013-12-18 17:47:20 +08:00
return s_sharedAnimationCache ;
2012-03-16 13:42:53 +08:00
}
2010-12-31 14:56:24 +08:00
2013-07-12 06:24:23 +08:00
void AnimationCache : : destroyInstance ( )
2012-03-16 13:42:53 +08:00
{
2013-12-18 17:47:20 +08:00
CC_SAFE_RELEASE_NULL ( s_sharedAnimationCache ) ;
2012-03-16 13:42:53 +08:00
}
2010-12-31 14:56:24 +08:00
2013-06-20 14:13:12 +08:00
bool AnimationCache : : init ( )
2012-03-16 13:42:53 +08:00
{
2012-04-19 14:35:52 +08:00
return true ;
2012-03-16 13:42:53 +08:00
}
2013-06-20 14:13:12 +08:00
AnimationCache : : AnimationCache ( )
2012-03-16 13:42:53 +08:00
{
}
2013-06-20 14:13:12 +08:00
AnimationCache : : ~ AnimationCache ( )
2012-03-16 13:42:53 +08:00
{
2013-08-22 11:12:09 +08:00
CCLOGINFO ( " deallocing AnimationCache: %p " , this ) ;
2012-03-16 13:42:53 +08:00
}
2010-12-31 14:56:24 +08:00
2013-11-06 11:02:03 +08:00
void AnimationCache : : addAnimation ( Animation * animation , const std : : string & name )
2012-03-16 13:42:53 +08:00
{
2013-12-05 10:59:43 +08:00
_animations . insert ( name , animation ) ;
2012-03-16 13:42:53 +08:00
}
2013-11-06 11:02:03 +08:00
void AnimationCache : : removeAnimation ( const std : : string & name )
2012-03-16 13:42:53 +08:00
{
2013-11-06 11:02:03 +08:00
if ( name . size ( ) = = 0 )
2012-04-19 14:35:52 +08:00
return ;
2010-12-31 14:56:24 +08:00
2013-12-11 17:15:27 +08:00
_animations . erase ( name ) ;
2012-03-16 13:42:53 +08:00
}
2010-12-31 14:56:24 +08:00
2013-11-06 11:02:03 +08:00
Animation * AnimationCache : : getAnimation ( const std : : string & name )
2012-03-16 13:42:53 +08:00
{
2013-12-05 10:59:43 +08:00
return _animations . at ( name ) ;
2012-03-16 13:42:53 +08:00
}
2010-12-31 14:56:24 +08:00
2013-12-04 17:46:57 +08:00
void AnimationCache : : parseVersion1 ( const ValueMap & animations )
2012-04-19 14:35:52 +08:00
{
2013-07-12 06:24:23 +08:00
SpriteFrameCache * frameCache = SpriteFrameCache : : getInstance ( ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
for ( auto iter = animations . cbegin ( ) ; iter ! = animations . cend ( ) ; + + iter )
2012-04-19 14:35:52 +08:00
{
2013-12-04 17:46:57 +08:00
const ValueMap & animationDict = iter - > second . asValueMap ( ) ;
const ValueVector & frameNames = animationDict . at ( " frames " ) . asValueVector ( ) ;
2013-12-03 14:47:35 +08:00
float delay = animationDict . at ( " delay " ) . asFloat ( ) ;
Animation * animation = nullptr ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
if ( frameNames . empty ( ) )
2012-04-19 14:35:52 +08:00
{
2013-12-03 14:47:35 +08:00
CCLOG ( " cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache. " , iter - > first . c_str ( ) ) ;
2012-04-19 14:35:52 +08:00
continue ;
}
2013-12-27 15:06:16 +08:00
ssize_t frameNameSize = frameNames . size ( ) ;
Vector < AnimationFrame * > frames ( frameNameSize ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
for ( auto & frameName : frameNames )
2012-04-19 14:35:52 +08:00
{
2013-12-03 14:47:35 +08:00
SpriteFrame * spriteFrame = frameCache - > getSpriteFrameByName ( frameName . asString ( ) ) ;
2012-04-19 14:35:52 +08:00
if ( ! spriteFrame ) {
2013-12-03 14:47:35 +08:00
CCLOG ( " cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the SpriteFrameCache. This frame will not be added to the animation. " , iter - > first . c_str ( ) , frameName . asString ( ) . c_str ( ) ) ;
2012-04-19 14:35:52 +08:00
continue ;
}
2013-12-04 17:46:57 +08:00
AnimationFrame * animFrame = AnimationFrame : : create ( spriteFrame , 1 , ValueMap ( ) ) ;
2013-12-05 10:35:10 +08:00
frames . pushBack ( animFrame ) ;
2012-04-19 14:35:52 +08:00
}
2013-12-27 15:06:16 +08:00
if ( frames . empty ( ) )
2013-12-03 14:47:35 +08:00
{
CCLOG ( " cocos2d: AnimationCache: None of the frames for animation '%s' were found in the SpriteFrameCache. Animation is not being added to the Animation Cache. " , iter - > first . c_str ( ) ) ;
2012-04-19 14:35:52 +08:00
continue ;
2013-12-03 14:47:35 +08:00
}
2013-12-27 15:06:16 +08:00
else if ( frames . size ( ) ! = frameNameSize )
2013-12-03 14:47:35 +08:00
{
CCLOG ( " cocos2d: AnimationCache: An animation in your dictionary refers to a frame which is not in the SpriteFrameCache. Some or all of the frames for the animation '%s' may be missing. " , iter - > first . c_str ( ) ) ;
2012-04-19 14:35:52 +08:00
}
2013-06-20 14:13:12 +08:00
animation = Animation : : create ( frames , delay , 1 ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
AnimationCache : : getInstance ( ) - > addAnimation ( animation , iter - > first . c_str ( ) ) ;
2013-11-28 16:02:03 +08:00
}
2012-04-19 14:35:52 +08:00
}
2013-12-04 17:46:57 +08:00
void AnimationCache : : parseVersion2 ( const ValueMap & animations )
2012-04-19 14:35:52 +08:00
{
2013-07-12 06:24:23 +08:00
SpriteFrameCache * frameCache = SpriteFrameCache : : getInstance ( ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
for ( auto iter = animations . cbegin ( ) ; iter ! = animations . cend ( ) ; + + iter )
2012-04-19 14:35:52 +08:00
{
2013-12-03 14:47:35 +08:00
std : : string name = iter - > first ;
2013-12-07 14:22:03 +08:00
ValueMap & animationDict = const_cast < ValueMap & > ( iter - > second . asValueMap ( ) ) ;
2012-04-19 14:35:52 +08:00
2013-12-07 14:22:03 +08:00
const Value & loops = animationDict [ " loops " ] ;
bool restoreOriginalFrame = animationDict [ " restoreOriginalFrame " ] . asBool ( ) ;
2012-04-19 14:35:52 +08:00
2013-12-07 14:22:03 +08:00
ValueVector & frameArray = animationDict [ " frames " ] . asValueVector ( ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
if ( frameArray . empty ( ) )
{
CCLOG ( " cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache. " , name . c_str ( ) ) ;
2012-04-19 14:35:52 +08:00
continue ;
}
// Array of AnimationFrames
2013-12-06 16:32:06 +08:00
Vector < AnimationFrame * > array ( static_cast < int > ( frameArray . size ( ) ) ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
for ( auto & obj : frameArray )
2012-04-19 14:35:52 +08:00
{
2013-12-07 14:22:03 +08:00
ValueMap & entry = obj . asValueMap ( ) ;
std : : string spriteFrameName = entry [ " spriteframe " ] . asString ( ) ;
2013-07-18 07:56:19 +08:00
SpriteFrame * spriteFrame = frameCache - > getSpriteFrameByName ( spriteFrameName ) ;
2012-04-19 14:35:52 +08:00
if ( ! spriteFrame ) {
2013-12-03 14:47:35 +08:00
CCLOG ( " cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the SpriteFrameCache. This frame will not be added to the animation. " , name . c_str ( ) , spriteFrameName . c_str ( ) ) ;
2012-04-19 14:35:52 +08:00
continue ;
}
2013-12-07 14:22:03 +08:00
float delayUnits = entry [ " delayUnits " ] . asFloat ( ) ;
Value & userInfo = entry [ " notification " ] ;
2012-04-19 14:35:52 +08:00
2014-05-13 17:08:30 +08:00
AnimationFrame * animFrame = AnimationFrame : : create ( spriteFrame , delayUnits , userInfo . getType ( ) = = Value : : Type : : MAP ? userInfo . asValueMap ( ) : ValueMapNull ) ;
2012-04-19 14:35:52 +08:00
2013-12-05 10:35:10 +08:00
array . pushBack ( animFrame ) ;
2012-04-19 14:35:52 +08:00
}
2013-12-07 14:22:03 +08:00
float delayPerUnit = animationDict [ " delayPerUnit " ] . asFloat ( ) ;
2013-12-03 14:47:35 +08:00
Animation * animation = Animation : : create ( array , delayPerUnit , loops . getType ( ) ! = Value : : Type : : NONE ? loops . asInt ( ) : 1 ) ;
2012-04-19 14:35:52 +08:00
animation - > setRestoreOriginalFrame ( restoreOriginalFrame ) ;
2013-07-12 06:24:23 +08:00
AnimationCache : : getInstance ( ) - > addAnimation ( animation , name ) ;
2012-04-19 14:35:52 +08:00
}
}
2014-01-06 20:23:45 +08:00
void AnimationCache : : addAnimationsWithDictionary ( const ValueMap & dictionary , const std : : string & plist )
2012-04-19 14:35:52 +08:00
{
2013-12-03 14:47:35 +08:00
if ( dictionary . find ( " animations " ) = = dictionary . end ( ) )
{
2013-06-20 14:13:12 +08:00
CCLOG ( " cocos2d: AnimationCache: No animations were found in provided dictionary. " ) ;
2012-04-19 14:35:52 +08:00
return ;
}
2013-12-03 14:47:35 +08:00
const Value & animations = dictionary . at ( " animations " ) ;
2012-04-19 14:35:52 +08:00
unsigned int version = 1 ;
2013-12-03 14:47:35 +08:00
if ( dictionary . find ( " properties " ) ! = dictionary . end ( ) )
2012-04-19 14:35:52 +08:00
{
2013-12-04 17:46:57 +08:00
const ValueMap & properties = dictionary . at ( " properties " ) . asValueMap ( ) ;
2013-12-03 14:47:35 +08:00
version = properties . at ( " format " ) . asInt ( ) ;
2013-12-04 17:46:57 +08:00
const ValueVector & spritesheets = properties . at ( " spritesheets " ) . asValueVector ( ) ;
2012-04-19 14:35:52 +08:00
2013-12-20 05:34:41 +08:00
for ( const auto & value : spritesheets ) {
2014-01-06 20:23:45 +08:00
std : : string path = FileUtils : : getInstance ( ) - > fullPathFromRelativeFile ( value . asString ( ) , plist ) ;
SpriteFrameCache : : getInstance ( ) - > addSpriteFramesWithFile ( path ) ;
2013-12-20 05:34:41 +08:00
}
2012-04-19 14:35:52 +08:00
}
switch ( version ) {
case 1 :
2013-12-04 17:46:57 +08:00
parseVersion1 ( animations . asValueMap ( ) ) ;
2012-04-19 14:35:52 +08:00
break ;
case 2 :
2013-12-04 17:46:57 +08:00
parseVersion2 ( animations . asValueMap ( ) ) ;
2012-04-19 14:35:52 +08:00
break ;
default :
2013-07-20 13:01:27 +08:00
CCASSERT ( false , " Invalid animation format " ) ;
2012-04-19 14:35:52 +08:00
}
}
/** Read an NSDictionary from a plist file and parse it automatically for animations */
2013-11-06 11:02:03 +08:00
void AnimationCache : : addAnimationsWithFile ( const std : : string & plist )
2012-04-19 14:35:52 +08:00
{
2013-11-06 11:02:03 +08:00
CCASSERT ( plist . size ( ) > 0 , " Invalid texture file name " ) ;
2012-04-19 14:35:52 +08:00
2013-07-12 06:24:23 +08:00
std : : string path = FileUtils : : getInstance ( ) - > fullPathForFilename ( plist ) ;
2013-12-04 17:50:57 +08:00
ValueMap dict = FileUtils : : getInstance ( ) - > getValueMapFromFile ( path ) ;
2012-04-19 14:35:52 +08:00
2013-12-03 14:47:35 +08:00
CCASSERT ( ! dict . empty ( ) , " CCAnimationCache: File could not be found " ) ;
2012-04-19 14:35:52 +08:00
2014-01-06 20:23:45 +08:00
addAnimationsWithDictionary ( dict , plist ) ;
2012-03-16 13:42:53 +08:00
}
NS_CC_END