NSTextField over NSOpenGLView

白昼怎懂夜的黑 提交于 2019-12-03 06:52:05

You have 2 choices:

  1. Create a window just for the text field. Add as a child window of the one hosting the OpenGL view. Major downside is you have to manage positioning it correctly if the Open GL view is moved.

  2. Set up your view hierarchy like so:

    • Layer-backed view
      • Layer-hosting view whose layer contains an OpenGL layer
      • Text field

Simply call -setWantsLayer:YES on the subviews of the NSOpenGLView.

NSOpenGLView cannot have subviews according to the documentation. Even if you subclass the NSOpenGLView, that will change nothing.

What you can do is to create a NSView that will hold both the NSOpenGLView and the NSTextField. You then overlap them in the right order to make one draw atop the other.

I'm not heavily into OpenGL yet, but it's my understanding that you can accomplish the visual effect of subviews with Quartz Extreme using layer-backed views; however, those may be problematic. Since subviews are not supported directly, any solution is liable to be a hack.

Indeed, the solution in that link actually hacks a second window to appear over your OpenGL display, the second window displaying the Cocoa views you desire.

The following code (from the above link) is something I've not tested (again not being an OpenGL guy by nature -- yet), but appears like a fairly clever approach:

// This is the GL Window and view you already have
glWindow = [[GLWindow alloc] initWithContentRect:windowRect];
glView = [[[GLView alloc] initWithFrame:NSMakeRect(0, 0, windowRect.size.width, windowRect.size.height)] autorelease];
[glView translateOriginToPoint:NSMakePoint(glView.bounds.size.width/2, glView.bounds.size.height/2)];
[glWindow setContentView:glView];

// And here's your transparent UI window
uiWindow = [[TransparentWindow alloc] initWithContentRect:windowRect];
uiView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, windowRect.size.width, windowRect.size.height)] autorelease];
[uiView translateOriginToPoint:NSMakePoint(uiView.bounds.size.width/2, uiView.bounds.size.height/2)];
uiView.wantsLayer = YES;

[uiWindow setContentView:uiView];
[glWindow addChildWindow:uiWindow ordered:NSWindowAbove];

Again, I've not tested this, but it looks like it will get you the visual effect you desire.

The text can be rendered into a texture -- I just used this for a project, did a lot of looking for sample code, and ultimately found Apple's GLString demo code, which was an absolute trove of how-to:

http://developer.apple.com/library/mac/#samplecode/CocoaGL/Listings/GLString_m.html

I haven't tried adding buttons, but you can, of course, draw your own and comparing the positions of click events with those of your buttons...

This was my solution:

1) Create a parent NSView (let's call it parentView).

2) Add an NSOpenGLView Child to parentView.

3) Add an additional NSView Child to parentView (make sure this is after the OpenGLView within the hierarchy). You can add additional TextFields, etc. to this view.

4) In the ViewController for the parent make sure you call [parentView setWantsLayer: TRUE]; I did this within -(void) viewWillAppear

1) The NSOpenGLView can have a subview. It can have plenty even.

2) The reason some views, controls and other elements are being bullied by NSOpenGLView is due to the loading process when the Application launches. I.e If you add a slider or textfield above and into the content view of the window where the NSOpenGLView also resides, upon Application-Launch that textfield will most likely wind up beneath the NSOpenGLView.

This is an Apple Bug. And they know about it.

You can solve it quite easily even without adding a subview to NSOpenGLView...

In Interface Builder drag i.e. a CustomView into the canvas (Not the view). And set it the way you want it with sliders, text and what not. Then create an outlet (Call it i.e topView) in your view controller. Then somewhere in your code... Perhaps (applicationDidFinishLaunching) add this line...

[_window.contentView addSubview:_topView]; (Do your positioning & layout) This will do the exact same thing as if you had dragged it into the contentView yourself inside IB. Only it will draw the darn thing in the correct Z position.

You loose IB's constraints this way and have to it manually

One could also just subclass and CAOpenGLLayer and use that as a backing layer inside of a regular NSView. There too it is drawn correctly...

Here is Apple's way of wanting to do that. CALayers are a Godsend ;)

Enter following String ** NSOpenGLLayer** in search and hit enter to get to where it is... NSOpenGLLayer

Hope this helps....

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!