子のオブジェクトまで拡縮・アルファ値などを反映させる

自分に追加されたすべての子どもに対して、
拡縮・アルファ値を反映させるCCSprite派生クラスです。
再起的に呼び出すので、子どもの子どもでも変更が効きます。
パーツアニメーションなどに便利かと思います。
ver 3.x用に翻訳したら需要あるのかなあ

```cpp:SpriteCluster.h
#ifndef __SpriteCluster__
#define __SpriteCluster__

#import "cocos2d.h"

class SpriteCluster:public cocos2d::CCSprite{
    //If true the "m_isAlone ~" These flags, cut off interference from parents.
    bool m_isAloneProperty;
    bool m_isAloneAction;
    
    //If true the "m_isHandsOffChild~" These flags, cut off the interference to the children.
    bool m_isHandsOffChildProperty;
    bool m_isHandsOffChildAction;
    
    bool m_isPaused;
public:
    static SpriteCluster* create();
    static SpriteCluster* create(const char *pszFileName);
    static SpriteCluster* create(const char *pszFileName, const cocos2d::CCRect& rect);
    virtual bool init(void);
    virtual void pause();
    virtual void resume();
    
    virtual void setShader(const char* key);
    virtual void setColor(cocos2d::ccColor3B _color);
    virtual void setOpacity(GLubyte opacity);
    virtual void resetRotateAndScale();
    
	void setChildStatus(CCNode* pChild);
    virtual void addChild(CCNode *pChild);
    virtual void addChild(CCNode *pChild, int zOrder);
    virtual void addChild(CCNode *pChild, int zOrder, int tag);
    
    virtual void stopAction();
    
    void setAloneProperty( bool st ){ m_isAloneProperty = st; }
    bool isAloneProperty(){ return m_isAloneProperty; }

    void setAloneAction( bool st ){ m_isAloneAction = st; }
    bool isAloneAction(){ return m_isAloneAction; }

    void setHandsOffChildProperty( bool st ){ m_isHandsOffChildProperty = st; }
    bool isHandsOffChildProperty(){ return m_isHandsOffChildProperty; }
    
    void setHandsOffChildAction( bool st ){ m_isHandsOffChildAction = st; }
    bool isHandsOffChildAction(){ return m_isHandsOffChildAction; }
    
    bool isPaused(){ return m_isPaused; }
};


#endif /* defined(__SpriteCluster__) */

```

```c++:SpriteCluster.cpp
#import "SpriteCluster.h"

using namespace cocos2d;

SpriteCluster* SpriteCluster::create(){
    SpriteCluster* sprite = new SpriteCluster();
    sprite->autorelease();
    sprite->init();
    return sprite;
}

SpriteCluster* SpriteCluster::create(const char *pszFileName){
    SpriteCluster* sprite = new SpriteCluster();
    sprite->autorelease();
    sprite->init();
    sprite->CCSprite::initWithFile(pszFileName);
    return sprite;
}
SpriteCluster* SpriteCluster::create(const char *pszFileName, const cocos2d::CCRect &rect){
    SpriteCluster* sprite = new SpriteCluster();
    sprite->autorelease();
    sprite->init();
    sprite->CCSprite::initWithFile(pszFileName, rect);
    return sprite;
}

bool SpriteCluster::init(){
    CCSprite::init();
    m_isAloneProperty = false;
    m_isAloneAction = false;
    m_isHandsOffChildProperty = false;
    m_isHandsOffChildAction = false;
    m_isPaused=false;
    return true;
}

void SpriteCluster::pause(){
    this->pauseSchedulerAndActions();
    if( isHandsOffChildAction() ) return;
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneAction() )child->pause();
            }else{
                CCNode* node = dynamic_cast<CCNode*>(access);
                if( node != NULL ){
                    node->pauseSchedulerAndActions();
                }
            }
        }
    }
    m_isPaused=true;
}

void SpriteCluster::resume(){
    this->resumeSchedulerAndActions();
    
    if( isHandsOffChildAction() ) return;
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneAction() )child->resume();
            }else{
                CCNode* node = dynamic_cast<CCNode*>(access);
                if( node != NULL ){
                    node->resumeSchedulerAndActions();
                }
            }
        }
    }
    m_isPaused=false;
}

void SpriteCluster::setShader(const char *key){
    this->setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(key));
    this->getShaderProgram()->use();
    if( isHandsOffChildProperty() ) return;
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){            
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneProperty() )child->setShader(key);
            }else{
                CCSprite* sprite = dynamic_cast<CCSprite*>(access);
                if( sprite != NULL ){
                    sprite->setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(key));
                    sprite->getShaderProgram()->use();
                }
            }
        }
    }
}

void SpriteCluster::setColor(cocos2d::ccColor3B _color){
    CCSprite::setColor(_color);
    if( isHandsOffChildProperty() ) return;
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneProperty() ) child->setColor(_color);
            }else{
                CCRGBAProtocol* sprite = dynamic_cast<CCRGBAProtocol*>(access);
                if( sprite != NULL ){
                    sprite->setColor(_color);
                }
            }
        }
    }
}

void SpriteCluster::setOpacity(GLubyte opacity){
    CCSprite::setOpacity(opacity);
    
    if( isHandsOffChildProperty() ) return;
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){            
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneProperty() )
                    child->setOpacity(opacity);
            }else{
                CCRGBAProtocol* sprite = dynamic_cast<CCRGBAProtocol*>(access);
                if( sprite != NULL ){
                    sprite->setOpacity(opacity);
                }
            }
        }
    }
}

void SpriteCluster::resetRotateAndScale(){
    CCSprite::setRotation(0);
    CCSprite::setScale(1);
    
    if( isHandsOffChildProperty() ) return;
    
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){            
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneProperty())
                child->resetRotateAndScale();
            }else{
                CCNode* node = dynamic_cast<CCNode*>(access);
                if( node != NULL ){
                    node->setRotation(0);
                    node->setScale(1);
                }
            }
        }
    }
}

void SpriteCluster::setChildStatus(CCNode* pChild) {
    SpriteCluster* child = dynamic_cast<SpriteCluster*>(pChild);
    if( child && child->isAloneProperty() ){
		return;
	}
	
	if(getShaderProgram()
	   && pChild->getShaderProgram() != getShaderProgram()) {
		pChild->setShaderProgram(getShaderProgram());
		pChild->getShaderProgram()->use();
	}
	
	CCRGBAProtocol* pChildRGBA = dynamic_cast<CCRGBAProtocol*>(pChild);
	if(pChildRGBA) {
		pChildRGBA->setColor(getColor());
		pChildRGBA->setOpacity(getOpacity());
	}
}

void SpriteCluster::addChild(CCNode *pChild){
    CCSprite::addChild(pChild);
}

void SpriteCluster::addChild(CCNode *pChild, int zOrder){
    CCSprite::addChild(pChild, zOrder);
}

void SpriteCluster::addChild(CCNode *pChild, int zOrder, int tag){
	if( !isHandsOffChildProperty() )setChildStatus(pChild);
    
    CCSprite::addChild(pChild, zOrder, tag);
}

void SpriteCluster::stopAction(){
    stopAllActions();
    if( isHandsOffChildAction() ) return;
    if( this->getChildrenCount() > 0 ){
        CCObject* access;
        CCARRAY_FOREACH(getChildren(), access){            
            SpriteCluster* child = dynamic_cast<SpriteCluster*>(access);
            if( child != NULL ){
                if( !child->isAloneAction() )child->stopAction();
            }else{
                CCNode* node = dynamic_cast<CCNode*>(access);
                if( node != NULL ){
                    node->stopAllActions();
                }
            }
        }
    }
}
```