本文原链接: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/5/Headers qt/QtCore.framework/Versions/5/Headers qt/QtGui.framework/Versions/5/Headers qt/QtOpenGL.framework/Versions/5/Headers
2、把 AppController.mm 文件从 HelloCpp 工程移除;把 WGLWidget.h 和 WGLWidget.mm 文件加到 HelloCpp 工程,文件内容具体如下:
1 #ifndef WGLWIDGET_H 2 #define WGLWIDGET_H 3 4 #include <QWidget> 5 #include <QtOpenGL> 6 #include "EAGLView.h" 7 8 class WGLWidget : public QWidget 9 { 10 11 public: 12 WGLWidget(QWidget *parent = 0); 13 ~WGLWidget(); 14 15 private: 16 EAGLView* _glView; 17 NSWindow* _NSWindow; 18 int glviewWidth; 19 int glviewHeight; 20 21 protected: 22 23 virtual void mouseDoubleClickEvent(QMouseEvent *event); 24 virtual void closeEvent(QCloseEvent *event); 25 virtual void resizeEvent(QResizeEvent *event); 26 27 28 }; 29 30 #endif // WGLWIDGET_H
1 #include "wglwidget.h" 2 #import "AppDelegate.h" 3 4 5 static AppDelegate s_sharedApplication; 6 7 WGLWidget::WGLWidget(QWidget *parent /* = 0 */): QWidget(parent) 8 { 9 this->glviewWidth = 480; 10 this->glviewHeight = 320; 11 12 setMinimumSize(this->glviewWidth, this->glviewHeight); 13 setWindowTitle("HelloCpp"); 14 setStyleSheet("background:green"); 15 16 17 //以下设置参考自:AppController。mm 18 NSRect rect = NSMakeRect(0, 0, this->glviewWidth, this->glviewHeight); 19 20 _NSWindow = [[NSWindow alloc] initWithContentRect:rect 21 styleMask:(NSBorderlessWindowMask ) 22 backing:NSBackingStoreBuffered 23 defer:YES]; 24 25 [_NSWindow setBackgroundColor:[NSColor redColor]]; 26 NSOpenGLPixelFormatAttribute attributes[] = { 27 NSOpenGLPFADoubleBuffer, 28 NSOpenGLPFADepthSize, 24, 29 NSOpenGLPFAStencilSize, 8, 30 0 31 }; 32 33 NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; 34 35 _glView = [[EAGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; 36 37 [_glView reshape]; 38 39 // set window parameters 40 [_NSWindow becomeFirstResponder]; 41 [_NSWindow setContentView:_glView]; 42 [_NSWindow setAcceptsMouseMovedEvents:NO]; 43 44 45 46 //通过 EAGLView* 对象来创建 QWindow,然后根据 QWindow 对象来创建 QWidget 47 QWindow* _glWindow = QWindow::fromWinId((WId) _glView); 48 QWidget* _glWidget = QWidget::createWindowContainer(_glWindow, parent); 49 50 _glWidget->setParent(this); 51 _glWidget->resize(this->glviewWidth, this->glviewHeight); 52 53 54 cocos2d::CCApplication::sharedApplication()->run(); 55 56 } 57 58 WGLWidget::~WGLWidget() 59 { 60 61 } 62 63 64 void WGLWidget::mouseDoubleClickEvent(QMouseEvent *event) 65 { 66 if(windowState() & Qt::WindowFullScreen) 67 showNormal(); 68 else 69 showFullScreen(); 70 } 71 72 73 74 void WGLWidget::resizeEvent(QResizeEvent *event) 75 { 76 QSize size = event->size(); 77 // printf("resizeEvent "); 78 // printf(" %d height: %d ", size.width(), size.height()); 79 80 //重绘 NSWindow 和 GLView 窗口 81 NSRect rect = NSMakeRect(0, 0, size.width(), size.height()); 82 [_NSWindow setFrame:rect display:YES animate:NO]; 83 84 cocos2d::CCEGLView* glView = cocos2d::CCEGLView::sharedOpenGLView(); 85 glView->setFrameSize(size.width(), size.height());// 86 glView->setDesignResolutionSize(this->glviewWidth, this->glviewHeight, kResolutionShowAll); 87 88 } 89 90 91 92 void WGLWidget::closeEvent(QCloseEvent *event) 93 { 94 QWidget::closeEvent(event); 95 }
3、把 main.m 文件改名为:main.mm,内容修改如下:
1 //#import <Cocoa/Cocoa.h> 2 #include <QApplication> 3 #include "WGLWidget.h" 4 5 int main(int argc, char *argv[]) 6 { 7 QApplication app(argc, argv); 8 9 WGLWidget mainWindow; 10 mainWindow.show(); 11 app.installEventFilter(&mainWindow); 12 return app.exec(); 13 14 //return NSApplicationMain(argc, (const char **)argv); 15 }
4、拉伸以下宽高看看效果,达到预期效果
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