第一次看CCControl
Control中有九种可能的事件,定义在.h文件中,另外还定义四种状态,用来表示控件高亮等。
在初始化控件的时候:
bool Control::init()
{
if (Layer::init())
{
// Initialise instance variables
//初始化控件的状态
_state=Control::State::NORMAL;
//开启控件
setEnabled(true);
//不选中
setSelected(false);
//不高亮
setHighlighted(false);
//获取分发器
auto dispatcher = Director::getInstance()->getEventDispatcher();
//创建单点触摸监听器
auto touchListener = EventListenerTouchOneByOne::create();
//设置触摸吞没,触摸控件时,控件下的其它东西不会接触到触摸事件
touchListener->setSwallowTouches(true);
//创建触摸不同阶段的回调函数
touchListener->onTouchBegan = CC_CALLBACK_2(Control::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(Control::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(Control::onTouchEnded, this);
touchListener->onTouchCancelled = CC_CALLBACK_2(Control::onTouchCancelled, this);
//添加场景图优先级的触摸监听器,也就是说优先级为0
dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
return true;
}
else
{
return false;
}
}
添加场景图优先级的触摸监听器
void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
{
CCASSERT(listener && node, "Invalid parameters.");
CCASSERT(!listener->isRegistered(), "The listener has been registered.");
if (!listener->checkAvailable())
return;
//设置监听器的节点参数
listener->setAssociatedNode(node);
//设置优先级
listener->setFixedPriority(0);
//设置为注册
listener->setRegistered(true);
//添加给存储监听器的全局数组添加元素
addEventListener(listener);
}
添加事件监听器到全局数组中
void EventDispatcher::addEventListener(EventListener* listener)
{
if (_inDispatch == 0)
{
//直接添加
forceAddEventListener(listener);
}
else
{
//正在使用,延时添加
_toAddedListeners.push_back(listener);
}
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (sEngine)
{
sEngine->retainScriptObject(this, listener);
}
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
listener->retain();
}
直接添加
void EventDispatcher::forceAddEventListener(EventListener* listener)
{
EventListenerVector* listeners = nullptr;
//通过listener获取ID
EventListener::ListenerID listenerID = listener->getListenerID();
//通过ID查找是否在存储所有listener的map中,这个map是用来存储监听器ID和监听器数组的
auto itr = _listenerMap.find(listenerID);
//如果没找到
if (itr == _listenerMap.end())
{
//新建一个监听器数组类型
listeners = new (std::nothrow) EventListenerVector();
//和对应的ID一起加入map中
_listenerMap.emplace(listenerID, listeners);
}
else
{
//如果找到了就获取它的second,即存储listener的数组
listeners = itr->second;
}
//添加到对应ID的listeners中
listeners->push_back(listener);
//如果优先级是0
if (listener->getFixedPriority() == 0)
{
//设置场景图的优先级
setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);
//获取关联节点
auto node = listener->getAssociatedNode();
CCASSERT(node != nullptr, "Invalid scene graph priority!");
//将节点和监听器放入_nodeListenersMap中
associateNodeAndEventListener(node, listener);
if (!node->isRunning())
{
listener->setPaused(true);
}
}
else
{
setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
}
}
要注意的地方是,fixedPriority事件是不绑定节点的。
setDirty看的还不是很明白,后补。