CCGLView.cpp:
部分代码注释如下,由于作者是在windows下阅读的代码,因此这里的CCGLView的路径为【 cocos2d\cocos\platform\desktop\CCGLView.cpp 】:
static
void
onGLFWError(
int
errorID,
const
char
* errorDesc)
_view->onGLFWError(errorID, errorDesc);
static
void
onGLFWMouseCallBack(GLFWwindow* window,
int
button,
int
action,
int
modify)
_view->onGLFWMouseCallBack(window, button, action, modify);
static
void
onGLFWMouseMoveCallBack(GLFWwindow* window,
double
x,
double
y)
_view->onGLFWMouseMoveCallBack(window, x, y);
static
void
onGLFWMouseScrollCallback(GLFWwindow* window,
double
x,
double
y)
_view->onGLFWMouseScrollCallback(window, x, y);
static
void
onGLFWKeyCallback(GLFWwindow* window,
int
key,
int
scancode,
int
action,
int
mods)
_view->onGLFWKeyCallback(window, key, scancode, action, mods);
static
void
onGLFWCharCallback(GLFWwindow* window, unsigned
int
character)
_view->onGLFWCharCallback(window, character);
static
void
onGLFWWindowPosCallback(GLFWwindow* windows,
int
x,
int
y)
_view->onGLFWWindowPosCallback(windows, x, y);
static
void
onGLFWframebuffersize(GLFWwindow* window,
int
w,
int
h)
_view->onGLFWframebuffersize(window, w, h);
static
void
onGLFWWindowSizeFunCallback(GLFWwindow *window,
int
width,
int
height)
_view->onGLFWWindowSizeFunCallback(window, width, height);
static
void
setGLView(GLView* view)
GLView* GLFWEventHandler::_view = nullptr;
EventKeyboard::KeyCode keyCode;
static
std::unordered_map<
int
, EventKeyboard::KeyCode> g_keyCodeMap;
static
keyCodeItem g_keyCodeStructArray[] = {
{ GLFW_KEY_UNKNOWN , EventKeyboard::KeyCode::KEY_NONE },
{ GLFW_KEY_SPACE , EventKeyboard::KeyCode::KEY_SPACE },
{ GLFW_KEY_MENU , EventKeyboard::KeyCode::KEY_MENU },
{ GLFW_KEY_LAST , EventKeyboard::KeyCode::KEY_NONE }
, _isInRetinaMonitor(
false
)
, _isRetinaEnabled(
false
)
for
(auto& item : g_keyCodeStructArray)
g_keyCodeMap[item.glfwKeyCode] = item.keyCode;
GLFWEventHandler::setGLView(
this
);
glfwSetErrorCallback(GLFWEventHandler::onGLFWError);
CCLOGINFO(
"deallocing GLView: %p"
,
this
);
GLFWEventHandler::setGLView(nullptr);
GLView* GLView::create(
const
std::string& viewName)
if
(ret && ret->initWithRect(viewName, Rect(0, 0, 960, 640), 1)) {
GLView* GLView::createWithRect(
const
std::string& viewName, Rect rect,
float
frameZoomFactor)
if
(ret && ret->initWithRect(viewName, rect, frameZoomFactor)) {
GLView* GLView::createWithFullScreen(
const
std::string& viewName)
if
(ret && ret->initWithFullScreen(viewName)) {
GLView* GLView::createWithFullScreen(
const
std::string& viewName,
const
GLFWvidmode &videoMode, GLFWmonitor *monitor)
if
(ret && ret->initWithFullscreen(viewName, videoMode, monitor)) {
bool
GLView::initWithRect(
const
std::string& viewName, Rect rect,
float
frameZoomFactor)
_frameZoomFactor = frameZoomFactor;
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
_mainWindow = glfwCreateWindow(rect.size.width * _frameZoomFactor,
rect.size.height * _frameZoomFactor,
glfwMakeContextCurrent(_mainWindow);
glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);
glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);
glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);
glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);
glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);
glfwSetWindowPosCallback(_mainWindow, GLFWEventHandler::onGLFWWindowPosCallback);
glfwSetFramebufferSizeCallback(_mainWindow, GLFWEventHandler::onGLFWframebuffersize);
glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);
setFrameSize(rect.size.width, rect.size.height);
const
GLubyte* glVersion = glGetString(GL_VERSION);
if
(
atof
((
const
char
*)glVersion) < 1.5 )
char
strComplain[256] = {0};
"OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card."
,
MessageBox(strComplain,
"OpenGL version too old"
);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
bool
GLView::initWithFullScreen(
const
std::string& viewName)
_monitor = glfwGetPrimaryMonitor();
const
GLFWvidmode* videoMode = glfwGetVideoMode(_monitor);
return
initWithRect(viewName, Rect(0, 0, videoMode->width, videoMode->height), 1.0f);
bool
GLView::initWithFullscreen(
const
std::string &viewname,
const
GLFWvidmode &videoMode, GLFWmonitor *monitor)
glfwWindowHint(GLFW_REFRESH_RATE, videoMode.refreshRate);
glfwWindowHint(GLFW_RED_BITS, videoMode.redBits);
glfwWindowHint(GLFW_BLUE_BITS, videoMode.blueBits);
glfwWindowHint(GLFW_GREEN_BITS, videoMode.greenBits);
return
initWithRect(viewname, Rect(0, 0, videoMode.width, videoMode.height), 1.0f);
bool
GLView::isOpenGLReady()
return
nullptr != _mainWindow;
glfwSetWindowShouldClose(_mainWindow,1);
void
GLView::swapBuffers()
glfwSwapBuffers(_mainWindow);
bool
GLView::windowShouldClose()
return
glfwWindowShouldClose(_mainWindow) ?
true
:
false
;
void
GLView::pollEvents()
void
GLView::enableRetina(
bool
enabled)
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
_isRetinaEnabled = enabled;
void
GLView::setIMEKeyboardState(
bool
)
void
GLView::setFrameZoomFactor(
float
zoomFactor)
CCASSERT(zoomFactor > 0.0f,
"zoomFactor must be larger than 0"
);
if
(
fabs
(_frameZoomFactor - zoomFactor) < FLT_EPSILON)
_frameZoomFactor = zoomFactor;
float
GLView::getFrameZoomFactor()
void
GLView::updateFrameSize()
if
(_screenSize.width > 0 && _screenSize.height > 0)
glfwGetWindowSize(_mainWindow, &w, &h);
int
frameBufferW = 0, frameBufferH = 0;
glfwGetFramebufferSize(_mainWindow, &frameBufferW, &frameBufferH);
if
(frameBufferW == 2 * w && frameBufferH == 2 * h)
glfwSetWindowSize(_mainWindow, _screenSize.width/2 * _retinaFactor * _frameZoomFactor, _screenSize.height/2 * _retinaFactor * _frameZoomFactor);
_isInRetinaMonitor =
true
;
glfwSetWindowSize(_mainWindow, _screenSize.width * _retinaFactor * _frameZoomFactor, _screenSize.height *_retinaFactor * _frameZoomFactor);
_isInRetinaMonitor =
false
;
void
GLView::setFrameSize(
float
width,
float
height)
GLViewProtocol::setFrameSize(width, height);
void
GLView::setViewPortInPoints(
float
x ,
float
y ,
float
w ,
float
h)
glViewport((GLint)(x * _scaleX * _retinaFactor * _frameZoomFactor + _viewPortRect.origin.x * _retinaFactor * _frameZoomFactor),
(GLint)(y * _scaleY * _retinaFactor * _frameZoomFactor + _viewPortRect.origin.y * _retinaFactor * _frameZoomFactor),
(GLsizei)(w * _scaleX * _retinaFactor * _frameZoomFactor),
(GLsizei)(h * _scaleY * _retinaFactor * _frameZoomFactor));
void
GLView::setScissorInPoints(
float
x ,
float
y ,
float
w ,
float
h)
glScissor((GLint)(x * _scaleX * _retinaFactor * _frameZoomFactor + _viewPortRect.origin.x * _retinaFactor * _frameZoomFactor),
(GLint)(y * _scaleY * _retinaFactor * _frameZoomFactor + _viewPortRect.origin.y * _retinaFactor * _frameZoomFactor),
(GLsizei)(w * _scaleX * _retinaFactor * _frameZoomFactor),
(GLsizei)(h * _scaleY * _retinaFactor * _frameZoomFactor));
void
GLView::onGLFWError(
int
errorID,
const
char
* errorDesc)
CCLOGERROR(
"GLFWError #%d Happen, %s\n"
, errorID, errorDesc);
void
GLView::onGLFWMouseCallBack(GLFWwindow* window,
int
button,
int
action,
int
modify)
if
(GLFW_MOUSE_BUTTON_LEFT == button)
if
(
this
->getViewPortRect().equals(Rect::ZERO) ||
this
->getViewPortRect().containsPoint(Vec2(_mouseX,_mouseY)))
this
->handleTouchesBegin(1, &id, &_mouseX, &_mouseY);
else
if
(GLFW_RELEASE == action)
this
->handleTouchesEnd(1, &id, &_mouseX, &_mouseY);
EventMouse event(EventMouse::MouseEventType::MOUSE_DOWN);
event.setCursorPosition(_mouseX,
this
->getViewPortRect().size.height - _mouseY);
event.setMouseButton(button);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
else
if
(GLFW_RELEASE == action)
EventMouse event(EventMouse::MouseEventType::MOUSE_UP);
event.setCursorPosition(_mouseX,
this
->getViewPortRect().size.height - _mouseY);
event.setMouseButton(button);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
void
GLView::onGLFWMouseMoveCallBack(GLFWwindow* window,
double
x,
double
y)
_mouseX /=
this
->getFrameZoomFactor();
_mouseY /=
this
->getFrameZoomFactor();
this
->handleTouchesMove(1, &id, &_mouseX, &_mouseY);
EventMouse event(EventMouse::MouseEventType::MOUSE_MOVE);
event.setCursorPosition(_mouseX,
this
->getViewPortRect().size.height - _mouseY);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
void
GLView::onGLFWMouseScrollCallback(GLFWwindow* window,
double
x,
double
y)
EventMouse event(EventMouse::MouseEventType::MOUSE_SCROLL);
event.setScrollData((
float
)x, -(
float
)y);
event.setCursorPosition(_mouseX,
this
->getViewPortRect().size.height - _mouseY);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
void
GLView::onGLFWKeyCallback(GLFWwindow *window,
int
key,
int
scancode,
int
action,
int
mods)
if
(GLFW_REPEAT != action)
EventKeyboard event(g_keyCodeMap[key], GLFW_PRESS == action);
auto dispatcher = Director::getInstance()->getEventDispatcher();
dispatcher->dispatchEvent(&event);
void
GLView::onGLFWCharCallback(GLFWwindow *window, unsigned
int
character)
IMEDispatcher::sharedDispatcher()->dispatchInsertText((
const
char
*) &character, 1);
void
GLView::onGLFWWindowPosCallback(GLFWwindow *windows,
int
x,
int
y)
Director::getInstance()->setViewport();
void
GLView::onGLFWframebuffersize(GLFWwindow* window,
int
w,
int
h)
float
frameSizeW = _screenSize.width;
float
frameSizeH = _screenSize.height;
float
factorX = frameSizeW / w * _retinaFactor * _frameZoomFactor;
float
factorY = frameSizeH / h * _retinaFactor * _frameZoomFactor;
if
(
fabs
(factorX - 0.5f) < FLT_EPSILON &&
fabs
(factorY - 0.5f) < FLT_EPSILON )
_isInRetinaMonitor =
true
;
glfwSetWindowSize(window,
static_cast
<
int
>(frameSizeW * 0.5f * _retinaFactor * _frameZoomFactor) ,
static_cast
<
int
>(frameSizeH * 0.5f * _retinaFactor * _frameZoomFactor));
else
if
(
fabs
(factorX - 2.0f) < FLT_EPSILON &&
fabs
(factorY - 2.0f) < FLT_EPSILON)
_isInRetinaMonitor =
false
;
glfwSetWindowSize(window,
static_cast
<
int
>(frameSizeW * _retinaFactor * _frameZoomFactor),
static_cast
<
int
>(frameSizeH * _retinaFactor * _frameZoomFactor));
void
GLView::onGLFWWindowSizeFunCallback(GLFWwindow *window,
int
width,
int
height)
if
(_resolutionPolicy != ResolutionPolicy::UNKNOWN)
updateDesignResolutionSize();
Director::getInstance()->setViewport();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
static
bool
glew_dynamic_binding()
const
char
*gl_extensions = (
const
char
*)glGetString(GL_EXTENSIONS);
if
(glGenFramebuffers == NULL)
log
(
"OpenGL: glGenFramebuffers is NULL, try to detect an extension"
);
if
(
strstr
(gl_extensions,
"ARB_framebuffer_object"
))
log
(
"OpenGL: ARB_framebuffer_object is supported"
);
glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) wglGetProcAddress(
"glIsRenderbuffer"
);
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) wglGetProcAddress(
"glGenerateMipmap"
);
if
(
strstr
(gl_extensions,
"EXT_framebuffer_object"
))
log
(
"OpenGL: EXT_framebuffer_object is supported"
);
glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) wglGetProcAddress(
"glIsRenderbufferEXT"
);
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) wglGetProcAddress(
"glGenerateMipmapEXT"
);
log
(
"OpenGL: No framebuffers extension is supported"
);
log
(
"OpenGL: Any call to Fbo will crash!"
);
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
GLenum GlewInitResult = glewInit();
if
(GLEW_OK != GlewInitResult)
MessageBox((
char
*)glewGetErrorString(GlewInitResult),
"OpenGL error"
);
if
(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
log
(
"Not totally ready :("
);
if
(glewIsSupported(
"GL_VERSION_2_0"
))
log
(
"Ready for OpenGL 2.0"
);
log
(
"OpenGL 2.0 not supported"
);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
if
(glew_dynamic_binding() ==
false
)
MessageBox(
"No OpenGL framebuffer support. Please upgrade the driver of your video card."
,
"OpenGL error"
);
#endif // (CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
这里我们再看一下GLView的继承关系:
class
CC_DLL GLView :
public
GLViewProtocol,
public
Ref
这里【 Ref 】是用来管理引用计数的。 这里【 GLViewProtocol 】是一个基类,各个平台下会对其进行继承,继承之后的名称都为GLView。
2 鼠标事件响应
glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);
GLView中注册了相关鼠标事件,当发生鼠标事件时,首先执行:GLView::pollEvents() ,然后调用注册后的GLFWEventHandler::onGLFWMouseCallBack ,接着基于鼠标点击状态调用
this
->handleTouchesBegin(1, &id, &_mouseX, &_mouseY);
或者this
->handleTouchesEnd(1, &id, &_mouseX, &_mouseY);