【纹理】
TextureCache::addImage
texture = new (std::nothrow) Texture2D(); // ref = 1, 没有autorelease
TextureCache::removeUnusedTextures
把引用计数是1的纹理释放掉
TextureCache::removeAllTextures
释放所有缓存的纹理
【事件】
分发顺序:优先级<0,场景图顺序(从前往后)(优先级=0),优先级>0
注册订阅者:
用场景图优先级方式添加,要绑定node,默认优先级为0
void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
按固定优先级方式添加,不能设置优先级为0(因为0在上面用,有特殊意义)
void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
添加的时候是放到一个map去:
std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
暂停、恢复与节点相关的侦听
void resumeEventListenersForTarget(Node* target, bool recursive = false);
void pauseEventListenersForTarget(Node* target, bool recursive = false);
开关订阅者
inline void setEnabled(bool enabled)
inline bool isEnabled()
设置优先级
void setPriority(EventListener* listener, int fixedPriority);
分发事件:
void dispatchEvent(Event* event);
void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);
TextureCache::addImage
texture = new (std::nothrow) Texture2D(); // ref = 1, 没有autorelease
TextureCache::removeUnusedTextures
把引用计数是1的纹理释放掉
TextureCache::removeAllTextures
释放所有缓存的纹理
【事件】
分发顺序:优先级<0,场景图顺序(从前往后)(优先级=0),优先级>0
注册订阅者:
用场景图优先级方式添加,要绑定node,默认优先级为0
void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
按固定优先级方式添加,不能设置优先级为0(因为0在上面用,有特殊意义)
void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
添加的时候是放到一个map去:
std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
而侦听id根据不同的事件类型获取的,每种事件对应一个字符串,而用户自定义事件则是事件的名字:
static EventListener::ListenerID __getListenerID(Event* event)
{
EventListener::ListenerID ret;
switch (event->getType())
{
case Event::Type::ACCELERATION:
ret = EventListenerAcceleration::LISTENER_ID;
break;
case Event::Type::CUSTOM:
{
auto customEvent = static_cast<EventCustom*>(event);
ret = customEvent->getEventName();
}
break;
case Event::Type::KEYBOARD:
ret = EventListenerKeyboard::LISTENER_ID;
break;
case Event::Type::MOUSE:
ret = EventListenerMouse::LISTENER_ID;
break;
case Event::Type::FOCUS:
ret = EventListenerFocus::LISTENER_ID;
break;
case Event::Type::TOUCH:
// Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
// return UNKNOWN instead.
CCASSERT(false, "Don't call this method if the event is for touch.");
break;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
case Event::Type::GAME_CONTROLLER:
ret = EventListenerController::LISTENER_ID;
break;
#endif
default:
CCASSERT(false, "Invalid type!");
break;
}
return ret;
}
暂停、恢复与节点相关的侦听
void resumeEventListenersForTarget(Node* target, bool recursive = false);
void pauseEventListenersForTarget(Node* target, bool recursive = false);
开关订阅者
inline void setEnabled(bool enabled)
inline bool isEnabled()
设置优先级
void setPriority(EventListener* listener, int fixedPriority);
分发事件:
void dispatchEvent(Event* event);
void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);
void EventDispatcher::dispatchEvent(Event* event)
{
if (!_isEnabled)
return;
updateDirtyFlagForSceneGraph();
DispatchGuard guard(_inDispatch);
if (event->getType() == Event::Type::TOUCH)
{
dispatchTouchEvent(static_cast<EventTouch*>(event));
return;
}
auto listenerID = __getListenerID(event);
sortEventListeners(listenerID);
auto iter = _listenerMap.find(listenerID);
if (iter != _listenerMap.end())
{
auto listeners = iter->second;
auto onEvent = [&event](EventListener* listener) -> bool{
event->setCurrentTarget(listener->getAssociatedNode());
listener->_onEvent(event);
return event->isStopped();
};
dispatchEventToListeners(listeners, onEvent);
}
updateListeners(event);
}
分发的过程:先对标记为dirty的侦听者进行排序,然后根据事件的侦听id找到对应的侦听者集合,然后遍历处理。而处理的结果event->isStopped会影响该事件是否继续传递给其他侦听者。
void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
{
bool shouldStopPropagation = false;
auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
ssize_t i = 0;
// priority < 0
if (fixedPriorityListeners)
{
CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
if (!fixedPriorityListeners->empty())
{
for (; i < listeners->getGt0Index(); ++i)
{
auto l = fixedPriorityListeners->at(i);
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
{
shouldStopPropagation = true;
break;
}
}
}
}
if (sceneGraphPriorityListeners)
{
if (!shouldStopPropagation)
{
// priority == 0, scene graph priority
for (auto& l : *sceneGraphPriorityListeners)
{
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
{
shouldStopPropagation = true;
break;
}
}
}
}
if (fixedPriorityListeners)
{
if (!shouldStopPropagation)
{
// priority > 0
ssize_t size = fixedPriorityListeners->size();
for (; i < size; ++i)
{
auto l = fixedPriorityListeners->at(i);
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
{
shouldStopPropagation = true;
break;
}
}
}
}
}