-
本帖最后由 dempsey 于 2013-8-27 00:43 编辑 *
个人觉得 Cocostudio的UI的系统 还是可以的 毕竟是刚刚起步,还有很多空间需要完善,继续加油!!!且本人c++功底不是一般的差 偶尔看看源码 权当学习了。 其实学习一个新的UI系统,可能我们最容易接触的就是按钮,所以TestCpp的例子就是一个Button的效果展示。 下面我们跟踪学习下在按下按钮和释放按钮后都发生了什么。 当进入一个场景后,如果要让场景上Layer响应触摸事件,我们必须给当前Layer setTouchEnabled为True.这个是一切触摸事件的前提。。 首先 看例子创建UIButton的代码
UIButton *button = UIButton::create();
button->setTouchEnable(true);
button->setTextures("cocosgui/animationbuttonnormal.png", "cocosgui/animationbuttonpressed.png", "");
button->setPosition(ccp(widgetSize.width / 2.0f, widgetSize.height / 2.0f));
button->addPushDownEvent(this, coco_pushselector(UIButtonTest::touchBeganEvent));
button->addMoveEvent(this, coco_moveselector(UIButtonTest::touchMovedEvent));
button->addReleaseEvent(this, coco_releaseselector(UIButtonTest::touchEndedEvent));
m_pUiLayer->addWidget(button);
其中: //按下事件
button->addPushDownEvent(this, coco_pushselector(UIButtonTest::touchBeganEvent));
// 移动事件
button->addMoveEvent(this, coco_moveselector(UIButtonTest::touchMovedEvent));
//松开事件
button->addReleaseEvent(this, coco_releaseselector(UIButtonTest::touchEndedEvent));
在所有的控件都是继承于 UIWidget,在UIWidget 里 我们看到
typedef void (CCObject::*SEL_PushEvent)(CCObject*);
typedef void (CCObject::*SEL_MoveEvent)(CCObject*);
typedef void (CCObject::*SEL_ReleaseEvent)(CCObject*);
typedef void (CCObject::*SEL_CancelEvent)(CCObject*);
#define coco_pushselector(_SELECTOR) (cocos2d::extension::SEL_PushEvent)(&_SELECTOR)
#define coco_moveselector(_SELECTOR) (cocos2d::extension::SEL_MoveEvent)(&_SELECTOR)
#define coco_releaseselector(_SELECTOR) (cocos2d::extension::SEL_ReleaseEvent)(&_SELECTOR)
#define coco_cancelselector(_SELECTOR) (cocos2d::extension::SEL_CancelEvent)(&_SELECTOR)
virtual void addPushDownEvent(CCObject* target,SEL_PushEvent selector);
virtual void addMoveEvent(CCObject* target,SEL_MoveEvent selector);
virtual void addReleaseEvent(CCObject* target,SEL_ReleaseEvent selector);
virtual void addCancelEvent(CCObject* target,SEL_CancelEvent selector);
这里我们举按下这个动作进行分析,其他 移动 和 松手动作 类似。
void UIWidget::addPushDownEvent(CCObject*target, SEL_PushEvent selector)
{
m_pPushListener = target;
m_pfnPushSelector = selector;
}
这是向父类UIWidget 注册触摸事件回调 函数。当我们触目屏幕时,UILayer 设置 setTouchEnabled 为True时,cocos2d 为帮我们将事件传递到UILayers上,看UILayer源码:
bool UILayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
if (m_pInputManager && m_pInputManager->onTouchBegan(pTouch))
{
return true;
}
// CCLOG("ui layer began");
return false;
}
void UILayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
m_pInputManager->onTouchMoved(pTouch);
// CCLOG("ui layer move");
}
void UILayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
m_pInputManager->onTouchEnd(pTouch);
// CCLOG("ui layer end");
}
这里 m_pInputManager 为studio自己设计管理输入和Wideget管理接口的类 定义如下:
class UIInputManager
{
public:
UIInputManager();
~UIInputManager();
void registWidget(UIWidget* widget);
void uiSceneHasChanged();
void sortWidgets(UIWidget* widget);
void sortRootWidgets(UIWidget* root);
void removeManageredWidget(UIWidget* widget);
UIWidget* checkEventWidget(const CCPoint &touchPoint);
void addCheckedDoubleClickWidget(UIWidget* widget);
void update(float dt);
bool onTouchBegan(CCTouch* touch);
bool onTouchMoved(CCTouch* touch);
bool onTouchEnd(CCTouch* touch);
bool onTouchCancelled(CCTouch* touch);
void setRootWidget(UIWidget* root);
UIWidget* getRootWidget();
在UILayer 上 通过m_pInputManager 来传递事件,如下:
bool UIInputManager::onTouchBegan(CCTouch* touch)
{
touchBeganedPoint.x = touch->getLocation().x;
touchBeganedPoint.y = touch->getLocation().y;
UIWidget* hitWidget = checkEventWidget(touchBeganedPoint);
if (!hitWidget)
{
m_pCurSelectedWidget = NULL;
return false;
}
m_pCurSelectedWidget = hitWidget;
hitWidget->onTouchBegan(touchBeganedPoint);
m_bTouchDown = true;
return true;
}
其中 checkEventWidget 这个函数是来检测触摸的点是否在UIWidget上,如果没有则返回false,如果 if (m_pInputManager && m_pInputManager->onTouchBegan(pTouch)) 返回false 则继续向下传递触摸事件。
如果hitWidget 不为NULL,则调用响应事件,hitWidget->onTouchBegan(touchBeganedPoint);,返回True 表示消费了此事件。
onTouchBegan 就会到 UIWidget的函数里
void UIWidget::onTouchBegan(const CCPoint &touchPoint)
{
setFocus(true);
m_touchStartPos.x = touchPoint.x;
m_touchStartPos.y = touchPoint.y;
if (m_pWidgetParent)
{
m_pWidgetParent->checkChildInfo(0,this,touchPoint);
}
pushDownEvent();
}
其中 setFouch(true);函数
void UIWidget::setFocus(bool fucos)
{
if (fucos == m_bFocus)
{
return;
}
m_bFocus = fucos;
if (m_bFocus)
{
setPressState(WidgetStateSelected);
}
else
{
setPressState(WidgetStateNormal);
}
}
两个作用:
设置 成员变量为 true;
改变按钮状态
至于 checkChildInfo 函数
void UIWidget::checkChildInfo(int handleState, UIWidget *sender,const CCPoint &touchPoint)
{
if (m_pWidgetParent)
{
m_pWidgetParent->checkChildInfo(handleState,sender,touchPoint);
}
}
应该是用于容器类型控件的判断 对于UIButton 没有实现这个函数 就可以不考虑了
到 pushDownEvent(); 函数了
void UIWidget::pushDownEvent()
{
if (m_pPushListener && m_pfnPushSelector)
{
(m_pPushListener->*m_pfnPushSelector)(this);
}
}
就会向我们之前的注册的回调函数进行回调了。
然后就回到 这里啦!!!
void UIButtonTest::touchBeganEvent(CCObject *pSender)
{
m_pDisplayValueLabel->setText(CCString::createWithFormat("Touch Down")->getCString());
}
Ok Game Over !!!