cocostudio 提供ui编辑工具,以及相应的控件,可以衔接到cocos2dx的引擎。
一个测试工程可参考:http://blog.csdn.net/chenjiayi_yun/article/details/22595387
这个测试工程相较于一般的Cocos2d-x程序多了两个库,第一个是UI库,第二个是动画库。本文说的是界面库。
设计上:
(1)ui库的控件是继承于CocoWidget,每个CocoWidget有成员cocos2d::CCNode* m_pRenderNode,是真正的渲染节点.
CocoWidget每次添加子节点,是把另一个CocoWidget控件加入到孩子节点容器cocos2d::CCArray* m_children,并把子控件的渲染节点添加到自己的渲染节点下。
(2)渲染节点的纹理可以从精灵帧缓存(CCSpriteFrameCache::sharedSpriteFrameCache())或纹理缓存(CCTextureCache::sharedTextureCache())中加载.
参考:http://www.verydemo.com/demo_c441_i93779.html
本文内容:
1、cocostudio的控件
(1)CocoWidget控件基类
(2)CocoButton 按钮
(3)CocoTextButton 文本按钮
(4)CocoContainerWidget 控件管理容器
(5)CocoPanel 面板
(6)CocoScrollView 滚动列表
(7)CocoSlider 滑动条
2、BatchNodeManager 节点管理器
3、cocostudio的控件加入到场景
4、cocostudio ui编辑器的生成配置
5、控件事件回调
(1)CocoWidget控件基类
class CocoWidget : public cocos2d::CCObject{
public:
CocoWidget();
virtual ~CocoWidget();
virtual void releaseResoures();
static CocoWidget* create();
virtual bool init();
virtual void initNodes();
virtual bool addChild(CocoWidget* child);
virtual void addChildNode(CocoWidget* child);
virtual void addElementNode(UIElement* element);//添加到子控件
virtual void activeToUIInputManager();
virtual void cleanFromUIInputManager();
virtual void setWidgetZOrder(int z);
virtual int getWidgetZOrder();
virtual void reorderChild(CocoWidget* child);
virtual void setNeedCheckVisibleDepandParent(bool need);
virtual void setVisibleTouch(bool visible);
virtual void addUIElement(UIElement* element);
virtual bool removeChild(CocoWidget* child,bool cleanup);
virtual void removeChildMoveToTrash(CocoWidget* child);
virtual void removeChildReferenceOnly(CocoWidget* child);
virtual void removeFromParentAndCleanup(bool cleanup);
virtual void removeAllChildrenAndCleanUp(bool cleanup);
virtual void removeAllUIElementsAndCleanUp(bool cleanup);
int checkContainedChild(CocoWidget* child);
void setBeTouchAble(bool able);
bool getBeTouchAble();
void setUpdateEnable(bool able);
void setBeFocus(bool fucos);
void didNotSelectSelf();
//触摸事件回调(根据控件的按下状态显示不同的精灵)
virtual bool onTouchPressed(cocos2d::CCPoint &touchPoint);
virtual bool onTouchMoved(cocos2d::CCPoint &touchPoint);
virtual bool onTouchReleased(cocos2d::CCPoint &touchPoint);
virtual bool onTouchCanceled(cocos2d::CCPoint &touchPoint);
virtual bool onTouchLongClicked(cocos2d::CCPoint &touchPoint);
void setPressState(int state);
virtual void disable();
virtual void active();
virtual bool getActive();
//按下按钮,转换到状态的回调
virtual void onPressStateChangedToNormal();
virtual void onPressStateChangedToPressed();
virtual void onPressStateChangedToDisabled();
virtual cocos2d::CCRect getRect();//获取控件的大小
virtual cocos2d::CCRect getRelativeRect();
void getLocationInWindow();
virtual CRenderNode* getValidNode();
CRenderNode* getContainerNode();
virtual bool pointAtSelfBody(cocos2d::CCPoint &pt);
bool checkVisibleDependParent(cocos2d::CCPoint &pt);
bool checkBeVisibleInParent();
virtual void checkChildInfo(int handleState,CocoWidget* sender,cocos2d::CCPoint &touchPoint);
void setVisible(bool visible);
bool getVisible();
virtual float getRelativeLeftPos();
virtual float getRelativeBottomPos();
virtual float getRelativeRightPos();
virtual float getRelativeTopPos();
CocoWidget* getWidgetParent();
virtual bool getClipAble(){return false;};
virtual void update(float dt){};
CocoWidget* getChildByName(const char* name);//获取子控件
CocoWidget* getChildByTag(int tag);
//触发事件回调
void pushDownEvent();
void releaseUpEvent();
void cancelUpEvent();
void longClickEvent();
//添加事件回调
virtual void addPushDownEvent(cocos2d::CCObject* target,SEL_PushEvent selector);
virtual void addMoveEvent(cocos2d::CCObject* target,SEL_MoveEvent selector);
virtual void addReleaseEvent(cocos2d::CCObject* target,SEL_ReleaseEvent selector);
//cocos2d property
void setPosition(cocos2d::CCPoint pos);
cocos2d::CCPoint getPosition();
void setScale(float scale);
float getScale();
void setScaleX(float scaleX);
float getScaleX();
void setScaleY(float scaleY);
float getScaleY();
void setRotation(float rotation);
float getRotation();
virtual void setFlipX(bool flipX){this->m_pCContainerNode->setFlipX(flipX);};
virtual bool isFlipX(){return this->getValidNode()->isFlipX();};
virtual void setFlipY(bool flipY){this->m_pCContainerNode->setFlipY(flipY);};
virtual bool isFlipY(){return this->getValidNode()->isFlipY();};
virtual void setColor(int r,int g,int b){this->m_pCContainerNode->setColor(r, g, b);};
virtual cocos2d::ccColor3B getColor(){return this->getValidNode()->getColor();};
virtual void setOpacity(int opacity){this->m_pCContainerNode->setOpacity(opacity);};
virtual int getOpacity(){return this->getValidNode()->getOpacity();};
//widget prop 控件的属性
float getAbsoluteScaleX();
float getAbsoluteScaleY();
void updateChildrenScaleXDirty(bool dirty);
void updateChildrenScaleYDirty(bool dirty);
bool getAbsoluteVisible();
void updateChildrenVisibleDirty(bool dirty);
//cocos action
virtual void setActionManager(cocos2d::CCActionManager* actionManager);
/**
* Gets the CCActionManager object that is used by all actions.
* @see setActionManager(CCActionManager*)
* @return A CCActionManager object.
*/
virtual cocos2d::CCActionManager* getActionManager();
/**
* Executes an action, and returns the action that is executed.
*
* This node becomes the action's target. Refer to CCAction::getTarget()
* @warning Actions don't retain their target.
*
* @return An Action pointer
*/
cocos2d::CCAction* runAction(cocos2d::CCAction* action);
/**
* Stops and removes all actions from the running action list .
*/
void stopAllActions(void);
/**
* Stops and removes an action from the running action list.
*
* @param An action object to be removed.
*/
void stopAction(cocos2d::CCAction* action);
/**
* Removes an action from the running action list by its tag.
*
* @param A tag that indicates the action to be removed.
*/
void stopActionByTag(int tag);
/**
* Gets an action from the running action list by its tag.
*
* @see setTag(int), getTag().
*
* @return The action object with the given tag.
*/
cocos2d::CCAction* getActionByTag(int tag);
protected:
bool m_bEnabled;
bool m_bVisible;
bool m_bActived;
bool m_bFocus;
bool m_bBeTouchEnabled;
int m_nWidgetZOrder;
CocoWidget* m_pWidgetParent;
int m_nCurPressState;
int m_nPrevPressstate;
bool m_bUpdateAble;
CRenderNode* m_pCContainerNode;
float m_fContentSizeWidth;
float m_fContentSizeHeight;
cocos2d::CCPoint m_locationInWindow;
cocos2d::CCSize m_contentSize;
cocos2d::CCRect m_rect;
cocos2d::CCRect m_relativeRect;
cocos2d::CCArray* m_UIElements;
bool m_bNeedCheckVisibleDependParent;
bool m_bVisibleTouch;
CC_SYNTHESIZE_READONLY(cocos2d::CCArray*, m_children, Children);
CC_SYNTHESIZE_READONLY(cocos2d::CCPoint,m_touchStartPos,TouchStartPos)
CC_SYNTHESIZE_READONLY(cocos2d::CCPoint,m_touchEndPos,TouchEndPos)
CC_SYNTHESIZE(int, m_nWidgetTag, WidgetTag)
CC_SYNTHESIZE(std::string, m_strName, Name)
CC_SYNTHESIZE(bool,m_bUseMergedTexture,UseMergedTexture)
CC_SYNTHESIZE_READONLY(int, m_nWidgetType, WidgetType)
cocos2d::CCObject* m_pPushListener;
SEL_PushEvent m_pfnPushSelector;
cocos2d::CCObject* m_pMoveListener;
SEL_MoveEvent m_pfnMoveSelector;
cocos2d::CCObject* m_pReleaseListener;//释放的监听器
SEL_ReleaseEvent m_pfnReleaseSelector;
float m_fAbsoluteScaleX;
float m_fAbsoluteScaleY;
bool m_bAbsoluteVisible;
bool m_bScaleXDirty;
bool m_bScaleYDirty;
bool m_bVisibleDirty;
};
(2)CocoButton 按钮
class CocoButton : public CocoWidget
{
public:
CocoButton();
virtual ~CocoButton();
static CocoButton* create();
virtual bool init();
//设置按钮的精灵,从帧批量节点获取帧节点(或者帧缓存的帧精灵来初始化),更新节点
void setTextures(const char* normal,const char* selected,const char* disabled,bool useSpriteFrame = false);
void setTexturesScale9(const char* normal,const char* selected,const char* disabled,cocos2d::CCRect capInsets,bool useSpriteFrame = false);
void setNormalTexture(const char* normal,bool useSpriteFrame = false);
void setPressedTexture(const char* selected,bool useSpriteFrame = false);
void setDisabledTexture(const char* disabled,bool useSpriteFrame = false);
void setNormalTextureScale9(const char* normal,cocos2d::CCRect capInsets,bool useSpriteFrame = false);
void setPressedTextureScale9(const char* selected,cocos2d::CCRect capInsets,bool useSpriteFrame = false);
void setDisabledTextureScale9(const char* disabled,cocos2d::CCRect capInsets,bool useSpriteFrame = false);
virtual void onPressStateChangedToNormal();
virtual void onPressStateChangedToPressed();
virtual void onPressStateChangedToDisabled();
virtual CRenderNode* getValidNode();//获取按钮的当前状态下的按钮的渲染节点
void setScale9Enable(bool able);
void setScale9Size(float width,float height);
virtual void setColor(int r,int g,int b);//设置按钮的颜色
virtual void setOpacity(int opcity);
virtual void setFlipX(bool flipX);
virtual void setFlipY(bool flipY);
protected:
UIElement* m_pButtonNormal;//正常的按钮(UIElement cocoWeget的封装)
UIElement* m_pButtonClicked;//按下的按钮
UIElement* m_pButtonDisable;//失效的按钮
bool m_bScale9Enable;//设置9宫格按钮
};
(3)CocoTextButton 文本按钮
class CocoTextButton : public CocoButton
{
public:
CocoTextButton();
virtual ~CocoTextButton();
static CocoTextButton* create();
virtual bool init();
void setText(const char* text);
void setTextColor(int r,int g,int b);
void setFontSize(int size);
void setFontName(const char* fontName);
virtual void setFlipX(bool flipX);//x坐标按中心线反过来
virtual void setFlipY(bool flipY);
virtual void setColor(int r,int g,int b);
virtual void setOpacity(int opcity);//设置所有子节点的透明度
protected:
UIText * m_pTextLable;//文本标签
};
(4)CocoContainerWidget 控件管理容器
class CocoContainerWidget : public CocoWidget
{
public:
CocoContainerWidget();
virtual ~CocoContainerWidget();
static CocoContainerWidget* create();
virtual bool init();
virtual void initNodes();
virtual bool addChild(CocoWidget* child);
virtual void setClipAble(bool able);
virtual void setClipRect(cocos2d::CCRect rect);
virtual void updateWidth();
virtual void updateHeight();
virtual void setColorAndSize(int r,int g,int b,int o,float width,float height);
virtual void setSize(float width,float height);
virtual void setWidth(float width);
virtual float getWidth();
virtual void setHeight(float height);
virtual float getHeight();
virtual void setColor(int r,int g,int b);
virtual void setOpcity(int opcity);
virtual bool getClipAble();
virtual bool pointAtSelfBody(cocos2d::CCPoint &pt);
protected:
float m_fWidth;
float m_fHeight;
float m_bClipAble;
};
(5)CocoPanel 面板
class CocoPanel : public CocoContainerWidget
{
public:
CocoPanel();
virtual ~CocoPanel();
static CocoPanel* create();
virtual bool init();
void setBackGroundImage(const char* fileName,bool useSpriteFrame = false);
void setBackGroundImageScale9(const char* fileName,cocos2d::CCRect capInsets,bool useSpriteFrame = false);
virtual void setColorAndSize(int r,int g,int b,int o,float width,float height);
virtual void setSize(float width,float height);
void setBackGroundImageScale9Enable(bool able);
virtual void setColor(int r,int g,int b);
virtual void setOpacity(int opcity);
protected:
bool m_bBackGroundScale9Enable;
UIElement* m_pBackGroundImage;//背景控件(渲染节点)
};
(6)CocoScrollView 滚动列表
class CocoScrollView : public CocoPanel
{
public:
CocoScrollView();
virtual ~CocoScrollView();
static CocoScrollView* create();
virtual bool init();
virtual bool addChild(CocoWidget* widget);
virtual void removeChildMoveToTrash(CocoWidget* child);
virtual void removeChildReferenceOnly(CocoWidget* child);
virtual void removeAllChildrenAndCleanUp(bool cleanup);
void resortChildren();
void moveChildren(float offset);
void autoScrollChildren(float dt);
void startAutoScrollChildren(float v);
void stopAutoScrollChildren();
float getCurAutoScrollDistance(float time);
void setDirection(int direction);
bool scrollChildren(float touchOffset);
void scrollToBottom();
void scrollToTop();
void startRecordSlidAction();
void endRecordSlidAction();
void handlePressLogic(cocos2d::CCPoint &touchPoint);//处理按下时的逻辑
void handleMoveLogic(cocos2d::CCPoint &touchPoint);
void handleReleaseLogic(cocos2d::CCPoint &touchPoint);
virtual bool onTouchPressed(cocos2d::CCPoint &touchPoint);
virtual bool onTouchMoved(cocos2d::CCPoint &touchPoint);
virtual bool onTouchReleased(cocos2d::CCPoint &touchPoint);
virtual bool onTouchCanceled(cocos2d::CCPoint &touchPoint);
virtual bool onTouchLongClicked(cocos2d::CCPoint &touchPoint);
virtual void update(float dt);//(所有子节点)处理自动返回运动
void recordSlidTime(float dt);//滑动时间
virtual void checkChildInfo(int handleState,CocoWidget* sender,cocos2d::CCPoint &touchPoint);
virtual void setColorAndSize(int r,int g,int b,int o,float width,float height);
virtual void setSize(float width,float height);//设置限制大小,面板大小
protected:
int m_nDirection;
float m_fTouchStartLocation;
float m_fTouchEndLocation;
float m_fTouchMoveStartLocation;
float m_fTopBoundary;//test
float m_fBottomBoundary;//test
float m_fLeftBoundary;
float m_fRightBoundary;
CocoWidget* m_pTopChild;//记录上下左右控件(按添加时的位置来记录)
CocoWidget* m_pBottomChild;
CocoWidget* m_pLeftChild;
CocoWidget* m_pRightChild;
int m_nHandleState;//0 normal, 1 top boundary, 2 bottom boundary
int m_nMoveDirection;//0 pull down, 1 push up
bool m_bTopEnd;
bool m_bBottomEnd;
bool m_bAutoScroll;
float m_fAutoScrollOriginalSpeed;
float m_fAutoScrollAcceleration;
bool m_bBePressed;
float m_fSlidTime;
cocos2d::CCPoint moveChildPoint;
float m_fChildrenSizeHeight;
float m_fChildrenSizeWidth;
float m_fChildFocusCancelOffset;
};
(7)CocoSlider 滑动条
class CocoSlider : public CocoWidget
{
public:
CocoSlider();
virtual ~CocoSlider();
static CocoSlider* create();
virtual bool init();
void setBarTexture(const char* fileName,bool useSpriteFrame = false);
void setBarTextureScale9(const char* fileName,float x,float y,float width,float height,bool useSpriteFrame = false);
void setBarTextureScale9Enable(bool able);
void setSlidBallTextures(const char* normal,const char* pressed,const char* disabled,bool useSpriteFrame = false);
void setSlidBallNormalTexture(const char* normal,bool useSpriteFrame = false);
void setSlidBallPressedTexture(const char* pressed,bool useSpriteFrame = false);
void setSlidBallDisabledTexture(const char* disabled,bool useSpriteFrame = false);
void setBarLength(float length);
void setSlidBallPercent(int percent);
int getClickPercent(float location);
void checkSlidBoundary();
virtual bool onTouchPressed(cocos2d::CCPoint &touchPoint);//设置滚动球位置,滚动球的状态,触发百分比改变后的事件
virtual bool onTouchMoved(cocos2d::CCPoint &touchPoint);
virtual bool onTouchReleased(cocos2d::CCPoint &touchPoint);
virtual bool onTouchCanceled(cocos2d::CCPoint &touchPoint);
float getPercentWithBallPos(float px,float py);
virtual bool pointAtSelfBody(cocos2d::CCPoint &pt);
virtual CRenderNode* getValidNode();
virtual void addPercentChangedEvent(cocos2d::CCObject* target,SEL_PushEvent selector);
void percentChangedEvent();
int getPercent();
virtual void setColor(int r,int g,int b);
virtual void setOpacity(int opcity);
protected:
UIElement* m_pBarNode;
float m_fMinLength;
float m_fBarLength;
int m_nDirection;
int m_nBarPercent;
CocoButton* m_pSlidBall;
float m_fBarNodeScaleValue;
float m_fTouchMoveStartLocation;
bool m_bBarScale9Enable;
cocos2d::CCObject* m_pPercentListener;
SEL_PushEvent m_pfnPercentSelector;//百分比改变回调函数
};
2、BatchNodeManager 节点管理器
缓存管理当前层的所有CCNode 节点。
class BatchNodeManager {
public:
/*
* If you want to reset the AlphaTestValue, you can use this method.
* You should note this method will effect all CCNode used cocos2dx's Alpha Test Shader
*
* @param _value the value you want to set to Alpha Test,
*/
static void setBatchNodeAlphaTestValue(float _value);
public:
static BatchNodeManager *sharedBatchNodeManager();
//使用层来初始化节点管理器
/*
* Init members with a CCLayer
*/
virtual bool initWithLayer(CCLayer *_layer, std::string _layerName);
/*
* Add a BatchNode to current layer
*
* @param name The image name used by _batchNode, used for a key
* @param batchNode The BatchNode you want to added to current layer
* @param zOrder BatchNode's zorder, defualt is 0
*/
void addBatchNode(const std::string &name, BatchNode *batchNode, int zOrder = 0);
/*
* Get a BatchNode which used a image named _name from current layer.
* If do not exsit, create a new BatchNode named _name and add to current layer
*/
BatchNode *getBatchNode(const std::string &name);
/*
* Set the zorder of BatchNode named _name
*
* @param name BatchNode's name
* @param zOrder The zorder you want to set
*/
void setBatchNodeZOrder(const std::string &name, int zOrder);
//设置批节点混合函数
void setBatchNodeBlendFunc(const std::string &name, unsigned int src, unsigned int dst);
/*
* Remove all BatchNodes added to the layer named _layerName
* @param name The layer's name
*/
void removeBatchNodes(const std::string &layerName);
CCLayer *getCurrentLayer();
private:
/*
* When create a BatchNodeManager, it will set Alpha Test to 0.5
*/
BatchNodeManager();
~BatchNodeManager();
static BatchNodeManager *m_sBatchNodeManager;
//图片索引的批量帧节点
/*
* @key The image name the CCSpriteBatchNode use
* @value CCSpriteBatchNode*
*/
CCDictionary *m_pBatchNodeDic;
//按层名字索引的层的所有节点的字典
/*
* @key Layer's name
* @value BatchNode dictionary
*/
CCDictionary *m_pLayer2BatchNodeDic;
//当前层
CCLayer *m_pLayer; //! Current CCLayer
CCDictionary *m_pLayerMap; //! a map used to judge if a layer with a name is the same with the layer in the map named with the same name.
};
3、cocostudio的ui控件加入到场景
场景的层的初始化
bool HelloWorld::init()
{}
//COCOUISYSTEM这是一个宏,用来获取一个UISystem对象
//初始化当前场景对象、纹理缓存、输入管理器等
COCOUISYSTEM->init();
//重置当前场景的ui系统,重置所有控件,添加ui系统触摸层到当前的容器层,replaceUISceneWithFile 会调用resetSystem
COCOUISYSTEM->resetSystem(this)
//从配置文件加载ui界面控件
//其四个参数分别是UI目标,也就是添加UI的对象指针(这里是层),配置文件,读取方式(1为json文件,0为plist文件),最后一个是是否允许自适应
COCOUISYSTEM->replaceUISceneWithFile(this, "CocoGUISample.json", 1, false);//设置关闭按钮
//这几行是生成一个CocoButton,也就是CocoStudio自己的UI控件
//这里要说一下,CocoButton的控件几乎都是自己重写的,不继承于Cocos2d-x的控件,其触碰分派也是独立的
CocoGUI::CocoButton* closeButton = CocoGUI::CocoButton::create();closeButton->setBeTouchAble(true);
//设置按钮的释放事件回调
closeButton->addReleaseEvent((CCObject*)this, coco_releaseselector(HelloWorld::menuCloseCallback));
//把控件add到当前场景中
//这些空间都是重写的,而且不是继承于CCNode,所以不能直接用addChild来add,而是通过UISystem来add,并且通过UISystem来管理的,
//也就是说Remove也不是通过this.remove而是通过COCOUISYSTEM->getCurScene()->removeWidgetAndCleanUp
//获取scrollview控件
//在UI编辑器中只能编辑样子,不能添加事件,时间的添加只能在代码中添加,而获取对象则是添加的关键
//COCOUISYSTEM->getCurScene()->getRootWidget() 是当前场景的所有控件的根节点
//CocoStudio就是通过UISystem中的checkWidgetByName来获取对象的
//其参数分别为:当前场景的rootwidget和对象名称(UI编辑器中使用的)
//这样就可以对控件进行一系列修改,也包括最重要的添加事件了
CocoGUI::CocoScrollView* sc =
(CocoGUI::CocoScrollView*)(COCOUISYSTEM->checkWidgetByName(COCOUISYSTEM->getCurScene()->getRootWidget(), "scrollview"));
//添加到当前场景的更新控件列表
sc->setUpdateEnable(true);
//获取文本按钮
CocoGUI::CocoTextButton* bt =
(CocoGUI::CocoTextButton*)(COCOUISYSTEM->checkWidgetByName(COCOUISYSTEM->getCurScene()->getRootWidget(), "backtotopbutton"));
//注册文本按钮的释放事件
bt->addReleaseEvent(this, coco_releaseselector(HelloWorld::backToTop));//获取滑条控件
CocoGUI::CocoSlider* sld = (CocoGUI::CocoSlider*)(COCOUISYSTEM->checkWidgetByName(COCOUISYSTEM->getCurScene()->getRootWidget(), "slider"));
//注册滑条控件改变事件
sld->addPercentChangedEvent(this, coco_percentchangedselector(HelloWorld::sliderPercentChanged));
//获取普通按钮
CocoGUI::CocoButton* anib = (CocoGUI::CocoButton*)(COCOUISYSTEM->checkWidgetByName(COCOUISYSTEM->getCurScene()->getRootWidget(), "animationbutton"));
......
//添加以TEST_LAYER 命名的字典容器到批量节点管理器,用来管理BatchNode类(继承于CCSpriteBatchNode),也就是该层的批量节点对象
cs::BatchNodeManager::sharedBatchNodeManager()->initWithLayer(this, "TEST_LAYER");
.....
return true;}