【Cocos2dx工具之Cocostudio界面编辑器】
三
写在前面——
如果转载请注明出处,谢谢大家支持
同步更新51CTO博客
——Forward
我的微博——秦京一梦
QQ技术交流群——forTheDream(225117179)
Hello,大家好,Forward新一期的博客又和大家见面了。接着上一期《【Cocos2dx工具——Cocostudio界面编辑器】二》末尾所提出的问题,我们往下说——
1、CocoGUILIB的结构是什么样子呢?
2、从文件解析到控件创建,CocoGUILIB是如何实现的呢?
3、有关Touch事件又是如何接收与处理呢?
4、CocoGUILIB是如何工作的呢?
好的,带着以上几个问题,我们正式开始学习CocoGUILIB库。这里我们依然使用《二》中用到的那个例子UIEditorDemo来说明。
按照Forward学习的习惯——在学习一样新知识时,最好对整体先有一个宏观哪怕浅显的认识也好,这里Forward根据自己里的理解,绘制了一个类图(个人UML不是特别熟悉,有使用不恰当的符号,大家多多指正)
图 1
首先需要说明的是,Forward在完成这篇博客的时候,使用额CocoGUILIB库版本号是0.1.3。
图 2
如上图所示,CocoGUILIB库的核心主要是一个UISystem类,它主要依靠内部的InputLayer类来接受Touch事件(具体我们后面会详细描述)、CocoRootWidget(通过这个Widget来保存所有包括在它之上的控件UI),其余两个(UIScene和UIManager是协助完成Widget控件的控制和Touch事件的分发的,具体的话我们可以看源代码),初次以外,UISystem外部还依赖与一个CSJsonDictionary类,这个类是对Json协议的一个封装,使用起来更加方便罢了(Forward曾经在一篇博客《Protocolbuffer介绍》中有提到过Json协议,后期Forward会根据Json的相关知识完成一篇博客)。
图 3
再看上面类图,CocoRootWidget最终继承自CocoWidget,这就是一个逻辑概念上的一个控件,具体的控件当前版本支持CocoButton、CocoCheckBox、CocoImageView、CocoLabel、CocoLabelAtlas、CocoLoadingBar、CocoPanel、CocoScrollView、CocoSlider、CocoTextArea、CocoTextButton、CocoTextField等,相信后续会有更多更好用的控件出炉^_^。
了解了逻辑控件之后呢,我们再往下看,可以看到有一个CCRenderNode模块,很容易想到,这一模块就是具体的控件加载所需的一个模块,包括CClipAbleLayerColor、CClipAbleSprite、CLabelAtlas、CPrimitivesNode、CTextField、GUINodeRGBA等,追踪源代码,我们可以发现,这几个自定义类又都分别继承自Cocos2dx的一些CCNode或其子类,这样就很清楚了,其实一个完成的UI在加载的时候 其实都是一层层的CCNode堆叠而成的。
经过以上的分析,相信大家已经对CocoGUILIB库有了一个整体上的认识,下面我们接着博客开题提到的问题继续学习——
大家是否还记得,在《Cocos2dx工具之Cocostudio界面编辑器一》中我们就提到通过界面编辑器编辑之后我们会得到一个Json格式的UI文件。今天我们通过上面的学习,相信不用我再赘述,大家脑海中已经有了一个下面这样一个流程图——
图 4
流程图可能并不美观,但它足以说明问题了,哈哈。
好了知道了上面这些以后,或许我们应该关注一下对于UI来说最为重要的一个特性就是交互性的实现,当然UI来说交互一般都是通过点击、拖拽等事件来完成。
对于UI交互,我们的CocoGUILIB是依赖一个InputLayer层来实现的,上面已经提到。
virtualbool ccTouchBegan(cocos2d::CCTouch*pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchMoved(cocos2d::CCTouch *pTouch,cocos2d::CCEvent *pEvent);
virtual void ccTouchEnded(cocos2d::CCTouch *pTouch,cocos2d::CCEvent *pEvent);
virtual void ccTouchCancelled(cocos2d::CCTouch*pTouch, cocos2d::CCEvent *pEvent);
正如我们所说的,InputLayer中重写了这几种Touch事件,那么他们的注册在哪里呢?我们打开UISystem.cpp可以在resetSystem接口中看到其注册如下:
this->m_pInputLayer =InputLayer::createWithUISystem(this);
this->m_pInputLayer->retain();
this->m_pInputLayer->setTouchEnabled(true);
cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this->m_pInputLayer,nPriority, true);
这样,当InputLayer这个层收到Touch事件之后,他就将根据事件的不同调用UISystem几种不同接口:
bool InputLayer::ccTouchBegan(cocos2d::CCTouch*pTouch, cocos2d::CCEvent *pEvent)
{
return this->m_pUISystem->onTouchPressed(pTouch);
}
void InputLayer::ccTouchMoved(cocos2d::CCTouch*pTouch, cocos2d::CCEvent *pEvent)
{
this->m_pUISystem->onTouchMoved(pTouch);
}
void InputLayer::ccTouchEnded(cocos2d::CCTouch*pTouch, cocos2d::CCEvent *pEvent)
{
this->m_pUISystem->onTouchReleased(pTouch);
}
voidInputLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch,cocos2d::CCEvent *pEvent)
{
this->m_pUISystem->onTouchCanceled(pTouch);
}
UISystem在收到不同的消息时再通过InputManager将这个Touch事件传递给这个UISystem中的每一个需要获取该消息的Widget控件。这就是UISystem的Touch事件处理的全过程了。
哈哈,不早了,明天还得上班,Forward的本次博客就先写到这里了,拜拜~~