Cocos2dx 把 glview 渲染到 Qt 控件上(Mac 环境)

时间:2021-04-02 09:09:56

本文原链接:http://www.cnblogs.com/zouzf/p/4423256.html

环境:Mac 10.9.2   Xcode5.1.1  Qt5.3  cocos2dx-2.2.4

项目基于 cocos2dx 2.x 源码二次封装后的框架进行开发,其中控件部分及相关的触摸事件传递机制等都改掉了;为了提高开发效率,项目还开发了一个 UI 编辑器用于可视化编辑 UI,但只有 win32版,公司都是 Mac 系统,很多同事对于 i3 的 cpu 的要装虚拟机来使用这个编辑器甚是抱怨~~于是 Mac 版本的 UI 编辑提上议程,同事们对于旧版的 UI 编辑器也有各种使用抱怨,于是进行重写~~,兼顾 Mac 和 win,使用 Qt 框架。

win32版本同事不久就做好了,Mac 版本就由我先行一步:先把 GL 渲染到 Qt 这个难点解决。其实,另一个同事在做 cocos2dx 3.x 的 UI 编辑器Mac 版本的时候,已经做了这个功能的,那是真的把 cocos2dx 的 GL 渲染到 Qt 控件上的,但他使用了3.x里的  glfw3native 相关的东西,在处理触摸事件的时候把要进行坐标转换。坐标转换还好, glfw3native 那部分的东西就不太好移植过来了。

后来尝试了一个方法:cocos2dx Cpp 里的 Mac版本是把 GL 渲染到NSWindow上,而 NSWindow 是和工程里的 .xib 文件关联的 (这里可能有误,请了解的朋友指正);如果直接把这个 NSWindow 窗口加到 Qt 控件上会如何?

1、添加对 Qt framework 的库和头文件的引用

安装完 qt,在安装目录下找到 Qt5.3.0/5.3/clang_64/lib 目录, 把 QtCore.framework、QtGui.framework、QtOpenGL.framework、QtWidgets.framework四个文件拷贝到 cocos2d-x-2.2.3/samples/Cpp/HelloCpp/proj.mac/qt 里,qt 是自己建的文件夹。HelloCpp 工程里通过 Build Phases ->Link Binary With Libraries 添加这四个 framework 的引用;HelloCpp 工程里通过 Build Setting->Search Paths->Header Search Paths 添加以下头文件搜索路劲:

qt/QtWidgets.framework/Versions//Headers
qt/QtCore.framework/Versions//Headers
qt/QtGui.framework/Versions//Headers
qt/QtOpenGL.framework/Versions//Headers

2、把 AppController.mm 文件从 HelloCpp 工程移除;把 WGLWidget.h 和 WGLWidget.mm 文件加到 HelloCpp 工程,文件内容具体如下:

 #ifndef WGLWIDGET_H
#define WGLWIDGET_H #include <QWidget>
#include <QtOpenGL>
#include "EAGLView.h" class WGLWidget : public QWidget
{ public:
WGLWidget(QWidget *parent = );
~WGLWidget(); private:
EAGLView* _glView;
NSWindow* _NSWindow;
int glviewWidth;
int glviewHeight; protected: virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void closeEvent(QCloseEvent *event);
virtual void resizeEvent(QResizeEvent *event); }; #endif // WGLWIDGET_H
 #include "wglwidget.h"
#import "AppDelegate.h" static AppDelegate s_sharedApplication; WGLWidget::WGLWidget(QWidget *parent /* = 0 */): QWidget(parent)
{
this->glviewWidth = ;
this->glviewHeight = ; setMinimumSize(this->glviewWidth, this->glviewHeight);
setWindowTitle("HelloCpp");
setStyleSheet("background:green"); //以下设置参考自:AppController。mm
NSRect rect = NSMakeRect(, , this->glviewWidth, this->glviewHeight); _NSWindow = [[NSWindow alloc] initWithContentRect:rect
styleMask:(NSBorderlessWindowMask )
backing:NSBackingStoreBuffered
defer:YES]; [_NSWindow setBackgroundColor:[NSColor redColor]];
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, ,
NSOpenGLPFAStencilSize, , }; NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; _glView = [[EAGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; [_glView reshape]; // set window parameters
[_NSWindow becomeFirstResponder];
[_NSWindow setContentView:_glView];
[_NSWindow setAcceptsMouseMovedEvents:NO]; //通过 EAGLView* 对象来创建 QWindow,然后根据 QWindow 对象来创建 QWidget
QWindow* _glWindow = QWindow::fromWinId((WId) _glView);
QWidget* _glWidget = QWidget::createWindowContainer(_glWindow, parent); _glWidget->setParent(this);
_glWidget->resize(this->glviewWidth, this->glviewHeight); cocos2d::CCApplication::sharedApplication()->run(); } WGLWidget::~WGLWidget()
{ } void WGLWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
if(windowState() & Qt::WindowFullScreen)
showNormal();
else
showFullScreen();
} void WGLWidget::resizeEvent(QResizeEvent *event)
{
QSize size = event->size();
// printf("resizeEvent\n");
// printf("width: %d height: %d\n\n\n", size.width(), size.height()); //重绘 NSWindow 和 GLView 窗口
NSRect rect = NSMakeRect(, , size.width(), size.height());
[_NSWindow setFrame:rect display:YES animate:NO]; cocos2d::CCEGLView* glView = cocos2d::CCEGLView::sharedOpenGLView();
glView->setFrameSize(size.width(), size.height());//
glView->setDesignResolutionSize(this->glviewWidth, this->glviewHeight, kResolutionShowAll); } void WGLWidget::closeEvent(QCloseEvent *event)
{
QWidget::closeEvent(event);
}

3、把 main.m 文件改名为:main.mm,内容修改如下:

 //#import <Cocoa/Cocoa.h>
#include <QApplication>
#include "WGLWidget.h" int main(int argc, char *argv[])
{
QApplication app(argc, argv); WGLWidget mainWindow;
mainWindow.show();
app.installEventFilter(&mainWindow);
return app.exec(); //return NSApplicationMain(argc, (const char **)argv);
}

4、拉伸以下宽高看看效果,达到预期效果

Cocos2dx 把 glview 渲染到 Qt 控件上(Mac 环境)     Cocos2dx 把 glview 渲染到 Qt 控件上(Mac 环境)

Cocos2dx 把 glview 渲染到 Qt 控件上(Mac 环境)

5、总结

还是使用cocos2dx 自带的 AppController 类里创建 NSWindow 和 EAGLView 的那一套代码,然后用了个使巧的方法:

    QWindow* _glWindow = QWindow::fromWinId((WId) _glView);
QWidget* _glWidget = QWidget::createWindowContainer(_glWindow, parent); _glWidget->setParent(this);

实现了根据已有的 glview 窗口创建 QtWidget~~在 UI 编辑器里,你喜欢怎么操作这个 widget 都随意了~~

本文原链接:http://www.cnblogs.com/zouzf/p/4423256.html