【Cocos2d-x】源代码分析之 2d/ui/Widget
生活随笔
收集整理的這篇文章主要介紹了
【Cocos2d-x】源代码分析之 2d/ui/Widget
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
從今天開始 咱也模仿 紅孩兒這些大牛分析源代碼 ,因為水平有限 不正確之處歡迎狂噴。哈哈。
#ifndef __UIWIDGET_H__ #define __UIWIDGET_H__#include "ui/CCProtectedNode.h" #include "ui/UILayoutDefine.h" #include "ui/UILayoutParameter.h" #include "ui/GUIDefine.h"NS_CC_BEGINnamespace ui {typedef enum {BRIGHT_NONE = -1,BRIGHT_NORMAL,//正常BRIGHT_HIGHLIGHT//高亮 按鈕點擊之后 }BrightStyle;//明亮的風格typedef enum {WidgetTypeWidget, //control 基本 UIWidget 默認WidgetTypeContainer //container 容器 layout 實例化 }WidgetType;//ui 類型typedef enum {UI_TEX_TYPE_LOCAL = 0,//means local fileUI_TEX_TYPE_PLIST = 1// means sprite frame }TextureResType;//貼圖類型enum class TouchEventType {TOUCH_EVENT_BEGAN,//開始TOUCH_EVENT_MOVED,//移動TOUCH_EVENT_ENDED,//結束TOUCH_EVENT_CANCELED//取消 };//觸摸事件類型typedef enum {SIZE_ABSOLUTE,//絕對值SIZE_PERCENT//百分比值 }SizeType;//size值類型typedef enum {POSITION_ABSOLUTE,//絕對 真實位置POSITION_PERCENT//相對父節點位置百分比 }PositionType;//位置類型typedef enum {WIDGET_SIZE,//sizeWIDGET_POSITION//position}WidgetInfoType;//位置類型 //哦 這里說明一下 回調函數被我改動了下 主要是這樣改動之后能夠用到C++11的lambda表達式?//不必在使用的時候多聲明一個回調函數了 比較方便 希望引擎組能夠採用這樣的方式。 typedef std::function<void(Ref*,TouchEventType)> SEL_TouchEvent;//函數指針 指向 返回值 void 參數列表(Ref*,TouchEventType) 類型的函數 //typedef void (Ref::*SEL_TouchEvent)(Ref*,TouchEventType); //宏定義 給函數指針SEL_TouchEvent取別名為toucheventselector #define toucheventselector(_SELECTOR) (SEL_TouchEvent)(&_SELECTOR)class Widget : public ProtectedNode { public:Widget(void);virtual ~Widget();static Widget* create();/**設置 是否 觸摸&&可見 默認true*/virtual void setEnabled(bool enabled);bool isEnabled() const;/**設置是否明亮 默認true*/void setBright(bool bright);/**是否明亮*/bool isBright() const;/**能否夠觸摸(響應事件)默認true*/virtual void setTouchEnabled(bool enabled);/**設置明亮風格 正常 or 明亮 默認正常*/void setBrightStyle(BrightStyle style);/**能否夠觸摸*/bool isTouchEnabled() const;/**是否被選中 默認false*/bool isFocused() const;/**是否被選中 默認false*/void setFocused(bool fucosed);/**獲取此控件距離左節點的下邊界長度*/float getLeftInParent();/**獲取此控件距離父節點的下邊界長度*/float getBottomInParent();/**獲取此控件距離父節點的右邊界長度*/float getRightInParent();/**獲取此控件距離父節點的上邊界長度*/float getTopInParent();/**獲取一個孩子從容器依據它的名字*/virtual Widget* getChildByName(const char* name);/**渲染重載*/virtual void visit(cocos2d::Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;/**加入回調事件*/void addTouchEventListener(SEL_TouchEvent selector);/**打印屬性 debug*/virtual void logInfo(WidgetInfoType _type);//cocos2d 屬性/**基類有的函數為virtual 有的不是不帶virtual 的是全部子類都擁有這個函數的功能。帶virtual 的是擁有上述功能之外 重載父類的函數 想拓展功能用的。帶virtual 的函數能夠使用多態 即父類指針指向子類成員*//***更改在OpenGL坐標系中widget的位置(X,Y)*原來的點(0,0)是在屏幕的左下角。*@參數位置在OpenGL坐標widget的位置(X,Y)*/virtual void setPosition(const Point &pos) override;/**同上絕對位置變為百分比*/void setPositionPercent(const Point &percent);/**得到在OpenGL坐標系中widget的百分比位置(X,Y)*/const Point& getPositionPercent();/**設置位置類型*/void setPositionType(PositionType type);/**得到位置類型*/PositionType getPositionType() const;/**設置該widget是否水平翻轉*/virtual void setFlippedX(bool flippedX);/**該widget是否水平翻轉*/virtual bool isFlippedX(){return _flippedX;};/**該widget是否垂直翻轉*/virtual void setFlippedY(bool flippedY);/**該widget是否垂直翻轉*/virtual bool isFlippedY(){return _flippedY;};/**設置顏色*/virtual void setColor(const Color3B& color) override;/**設置透明度*/virtual void setOpacity(GLubyte opacity) override;/**得到顏色值*/const Color3B& getColor() const override {return _color;};/**得到透明度*/GLubyte getOpacity() const override {return _opacity;};/**棄用的屬性*//** @deprecated Use isFlippedX() instead */CC_DEPRECATED_ATTRIBUTE bool isFlipX() { return isFlippedX(); };/** @deprecated Use setFlippedX() instead */CC_DEPRECATED_ATTRIBUTE void setFlipX(bool flipX) { setFlippedX(flipX); };/** @deprecated Use isFlippedY() instead */CC_DEPRECATED_ATTRIBUTE bool isFlipY() { return isFlippedY(); };/** @deprecated Use setFlippedY() instead */CC_DEPRECATED_ATTRIBUTE void setFlipY(bool flipY) { setFlippedY(flipY); };/**當該widget失去焦點會調用*/void didNotSelectSelf();/**檢查一個點是否在父節點區域*/bool clippingParentAreaContainPoint(const Point &pt);/** 發送觸摸事件到widget的父節點*/virtual void checkChildInfo(int handleState,Widget* sender,const Point &touchPoint);/** Gets the touch began point of widget when widget is selected.*/const Point& getTouchStartPos();/** Gets the touch move point of widget when widget is selected*/const Point& getTouchMovePos();/** Gets the touch end point of widget when widget is selected.*/const Point& getTouchEndPos();/**設置name*/void setName(const char* name);/**得到name*/const char* getName() const;/**得到控件類型*/WidgetType getWidgetType() const;/**設置控件大小*/virtual void setSize(const Size &size);virtual void setSizeW(const int &sizeW);virtual void setSizeH(const int &sizeH);/**設置size百分比*/virtual void setSizePercent(const Point &percent);/**size類型*/void setSizeType(SizeType type);/**得到size類型*/SizeType getSizeType() const;/**得到size*/const Size& getSize() const;/**得到Customsize*/const Size& getCustomSize() const;/**得到layout size*/virtual const Size& getLayoutSize() {return _size;};//虛函數 供子類重寫?/**得到size百分比*/const Point& getSizePercent() const;/***/virtual bool hitTest(const Point &pt);/**觸摸事件*/virtual bool onTouchBegan(Touch *touch, Event *unusedEvent);virtual void onTouchMoved(Touch *touch, Event *unusedEvent);virtual void onTouchEnded(Touch *touch, Event *unusedEvent);virtual void onTouchCancelled(Touch *touch, Event *unusedEvent);/**設置布局參數*/void setLayoutParameter(LayoutParameter* parameter);/**得到布局參數*/LayoutParameter* getLayoutParameter(LayoutParameterType type);/**是否忽略size使用texture size 默認true*/virtual void ignoreContentAdaptWithSize(bool ignore);/**是否忽略size使用texture size*/bool isIgnoreContentAdaptWithSize() const;/**得到世界位置*/Point getWorldPosition();/**得到虛擬渲染器 比如 一個button的虛擬渲染器是他的 texture renderer 貼圖渲染器*/virtual Node* getVirtualRenderer();/**得到虛擬渲染器的size 默認是_contentSize 不同的子類有自己的重載*/virtual const Size& getVirtualRendererSize() const;/*** 得到改控件相應的"class name".*/virtual std::string getDescription() const override;/**克隆替身*/Widget* clone();virtual void onEnter() override;virtual void onExit() override;/**更新size和position*/void updateSizeAndPosition();void updateSizeAndPosition(const Size& parentSize);/*temp action*/void setActionTag(int tag);int getActionTag();CC_CONSTRUCTOR_ACCESS://initializes state of widget.virtual bool init() override;protected://call back function called when size changed.virtual void onSizeChanged();//initializes renderer of widget.virtual void initRenderer();//回復正常調用.virtual void onPressStateChangedToNormal();//選中會調用virtual void onPressStateChangedToPressed();//變暗會調用virtual void onPressStateChangedToDisabled();//不同的事件void pushDownEvent();void moveEvent();void releaseUpEvent();void cancelUpEvent();//空的虛函數為了多態virtual void updateTextureColor(){};virtual void updateTextureOpacity(){};virtual void updateTextureRGBA(){};virtual void updateFlippedX(){};virtual void updateFlippedY(){};void updateColorToRenderer(Node* renderer);void updateOpacityToRenderer(Node* renderer);void updateRGBAToRenderer(Node* renderer);void copyProperties(Widget* model);virtual Widget* createCloneInstance();virtual void copySpecialProperties(Widget* model);virtual void copyClonedWidgetChildren(Widget* model);Widget* getWidgetParent();void updateContentSizeWithTextureSize(const Size& size);/**多態 適用于全部的子類重載 實現自己的邏輯*/virtual void adaptRenderers(){}; protected:bool _enabled; ///< 是否可見&&可觸摸 最高屬性 bool _bright; ///< 是否光亮bool _touchEnabled; ///< 是否響應觸摸bool _touchPassedEnabled; ///< 觸摸時間是不是按下bool _focus; ///< 是不是焦點BrightStyle _brightStyle; ///< 明亮風格Point _touchStartPos; ///< touch began pointPoint _touchMovePos; ///< touch moved pointPoint _touchEndPos; ///< touch ended pointSEL_TouchEvent _touchEventSelector;///回調函數類型std::string _name;///類名WidgetType _widgetType;///控件類型int _actionTag;///運行動作的tagSize _size;///untransformed sizeSize _customSize;///自己定義sizebool _ignoreSize;///是否忽略自己定義的大小 而取資源原本的大小 untransformed img size 默認_size = _customSizebool _affectByClipping;SizeType _sizeType;///size 類型Point _sizePercent;///相對父節點size百分比PositionType _positionType;///位置類型Point _positionPercent;///相對父節點的位置百分比bool _reorderWidgetChildDirty;bool _hitted;EventListenerTouchOneByOne* _touchListener;///單點觸摸Color3B _color;///顏色值GLubyte _opacity;///透明度bool _flippedX;//是否鏡像X軸bool _flippedY;//是否鏡像Y軸Map<int, LayoutParameter*> _layoutParameterDictionary;//布局參數Map}; }NS_CC_END#endif /* defined(__Widget__) *//**************************************************************************** Copyright (c) 2013-2014 Chukong Technologies Inc.http://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/#include "ui/UIWidget.h" #include "ui/UILayout.h" #include "ui/UIHelper.h"NS_CC_BEGINnamespace ui {Widget::Widget(): _enabled(true), _bright(true), _touchEnabled(false), _touchPassedEnabled(false), _focus(false), _brightStyle(BRIGHT_NONE), _touchStartPos(Point::ZERO), _touchMovePos(Point::ZERO), _touchEndPos(Point::ZERO), _touchEventSelector(nullptr), _name("default"), _widgetType(WidgetTypeWidget), _actionTag(0), _size(Size::ZERO), _customSize(Size::ZERO), _ignoreSize(false), _affectByClipping(false), _sizeType(SIZE_ABSOLUTE), _sizePercent(Point::ZERO), _positionType(POSITION_ABSOLUTE), _positionPercent(Point::ZERO), _reorderWidgetChildDirty(true), _hitted(false), _touchListener(nullptr), _color(Color3B::WHITE), _opacity(255), _flippedX(false), _flippedY(false) {}Widget::~Widget() {_touchEventSelector = nullptr;setTouchEnabled(false); }Widget* Widget::create() {Widget* widget = new Widget();if (widget && widget->init()){widget->autorelease();return widget;}CC_SAFE_DELETE(widget);return nullptr; }bool Widget::init() {if (ProtectedNode::init()){initRenderer();//初始化渲染器 多態setBright(true);//設置明亮ignoreContentAdaptWithSize(true);//默認 內容不適應size大小setAnchorPoint(Point(0.5f, 0.5f));//默認 錨點在中心return true;}return false; }void Widget::onEnter() {updateSizeAndPosition();ProtectedNode::onEnter(); }void Widget::onExit() {unscheduleUpdate();ProtectedNode::onExit(); }void Widget::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) {if (_enabled){adaptRenderers();ProtectedNode::visit(renderer, parentTransform, parentTransformUpdated);} }Widget* Widget::getWidgetParent() {//得到父節點return dynamic_cast<Widget*>(getParent()); }void Widget::setEnabled(bool enabled) {_enabled = enabled;for (auto& child : _children){if (child){Widget* widgetChild = dynamic_cast<Widget*>(child);if (widgetChild){widgetChild->setEnabled(enabled);}}}for (auto& child : _protectedChildren){if (child){Widget* widgetChild = dynamic_cast<Widget*>(child);if (widgetChild){widgetChild->setEnabled(enabled);}}} }Widget* Widget::getChildByName(const char *name) {for (auto& child : _children){if (child){Widget* widgetChild = dynamic_cast<Widget*>(child);if (widgetChild){if (strcmp(widgetChild->getName(), name) == 0){return widgetChild;}}}}return nullptr; }void Widget::initRenderer() {//多態 不同的控件有自己的初始化渲染方式}void Widget::setSizeW(const int &sizeW) {_customSize.width = sizeW;if (_ignoreSize){_size = getVirtualRendererSize();}else{_size.width = sizeW;}if (_running){Widget* widgetParent = getWidgetParent();Size pSize;if (widgetParent){pSize = widgetParent->getSize();}else{pSize = _parent->getContentSize();}float spx = 0.0f;float spy = 0.0f;if (pSize.width > 0.0f){spx = _customSize.width / pSize.width;}if (pSize.height > 0.0f){spy = _customSize.height / pSize.height;}_sizePercent = Point(spx, spy);}onSizeChanged(); } void Widget::setSizeH(const int &sizeH) {_customSize.height = sizeH;if (_ignoreSize){_size = getVirtualRendererSize();}else{_size.height = sizeH;}if (_running){Widget* widgetParent = getWidgetParent();Size pSize;if (widgetParent){pSize = widgetParent->getSize();}else{pSize = _parent->getContentSize();}float spx = 0.0f;float spy = 0.0f;if (pSize.width > 0.0f){spx = _customSize.width / pSize.width;}if (pSize.height > 0.0f){spy = _customSize.height / pSize.height;}_sizePercent = Point(spx, spy);}onSizeChanged(); } void Widget::setSize(const Size &size) {_customSize = size;if (_ignoreSize){_size = getVirtualRendererSize();}else{_size = size;}if (_running){Widget* widgetParent = getWidgetParent();Size pSize;if (widgetParent){pSize = widgetParent->getSize();}else{pSize = _parent->getContentSize();}float spx = 0.0f;float spy = 0.0f;if (pSize.width > 0.0f){spx = _customSize.width / pSize.width;}if (pSize.height > 0.0f){spy = _customSize.height / pSize.height;}_sizePercent = Point(spx, spy);}onSizeChanged(); }void Widget::setSizePercent(const Point &percent) {_sizePercent = percent;Size cSize = _customSize;if (_running){Widget* widgetParent = getWidgetParent();if (widgetParent){cSize = Size(widgetParent->getSize().width * percent.x , widgetParent->getSize().height * percent.y);}else{cSize = Size(_parent->getContentSize().width * percent.x , _parent->getContentSize().height * percent.y);}}if (_ignoreSize){_size = getVirtualRendererSize();}else{_size = cSize;}_customSize = cSize;onSizeChanged(); }void Widget::updateSizeAndPosition() {Widget* widgetParent = getWidgetParent();Size pSize;if (widgetParent){//假設有父節點是控件基類widget 保存父節點的容器大小pSize = widgetParent->getLayoutSize();}else{//假設父節點不是控件基類widget 得到綁定貼圖大小pSize = _parent->getContentSize();}updateSizeAndPosition(pSize); }void Widget::updateSizeAndPosition(const cocos2d::Size &parentSize) {switch (_sizeType){case SIZE_ABSOLUTE://絕對大小 真實大小{if (_ignoreSize)//忽略設置的大小{_size = getVirtualRendererSize();//size取untransformed img size}else//不忽略自己定義大小{_size = _customSize;//size 取自己定義大小}float spx = 0.0f;float spy = 0.0f;if (parentSize.width > 0.0f){spx = _customSize.width / parentSize.width;}if (parentSize.height > 0.0f){spy = _customSize.height / parentSize.height;}_sizePercent = Point(spx, spy);//計算得到相對父節點的size百分比break;}case SIZE_PERCENT://百分比size{Size cSize = Size(parentSize.width * _sizePercent.x , parentSize.height * _sizePercent.y);//計算得到自己定義大小if (_ignoreSize)//忽略設置的大小{_size = getVirtualRendererSize();//size取untransformed img size}else//不忽略自己定義大小{_size = cSize;//size 取 計算得到自己定義大小}_customSize = cSize;//計算得到自己定義大小break;}default:break;}onSizeChanged();Point absPos = getPosition();switch (_positionType){case POSITION_ABSOLUTE://真實位置{if (parentSize.width <= 0.0f || parentSize.height <= 0.0f){//父節點size=0_positionPercent = Point::ZERO;//相對父節點的位置百分比為0}else{_positionPercent = Point(absPos.x / parentSize.width, absPos.y / parentSize.height);//相對父節點的位置百分比}break;}case POSITION_PERCENT://相對位置{absPos = Point(parentSize.width * _positionPercent.x, parentSize.height * _positionPercent.y);//得到真實位置break;}default:break;}setPosition(absPos);//更新真實位置 }void Widget::setSizeType(SizeType type) {_sizeType = type;//設置size類型 }SizeType Widget::getSizeType() const//返回值不可改 {return _sizeType;//得到size type 返回值不可改 }void Widget::ignoreContentAdaptWithSize(bool ignore) {if (_ignoreSize == ignore){return;//和當前值一樣 不是必需更新處理了 直接返回}_ignoreSize = ignore;if (_ignoreSize)//忽略自己定義size{Size s = getVirtualRendererSize();//取原本大小的size_size = s;}else//不忽略自己定義size{_size = _customSize;//取自己定義size}onSizeChanged();//更新size }bool Widget::isIgnoreContentAdaptWithSize() const {return _ignoreSize; }const Size& Widget::getSize() const {return _size; }const Size& Widget::getCustomSize() const {return _customSize; }const Point& Widget::getSizePercent() const {return _sizePercent; }Point Widget::getWorldPosition() {return convertToWorldSpace(Point(_anchorPoint.x * _contentSize.width, _anchorPoint.y * _contentSize.height));//得到世界坐標 }Node* Widget::getVirtualRenderer() {return this;//得到虛擬渲染器 默認是自己 不同的子類有自己的重載 }void Widget::onSizeChanged() {setContentSize(_size);//設置 untransformed sizefor (auto& child : getChildren()){Widget* widgetChild = dynamic_cast<Widget*>(child);if (widgetChild){widgetChild->updateSizeAndPosition();//遞歸更新全部子節點size position}} }const Size& Widget::getVirtualRendererSize() const {return _contentSize;//得到虛擬渲染器zise 默認是_contentSize 不同的子類有自己的重載 }void Widget::updateContentSizeWithTextureSize(const cocos2d::Size &size) {if (_ignoreSize){_size = size;}else{_size = _customSize;}onSizeChanged(); }void Widget::setTouchEnabled(bool enable) {if (enable == _touchEnabled){return;}_touchEnabled = enable;if (_touchEnabled)//假設開啟觸摸{_touchListener = EventListenerTouchOneByOne::create();CC_SAFE_RETAIN(_touchListener);//創建單點觸摸_touchListener->setSwallowTouches(true);//不向下觸摸,簡單點來說,比方有兩個sprite ,A 和B,A在上B在下(位置重疊),觸摸A的時候,B不會受到影響//綁定四個回調函數_touchListener->onTouchBegan = CC_CALLBACK_2(Widget::onTouchBegan, this);_touchListener->onTouchMoved = CC_CALLBACK_2(Widget::onTouchMoved, this);_touchListener->onTouchEnded = CC_CALLBACK_2(Widget::onTouchEnded, this);_touchListener->onTouchCancelled = CC_CALLBACK_2(Widget::onTouchCancelled, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(_touchListener, this);}else //假設不開啟觸摸{_eventDispatcher->removeEventListener(_touchListener);//移除CC_SAFE_RELEASE_NULL(_touchListener);//釋放} }bool Widget::isTouchEnabled() const {return _touchEnabled; }bool Widget::isFocused() const {return _focus; }void Widget::setFocused(bool fucos) {if (fucos == _focus){return;}_focus = fucos;if (_bright)//假設亮{if (_focus)//假設選中{setBrightStyle(BRIGHT_HIGHLIGHT);//高亮}else//假設沒有選中{setBrightStyle(BRIGHT_NORMAL);//正常}}else//假設不亮{onPressStateChangedToDisabled();//變暗} }void Widget::setBright(bool bright) {_bright = bright;if (_bright)//假設亮{_brightStyle = BRIGHT_NONE;setBrightStyle(BRIGHT_NORMAL);//正常亮}else//假設不亮{onPressStateChangedToDisabled();//變暗} }void Widget::setBrightStyle(BrightStyle style) {if (_brightStyle == style){return;}_brightStyle = style;switch (_brightStyle){case BRIGHT_NORMAL:onPressStateChangedToNormal();break;case BRIGHT_HIGHLIGHT:onPressStateChangedToPressed();break;default:break;} }void Widget::onPressStateChangedToNormal() {}void Widget::onPressStateChangedToPressed() {}void Widget::onPressStateChangedToDisabled() {}void Widget::didNotSelectSelf() {} void Widget::logInfo(WidgetInfoType _type) {log("widget anchor x = %f,y = %f",getAnchorPoint().x,getAnchorPoint().y);if (_type == WIDGET_SIZE) {log("widget size width = %f,height = %f",_size.width,_size.height);}if (_type == WIDGET_POSITION) {log("widget position x = %f,y = %f",getPositionX(),getPositionY());} } bool Widget::onTouchBegan(Touch *touch, Event *unusedEvent) {_hitted = false;//剛開始觸摸 沒有碰到if (isEnabled() && isTouchEnabled())//節點能夠使用 能夠點擊{_touchStartPos = touch->getLocation();//得到點擊位置//觸摸點在到圖像區域 而且 觸摸點在裁切區域if(hitTest(_touchStartPos) && clippingParentAreaContainPoint(_touchStartPos)){_hitted = true;//觸摸到了}}if (!_hitted)//沒有觸摸到{return false;//停止}setFocused(true);//得到焦點Widget* widgetParent = getWidgetParent();if (widgetParent)//有父節點{widgetParent->checkChildInfo(0,this,_touchStartPos);//檢查孩子屬性}pushDownEvent();//按下回調響應return !_touchPassedEnabled; }void Widget::onTouchMoved(Touch *touch, Event *unusedEvent) {_touchMovePos = touch->getLocation();setFocused(hitTest(_touchMovePos));Widget* widgetParent = getWidgetParent();if (widgetParent){widgetParent->checkChildInfo(1,this,_touchMovePos);}moveEvent(); }void Widget::onTouchEnded(Touch *touch, Event *unusedEvent) {_touchEndPos = touch->getLocation();bool focus = _focus;setFocused(false);Widget* widgetParent = getWidgetParent();if (widgetParent){widgetParent->checkChildInfo(2,this,_touchEndPos);}if (focus){releaseUpEvent();}else{cancelUpEvent();} }void Widget::onTouchCancelled(Touch *touch, Event *unusedEvent) {setFocused(false);cancelUpEvent(); }void Widget::pushDownEvent() {if ( _touchEventSelector){ // ( ->*_touchEventSelector)(this,TouchEventType::TOUCH_EVENT_BEGAN);//響應開始按下的回調_touchEventSelector(this,TouchEventType::TOUCH_EVENT_BEGAN);//響應開始按下的回調} }void Widget::moveEvent() {if ( _touchEventSelector){ // ( ->*_touchEventSelector)(this,TouchEventType::TOUCH_EVENT_MOVED);//響應移動的回調_touchEventSelector(this,TouchEventType::TOUCH_EVENT_MOVED);//響應移動的回調} }void Widget::releaseUpEvent() {if ( _touchEventSelector){ // ( ->*_touchEventSelector)(this,TouchEventType::TOUCH_EVENT_ENDED);//響應結束的回調_touchEventSelector(this,TouchEventType::TOUCH_EVENT_ENDED);//響應結束的回調} }void Widget::cancelUpEvent() {if ( _touchEventSelector){_touchEventSelector(this,TouchEventType::TOUCH_EVENT_CANCELED);//響應取消按下的回調 // ( ->*_touchEventSelector)(this,TouchEventType::TOUCH_EVENT_CANCELED);//響應取消按下的回調} } //共外部注冊回調 void Widget::addTouchEventListener( SEL_TouchEvent selector) {_touchEventSelector = selector; }bool Widget::hitTest(const Point &pt) {Point nsp = convertToNodeSpace(pt);//相對this的點Rect bb;bb.size = _contentSize;if (bb.containsPoint(nsp)){return true;//點在size內 hit ~!}return false; }bool Widget::clippingParentAreaContainPoint(const Point &pt) {_affectByClipping = false;Widget* parent = getWidgetParent();Widget* clippingParent = nullptr;while (parent)//有父節點{Layout* layoutParent = dynamic_cast<Layout*>(parent);if (layoutParent)//父節點是層容器{if (layoutParent->isClippingEnabled())//父節點是能夠裁切的{_affectByClipping = true;//受裁切的影響clippingParent = layoutParent;//取到已經裁切的父節點break;//跳出循環}}parent = parent->getWidgetParent();//向上遍歷父節點}if (!_affectByClipping)//沒有能夠裁切的層容器{return true;}if (clippingParent)//存在裁切的父節點{bool bRet = false;if (clippingParent->hitTest(pt))//點在裁切裁切范圍內{bRet = true;}if (bRet){return clippingParent->clippingParentAreaContainPoint(pt);//遞歸裁切父節點}return false;}return true; }void Widget::checkChildInfo(int handleState, Widget *sender, const Point &touchPoint) {Widget* widgetParent = getWidgetParent();if (widgetParent){widgetParent->checkChildInfo(handleState,sender,touchPoint);//遞歸檢查孩子的info} }void Widget::setPosition(const Point &pos) {if (_running)//若在執行狀態{Widget* widgetParent = getWidgetParent();if (widgetParent)//若有父節點{Size pSize = widgetParent->getSize();//父節點大小if (pSize.width <= 0.0f || pSize.height <= 0.0f){_positionPercent = Point::ZERO;//百分比為0}else{//計算相對父節點百分比_positionPercent = Point(pos.x / pSize.width, pos.y / pSize.height);}}}//由于widget對于position的表示除了 世界坐標之外 還新加了百分比坐標//所以須要額外處理計算百分比坐標ProtectedNode::setPosition(pos); }void Widget::setPositionPercent(const Point &percent) {_positionPercent = percent;if (_running){Widget* widgetParent = getWidgetParent();if (widgetParent){Size parentSize = widgetParent->getSize();Point absPos = Point(parentSize.width * _positionPercent.x, parentSize.height * _positionPercent.y);//絕對坐標setPosition(absPos);}} }const Point& Widget::getPositionPercent() {return _positionPercent; }void Widget::setPositionType(PositionType type) {_positionType = type; }PositionType Widget::getPositionType() const {return _positionType; }bool Widget::isBright() const {return _bright; }bool Widget::isEnabled() const {return _enabled; }float Widget::getLeftInParent() {return getPosition().x - getAnchorPoint().x * _size.width;; } //得到距離父節點底部的距離 float Widget::getBottomInParent() {return getPosition().y - getAnchorPoint().y * _size.height;; }float Widget::getRightInParent() {return getLeftInParent() + _size.width; }float Widget::getTopInParent() {return getBottomInParent() + _size.height; }const Point& Widget::getTouchStartPos() {return _touchStartPos; }const Point& Widget::getTouchMovePos() {return _touchMovePos; }const Point& Widget::getTouchEndPos() {return _touchEndPos; }void Widget::setName(const char* name) {_name = name; }const char* Widget::getName() const {return _name.c_str(); }WidgetType Widget::getWidgetType() const {return _widgetType; } //設置布局參數 void Widget::setLayoutParameter(LayoutParameter *parameter) {if (!parameter){return;}_layoutParameterDictionary.insert(parameter->getLayoutType(), parameter); } //得到全部布局參數 LayoutParameter* Widget::getLayoutParameter(LayoutParameterType type) {return dynamic_cast<LayoutParameter*>(_layoutParameterDictionary.at(type)); }std::string Widget::getDescription() const {return "Widget"; } //克隆 Widget* Widget::clone() {Widget* clonedWidget = createCloneInstance();clonedWidget->copyProperties(this);//拷貝基礎屬性clonedWidget->copyClonedWidgetChildren(this);//拷貝全部孩子return clonedWidget; }Widget* Widget::createCloneInstance() {return Widget::create(); }void Widget::copyClonedWidgetChildren(Widget* model) {//引用類型auto&auto& modelChildren = model->getChildren();for (auto& subWidget : modelChildren){Widget* child = dynamic_cast<Widget*>(subWidget);if (child){addChild(child->clone());}} }void Widget::copySpecialProperties(Widget* model) {} //拷貝屬性 void Widget::copyProperties(Widget *widget) {setEnabled(widget->isEnabled());setVisible(widget->isVisible());setBright(widget->isBright());setTouchEnabled(widget->isTouchEnabled());_touchPassedEnabled = false;setLocalZOrder(widget->getLocalZOrder());setTag(widget->getTag());setName(widget->getName());setActionTag(widget->getActionTag());_ignoreSize = widget->_ignoreSize;_size = widget->_size;_customSize = widget->_customSize;copySpecialProperties(widget);_sizeType = widget->getSizeType();_sizePercent = widget->_sizePercent;_positionType = widget->_positionType;_positionPercent = widget->_positionPercent;setPosition(widget->getPosition());setAnchorPoint(widget->getAnchorPoint());setScaleX(widget->getScaleX());setScaleY(widget->getScaleY());setRotation(widget->getRotation());setRotationSkewX(widget->getRotationSkewX());setRotationSkewY(widget->getRotationSkewY());setFlippedX(widget->isFlippedX());setFlippedY(widget->isFlippedY());setColor(widget->getColor());setOpacity(widget->getOpacity());//遍歷布局參數 容器 拷貝Map<int, LayoutParameter*>& layoutParameterDic = widget->_layoutParameterDictionary;for (auto iter = layoutParameterDic.begin(); iter != layoutParameterDic.end(); ++iter){setLayoutParameter(iter->second->clone());}onSizeChanged(); }void Widget::setColor(const Color3B& color) {_color = color;updateTextureColor(); }void Widget::setOpacity(GLubyte opacity) {_opacity = opacity;updateTextureOpacity(); }void Widget::setFlippedX(bool flippedX) {_flippedX = flippedX;updateFlippedX(); }void Widget::setFlippedY(bool flippedY) {_flippedY = flippedY;updateFlippedY(); }void Widget::updateColorToRenderer(Node* renderer) {renderer->setColor(_color); }void Widget::updateOpacityToRenderer(Node* renderer) {renderer->setOpacity(_opacity); }void Widget::updateRGBAToRenderer(Node* renderer) {renderer->setColor(_color);renderer->setOpacity(_opacity); }/*temp action*/ void Widget::setActionTag(int tag) {_actionTag = tag; }int Widget::getActionTag() {return _actionTag; }}NS_CC_END
總結
以上是生活随笔為你收集整理的【Cocos2d-x】源代码分析之 2d/ui/Widget的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iptables如何添加容许某个端口的访
- 下一篇: CSS 实现加载动画之四-圆点旋转