CCGestureRecognizer/CCGestureListener, CCRenderTextureMutable & CCInputEvent/CCInputListener for cocos2dx 1.x

Here are some extensions I developed/modified during the development of my recent projects

Source & simple examples - https://github.com/darkfall/cocos2dx-extensions

Gesture Recognizers(iOS Only)

  • CCGestureRecognizer: singleton that dispatches gesture events, based on UIGestureRecognizer*, you must add window.rootViewController = viewController in your AppController.mm manually to use this(as I’m using [[UIApplication sharedApplication] keyWindow].rootViewController.view to add UIGestureRecognizers)
  • CCGestureListener: Gesture event listener, inherit from this class and add “this” to CCGestureRecognizer to listen to gesture events

example:

class MyGestureListener: public CCNode, public CCGestureListener {
public:
    MyGestureRecognizer() {
        CCGestureRecognizer::Instance().attachListener(this);

        mPinchRecognizer = CCGestureRecognizer::Instance().addPinchRecognizer();
    }
    virtual ~MyGestureRecognizer() {
        CCGestureRecognizer::Instance().removeListener(this);

        CCGestureRecognizer::Instance().removeRecognizer(mPinchRecognizer);
    }

    virtual void onPinch(unsigned long which, float v, float scale, float x, float y) {
        printf("on pinch!");
    }

private:
    unsigned long mPinchRecognizer;
};

Mutable Texture2D and RenderTexture(Tested on iOS, Windows and OS X):

  • CCTexture2DMutable Created by Lam Hoang Pham and Improved by Manuel Martinez-Almeida.
  • CCRenderTextureMutable is a CCRenderTexture extension that uses CCTexture2DMutable to render the content, so you can make changes to the rendered texture(for posteffects etc)

example:

 CCTexture2DMutable* texture = mRenderLayer->getTexture();
int width = texture->getContentSize().width;
int height = texture->getContentSize().height;
unsigned int* data = texture->getDataRGBA();
assert(data);
for(int y = 0; y < height; ++y) {
    for(int x = 0; x < width; ++x) {
        uint32 color = 
        data[y * texture->getPixelsWide() + x];

        uint8 r = COLOR_GETR_RGBA(color);
        uint8 g = COLOR_GETG_RGBA(color);
        uint8 b = COLOR_GETB_RGBA(color);
        uint8 a = COLOR_GETA_RGBA(color);

        if(a == 0)
            continue;

        uint8 avg = 0.3 * r + 0.59 * g + 0.11 * b;

        data[y * texture->getPixelsWide() + x] = COLOR_RGBA(avg, avg, avg, a);
    }
}
texture->putDataRGBA();

Keyboard & Mouse Events(OS X and Windows only):

I uses cocos2dx for mac from from http://www.cocos2d-x.org/boards/6/topics/10352

  • CCInputEvent: represent a specific input event, like CCMouseEvent, CCKeyEvent
  • CCInputDispatcher: Singleton input event dispatcher, platform implementations call methods in this class to dispatch input events
  • CCInputListener: input event listener, inherit from this class and add “this” to CCInputDispatcher to listen to input events.

Note: return true on event callbacks means you want to occupy the event and the event would not be delivered further

This extension requires modified platform implementations, see platform folder for more details.

example:

class MyInputListener: public cocos2d::CCInputListener, public cocos2d::CCNode {
public:
    MyInputListener();
    virtual ~MyInputListener();

    virtual bool onMouseEvent(const cocos2d::CCMouseEvent& evt);
    virtual bool onKeyEvent(const cocos2d::CCKeyEvent& evt);
};

MyInputListener::MyInputListener() {
    CCInputDispatcher::Instance().addListener(this, 1);
}

MyInputListener::~MyInputListener() {
    CCInputDispatcher::Instance().removeListener(this);
}

bool MyInputListener::onMouseEvent(const CCMouseEvent& evt) {
    switch(evt.state) {
        case CCMouse::Press:
            printf("mouse button %d pressed!\n", (int)evt.button);
            break;

        case CCMouse::Release:
            printf("mouse button %d released!\n", (int)evt.button);
            break;

        default:
            break;
    }
    /* return true here to occupy the event */
    return false;
}

bool MyInputListener::onKeyEvent(const CCKeyEvent& evt) {
    switch (evt.state) {
        case CCKey::Press:
            printf("key %c pressed!\n", evt.toCharCode());
            break;

        case CCKey::Release:
            printf("key %c released!\n", evt.toCharCode());
            break;

        default:
            break;
    }
    /* return true here to occupy the event */
    return false;
}

Can you post the source codes? Thanks.

Robert Bu wrote:

Here are some extensions I developed/modified during the development of my recent projects

Thanks, it’s a very helpful!
I ported Gaussian blur using your extensions. But in void CCTexture2DMutable::updateData() and void CCRenderTextureMutable::end(bool bIsTOCacheTexture) need to add CC_TARGET_PLATFORM !=CC_PLATFORM_ANDROID

How to use:

CCRenderTextureMutable *texture = CCRenderTextureMutable::renderTextureWithWidthAndHeight(400, 400);
texture->beginWithClear(1, 1, 1, 0);
image->visit();
texture->end();

AWTextureFilter txrFilter;
txrFilter.blur(texture->getTexture(), 1);
CCSprite* mFragment = CCSprite::spriteWithTexture(texture->getTexture());

Alex Zhd wrote:

Robert Bu wrote:
> Here are some extensions I developed/modified during the development of my recent projects
>
Thanks, it’s a very helpful!
I ported Gaussian blur using your extensions. But in void CCTexture2DMutable::updateData() and void CCRenderTextureMutable::end(bool bIsTOCacheTexture) need to add CC_TARGET_PLATFORM !=CC_PLATFORM_ANDROID
>
How to use:
[…]

Thank you! I’ve commit the change

Hi,

I am trying to get my head around the Input Dispatcher. You declare and implement the method CCEGLView::dispatchInputEvents() but no one ever calls that method? How is this? I could not find any reference to the method other than the declaration and implementation.

Hi Alex, thanks for share your implementation .

Im try to test your code , and i don know if its normal , i configure the method
CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);

and my sprite with blur effect is very small , 1/4 of the screen , what im doing wrong?

Thanks

Alex Zhd wrote:

Robert Bu wrote:
> Here are some extensions I developed/modified during the development of my recent projects
>
Thanks, it’s a very helpful!
I ported Gaussian blur using your extensions. But in void CCTexture2DMutable::updateData() and void CCRenderTextureMutable::end(bool bIsTOCacheTexture) need to add CC_TARGET_PLATFORM !=CC_PLATFORM_ANDROID
>
How to use:
[…]

Can you show your code?

Moc Interactive wrote:

Hi Alex, thanks for share your implementation .
>
Im try to test your code , and i don know if its normal , i configure the method
CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
>
and my sprite with blur effect is very small , 1/4 of the screen , what im doing wrong?
>
Thanks

Hi Alex

here its:

@
CCSprite land1 = CCSprite::spriteWithFile;
CCRenderTextureMutable
texture = CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
texture~~>beginWithClear;
land1~~>visit();
texture->end();

AWTextureFilter txrFilter;
txrFilter.blur(texture->getTexture(), 1);
CCSprite* mFragment = CCSprite::spriteWithTexture(texture->getTexture());@

after this texture effect , appear a small image, some 1/4 of original sprite

Alex Zhd wrote:

Can you show your code?
>
Moc Interactive wrote:
> Hi Alex, thanks for share your implementation .
>
> Im try to test your code , and i don know if its normal , i configure the method
> CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
>
> and my sprite with blur effect is very small , 1/4 of the screen , what im doing wrong?
>
> Thanks

Sorry for the long answer. Are you solved this problem?

Moc Interactive wrote:

Hi Alex
>
here its:
>
@
CCSprite land1 = CCSprite::spriteWithFile;
CCRenderTextureMutable
texture = CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
texture~~>beginWithClear;
land1~~>visit();
texture->end();
>
AWTextureFilter txrFilter;
txrFilter.blur(texture->getTexture(), 1);
CCSprite* mFragment = CCSprite::spriteWithTexture(texture->getTexture());@
>
after this texture effect , appear a small image, some 1/4 of original sprite
>
Alex Zhd wrote:
> Can you show your code?
>
> Moc Interactive wrote:
> > Hi Alex, thanks for share your implementation .
> >
> > Im try to test your code , and i don know if its normal , i configure the method
> > CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
> >
> > and my sprite with blur effect is very small , 1/4 of the screen , what im doing wrong?
> >
> > Thanks

No alex , the image resize to 1/4 of the original , do you have some code yours , what the size of the images that you use?

thanks

Alex Zhd wrote:

Sorry for the long answer. Are you solved this problem?
>
>
Moc Interactive wrote:
> Hi Alex
>
> here its:
>
> @
> CCSprite land1 = CCSprite::spriteWithFile;
> CCRenderTextureMutable
texture = CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
> texture~~>beginWithClear;
> land1~~>visit();
> texture->end();
>
> AWTextureFilter txrFilter;
> txrFilter.blur(texture->getTexture(), 1);
> CCSprite* mFragment = CCSprite::spriteWithTexture(texture->getTexture());@
>
> after this texture effect , appear a small image, some 1/4 of original sprite
>
> Alex Zhd wrote:
> > Can you show your code?
> >
> > Moc Interactive wrote:
> > > Hi Alex, thanks for share your implementation .
> > >
> > > Im try to test your code , and i don know if its normal , i configure the method
> > > CCRenderTextureMutable::renderTextureWithWidthAndHeight(320, 480);
> > >
> > > and my sprite with blur effect is very small , 1/4 of the screen , what im doing wrong?
> > >
> > > Thanks

Hello, looked at ur code @ gestureRecognizers.
I am so frustrated, why did u chose listeners idea?
It must be attached to layer as it’s done in UIKit.

I implemented gestureRecognizers and it worked fine on iOS. The problem with that is that it doesn’t work on Android. Based on that post:

I made the following implementation on cocos2dx:

void TestScene::ccTouchesMoved(CCSet\* touches, CCEvent\* event){

\#define CLAMP (x,y,z) MIN (MAX(x,y),z)

CCSetIterator it;
 it = touches~~\>begin;
 if2)
    {
        // get positions of touches
        CCTouch\* touch1 = (CCTouch\*)(\*it);

        it ++;
        CCTouch\* touch2 = (CCTouch\*)(\*it);

        CCPoint position1 = touch1-\>getLocationInView();
        position1 = CCDirector::sharedDirector()-\>convertToGL(position1);

        CCPoint oldPosition1 = touch1-\>getPreviousLocationInView();
        oldPosition1 = CCDirector::sharedDirector()-\>convertToGL(oldPosition1);

        CCPoint position2 = touch2-\>getLocationInView();
        position2 = CCDirector::sharedDirector()-\>convertToGL(position2);

        CCPoint oldPosition2 = touch2-\>getPreviousLocationInView();
        oldPosition2 = CCDirector::sharedDirector()-\>convertToGL(oldPosition2);

        // calculate scale factor
    float distance = ccpDistance(position1, position2);
    float oldDistance = ccpDistance(oldPosition1, oldPosition2);
        float factor = (distance  0 || oldDistance == 0) ? 1.0f : distance / oldDistance;
 float oldScale = lamina~~\>getScale();
 float newScale = CLAMP (oldScale\*factor, 1, 3);
 testSprite~~\>setScale;
 // calculate translation
 CCPoint newPos1 = ccpAdd, oldPosition1), newScale/oldScale));
 CCPoint newPos2 = ccpAdd, oldPosition2), newScale/oldScale));
 testSprite~~\>setPosition ( ccpMidpoint(newPos1, newPos2));

}
\#undef CLAMP
}

Does it work for Android ?

I’m having trouble getting the keyboard input working. I’m using the version of Cocos2d-x in the Gles11 branch of the github repository, to make it feasible to integrate these extensions. But now I can’t seem to actually get a simple keyboard test working. I’ve tried a couple of different things, so this has turned a tad ugly, but I’m trying to modify HelloWorld to see keyboard events.

I just added the sample inputListner to helloworld. Here’s the class in HelloWorld.h:

using namespace cocos2d;

class MyInputListener: public /*cocos2d::*/CCInputListener, public /*cocos2d::*/CCNode {
public:
    MyInputListener(CCSprite* pPlayer1); //I added a sprite here just trying to get something to work,
                                         //as I've never done anything with cocos2d before
    virtual ~MyInputListener();

    cocos2d::CCSprite* pPlayer;
    virtual bool onKeyEvent(const /*cocos2d::*/CCKeyEvent& evt);
};

And have added this to HelloWorld::init() :

//Input listener
    MyInputListener* inputListener = new MyInputListener(pPlayer);
    CCInputDispatcher& dispatch = CCInputDispatcher::Instance();
    dispatch.addListener(inputListener, 1);
    this->addChild(inputListener);

And then for onKeyEvent, I’ve tried a bunch of different things to get any sort of response:

bool MyInputListener::onKeyEvent(const CCKeyEvent& evt) {
   //CCPoint playerPos;
   //CCSprite* pPlayer;
    HelloWorld* hello;
    pPlayer->setPositionX(pPlayer->getPositionX()+10);
    hello = (HelloWorld*)getChildByTag(5);
    hello->step(0);

    switch (evt.state) {
        case CCKey::Press:
            printf("key %c pressed!\n", evt.toCharCode());
            //pPlayer = (CCSprite*)getChildByTag(10);
            //playerPos = pPlayer->getPosition();
            //playerPos.x += 20;
            //pPlayer->setPosition(playerPos);
            pPlayer->setPositionX(pPlayer->getPositionX()+10);
            hello = (HelloWorld*)getChildByTag(5);
            if (hello == 0)
                std::exit(0);
            hello->keyIsPushed = true;
            hello->removeChildByTag(10, true);
            break;

        case CCKey::Release:
   //         printf("key %c released!\n", evt.toCharCode());
            //pPlayer = (CCSprite*)getChildByTag(10);
            //playerPos = pPlayer->getPosition();
            //playerPos.x += 20;
            //pPlayer->setPosition(playerPos);
            //pPlayer->setPositionX(pPlayer->getPositionX()+10);
            hello = (HelloWorld*)getChildByTag(5);
            if (hello == 0)
                std::exit(0);
            hello->keyIsPushed = false;
            break;

        default:
            break;
    }
    return false;
}

I’m a complete beginner with cocos2d-x, this is my first attempt at using it, so I may be missing something obvious. Or maybe the older version of the engine I found isn’t actually compatible with Robert Bu’s extension? I figure it’s more likely that I’m doing something wrong though =P So I’d greatly appreciate any help!