void DisplayLinkDirector::mainLoop() { if (_purgeDirectorInNextLoop) { _purgeDirectorInNextLoop = false; purgeDirector(); } else if (! _invalid) { drawScene(); // release the objects //释放资源对象 PoolManager::getInstance()->getCurrentPool()->clear(); } }
void Director::drawScene() { // calculate "global" dt //计算全局帧间时间差 dt calculateDeltaTime(); // skip one flame when _deltaTime equal to zero. if(_deltaTime < FLT_EPSILON) { return; } if (_openGLView) { _openGLView->pollInputEvents(); } //tick before glClear: issue #533 if (! _paused) { _scheduler->update(_deltaTime); _eventDispatcher->dispatchEvent(_eventAfterUpdate); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* to avoid flickr, nextScene MUST be here: after tick and before draw. XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */ if (_nextScene) { setNextScene(); } kmGLPushMatrix(); // global identity matrix is needed... come on kazmath! kmMat4 identity; kmMat4Identity(&identity); // draw the scene //绘制场景 if (_runningScene) { _runningScene->visit(_renderer, identity, false); _eventDispatcher->dispatchEvent(_eventAfterVisit); } // draw the notifications node //处理通知节点 if (_notificationNode) { _notificationNode->visit(_renderer, identity, false); } if (_displayStats) { showStats(); } _renderer->render(); _eventDispatcher->dispatchEvent(_eventAfterDraw); kmGLPopMatrix(); _totalFrames++; // swap buffers //交换缓冲区 if (_openGLView) { _openGLView->swapBuffers(); } if (_displayStats) { calculateMPF(); } }
void Node::scheduleUpdateWithPriority(int priority) { _scheduler->scheduleUpdate(this, priority, !_running); } void Node::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay) { CCASSERT( selector, "Argument must be non-nil"); CCASSERT( interval >=0, "Argument must be positive"); _scheduler->schedule(selector, this, interval , repeat, delay, !_running); }
// main loop void Scheduler::update(float dt) { _updateHashLocked = true; //a.预处理 if (_timeScale != 1.0f) { dt *= _timeScale; } // // Selector callbacks // // Iterate over all the Updates' selectors //b.枚举所有的 update 定时器 tListEntry *entry, *tmp; // updates with priority < 0 //优先级小于 0 的定时器 DL_FOREACH_SAFE(_updatesNegList, entry, tmp) { if ((! entry->paused) && (! entry->markedForDeletion)) { entry->callback(dt); } } // updates with priority == 0 //优先级等于 0 的定时器 DL_FOREACH_SAFE(_updates0List, entry, tmp) { if ((! entry->paused) && (! entry->markedForDeletion)) { entry->callback(dt); } } // updates with priority > 0 //优先级大于 0 的定时器 DL_FOREACH_SAFE(_updatesPosList, entry, tmp) { if ((! entry->paused) && (! entry->markedForDeletion)) { entry->callback(dt); } } // Iterate over all the custom selectors //c.枚举所有的普通定时器 for (tHashTimerEntry *elt = _hashForTimers; elt != nullptr; ) { _currentTarget = elt; _currentTargetSalvaged = false; if (! _currentTarget->paused) { // The 'timers' array may change while inside this loop //枚举此节点中的所有定时器 //timers 数组可能在循环中改变,因此在此处需要小心处理 for (elt->timerIndex = 0; elt->timerIndex < elt->timers->num; ++(elt->timerIndex)) { elt->currentTimer = (Timer*)(elt->timers->arr[elt->timerIndex]); elt->currentTimerSalvaged = false; elt->currentTimer->update(dt); if (elt->currentTimerSalvaged) { // The currentTimer told the remove itself. To prevent the timer from // accidentally deallocating itself before finishing its step, we retained // it. Now that step is done, it's safe to release it. elt->currentTimer->release(); } elt->currentTimer = nullptr; } } // elt, at this moment, is still valid // so it is safe to ask this here (issue #490) elt = (tHashTimerEntry *)elt->hh.next; // only delete currentTarget if no actions were scheduled during the cycle (issue #481) if (_currentTargetSalvaged && _currentTarget->timers->num == 0) { removeHashElement(_currentTarget); } } // delete all updates that are marked for deletion // updates with priority < 0 //d.清理所有被标记了删除记号的 update 方法 //优先级小于 0 的定时器 DL_FOREACH_SAFE(_updatesNegList, entry, tmp) { if (entry->markedForDeletion) { this->removeUpdateFromHash(entry); } } // updates with priority == 0 //优先级等于 0 的定时器 DL_FOREACH_SAFE(_updates0List, entry, tmp) { if (entry->markedForDeletion) { this->removeUpdateFromHash(entry); } } // updates with priority > 0 //优先级大于 0 的定时器 DL_FOREACH_SAFE(_updatesPosList, entry, tmp) { if (entry->markedForDeletion) { this->removeUpdateFromHash(entry); } } _updateHashLocked = false; _currentTarget = nullptr; #if CC_ENABLE_SCRIPT_BINDING // // Script callbacks // // Iterate over all the script callbacks //e.处理脚本引擎相关的事件 if (!_scriptHandlerEntries.empty()) { for (auto i = _scriptHandlerEntries.size() - 1; i >= 0; i--) { SchedulerScriptHandlerEntry* eachEntry = _scriptHandlerEntries.at(i); if (eachEntry->isMarkedForDeletion()) { _scriptHandlerEntries.erase(i); } else if (!eachEntry->isPaused()) { eachEntry->getTimer()->update(dt); } } } #endif // // Functions allocated from another thread // // Testing size is faster than locking / unlocking. // And almost never there will be functions scheduled to be called. if( !_functionsToPerform.empty() ) { _performMutex.lock(); // fixed #4123: Save the callback functions, they must be invoked after '_performMutex.unlock()', otherwise if new functions are added in callback, it will cause thread deadlock. auto temp = _functionsToPerform; _functionsToPerform.clear(); _performMutex.unlock(); for( const auto &function : temp ) { function(); } } }
void Timer::update(float dt) { if (_elapsed == -1) { _elapsed = 0; _timesExecuted = 0; } else { if (_runForever && !_useDelay) {//standard timer usage _elapsed += dt; if (_elapsed >= _interval) { trigger(); _elapsed = 0; } } else {//advanced usage _elapsed += dt; if (_useDelay) { if( _elapsed >= _delay ) { trigger(); _elapsed = _elapsed - _delay; _timesExecuted += 1; _useDelay = false; } } else { if (_elapsed >= _interval) { trigger(); _elapsed = 0; _timesExecuted += 1; } } if (!_runForever && _timesExecuted > _repeat) { //unschedule timer cancel(); } } } }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。