// Draw the Scene
void Director::drawScene()
{
//获取上一帧到此帧的间隔时间
// calculate "global" dt
calculateDeltaTime();
if (_openGLView)
{
//处理用户交互事件
_openGLView->pollEvents();
}
//tick before glClear: issue #533
if (! _paused)
{
//处理延迟回调事件
_scheduler->update(_deltaTime);
_eventDispatcher->dispatchEvent(_eventAfterUpdate);
}
//绘制UI
_renderer->clear();
/* to avoid flickr, nextScene MUST be here: after tick and before draw.
* FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9
*/
if (_nextScene)
{
setNextScene();
}
pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
if (_runningScene)
{
#if CC_USE_PHYSICS
auto physicsWorld = _runningScene->getPhysicsWorld();
if (physicsWorld && physicsWorld->isAutoStep())
{
physicsWorld->update(_deltaTime, false);
}
#endif
//clear draw stats
_renderer->clearDrawStats();
//render the scene
_runningScene->render(_renderer);
_eventDispatcher->dispatchEvent(_eventAfterVisit);
}
// draw the notifications node
if (_notificationNode)
{
_notificationNode->visit(_renderer, Mat4::IDENTITY, 0);
}
if (_displayStats)
{
showStats();
}
updateFrameRate();
_renderer->render();
//处理在绘制后发生的用户输入事件
_eventDispatcher->dispatchEvent(_eventAfterDraw);
popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_totalFrames++;
// swap buffers
if (_openGLView)
{
_openGLView->swapBuffers();
}
if (_displayStats)
{
calculateMPF();
}
}
1. 全局范围内Scheduler只有一个 是处于Director下的成员对象
2. Scheduler的update是通过Director::drawScene(dt) 调用 处于UI线程 所以在UI类内调用 无需考虑线程安全问题
3. 调用Scheduler::update()之前 首先处理的是GLFW的PullEvents() 所以所有交互类事件都会在此之前被相应
/*! @brief Processes all pending events.
* 处理所有待处理的事件
* This function processes only those events that have already been received
* and then returns immediately. Processing events will cause the window and
* input callbacks associated with those events to be called.
这个方法只会处理那些已经被接收的事件,并且会立即返回。
处理事件会调用交互事件的回调
*
* This function is not required for joystick input to work.
这个事件并不需要遥感才能工作(?)
*
* @par New in GLFW 3
* This function is no longer called by @ref glfwSwapBuffers. You need to call
* it or @ref glfwWaitEvents yourself.
在GLFW 3中 这个方法不再被glfwSwapBuffers调用
你需要自行调用这个方法
*
* @remarks On some platforms, a window move, resize or menu operation will
* cause event processing to block. This is due to how event processing is
* designed on those platforms. You can use the
* [window refresh callback](@ref GLFWwindowrefreshfun) to redraw the contents
* of your window when necessary during the operation.
在一些特定的平台下,窗口移动/变更大小/菜单栏操作将有可能阻塞事件处理。
这取决于这些平台如何处理他们内部的事件。
当你的窗口正在执行以上操作的时候,你可以使用GLFWwindowrefreshfun这个方法来渲染一些必要
的UI
*
* @note This function may only be called from the main thread.
这个方法应该在主线程内被调用
*
* @note This function may not be called from a callback.
这个方法最好不要在回调内被调用
*
* @note On some platforms, certain callbacks may be called outside of a call
* to one of the event processing functions.
* 在某些平台,某些回调可能会不会再这个方法内被调用(这个有点看不懂)
* @sa glfwWaitEvents
* 详细查询glfwWaitEvents
* @ingroup window
*/
GLFWAPI void glfwPollEvents(void);
4. 调用Scheduler::update()之后 才会开始渲染Scene 所以所有交互事件及Scheduler事件会在绘图之前被响应.
上一帧的帧内到本帧的帧前收到了点击事件 都应该在绘制UI之前被处理,如果拖到下一帧处理的话 会有延迟感