NSTextField поверх NSOpenGLView
Я сделал окно с NSOpenGLView, в которое я рендеринг контента openGL.
Я хочу добавить несколько кнопок и текстовых полей к представлению: я могу добавить NSTextFields и NSButtons, используя построитель интерфейса (или код), но они не отображаются.
NSOpenGLView задокументирован как неспособный иметь подвиды, поэтому я затем создал свой собственный CustomGLView, напрямую производя от NSView и реализуя код для создания и использования в нем NSOpenGLContext. Но подпредставления все еще не появляются:- контекст OpenGL закрашивает их.
В Windows эта проблема не существует:- Windows, используемая для размещения OpenGL, ДОЛЖНА иметь WS_CLIPCHILDREN
а также WS_CHIPSIBLINGS
набор стилей, гарантирующий, что любой одноранговый узел или дочерние элементы (представления) не будут скрыты поверхностью OpenGL.
Как мне получить подпредставления для отображения поверх рисунка NSView, используя OpenGL?
7 ответов
У вас есть 2 варианта:
Создайте окно только для текстового поля. Добавьте в качестве дочернего окна того, в котором размещается представление OpenGL. Основным недостатком является то, что вы должны правильно позиционировать его, если перемещен вид Open GL.
Настройте иерархию представления следующим образом:
- Многослойный вид
- Layer- хостинг, чей слой содержит слой OpenGL
- Текстовое поле
- Многослойный вид
Просто позвони -setWantsLayer:YES
на подпредставлениях NSOpenGLView.
NSOpenGLView не может иметь подпредставления в соответствии с документацией. Даже если вы создадите подкласс NSOpenGLView, это ничего не изменит.
Что вы можете сделать, это создать NSView, который будет содержать как NSOpenGLView, так и NSTextField. Затем вы перекрываете их в правильном порядке, чтобы сделать одну ничью поверх другой.
Это было мое решение:
1) Создайте родительский NSView (назовем его parentView).
2) Добавьте дочерний элемент NSOpenGLView в parentView.
3) Добавьте дополнительный дочерний элемент NSView в parentView (убедитесь, что это после OpenGLView в иерархии). Вы можете добавить дополнительные TextFields и т. Д. Для этого представления.
4) В ViewController для родителя убедитесь, что вы вызываете [parentView setWantsLayer: TRUE]; Я сделал это в пределах -(void) viewWillAppear
Я пока не сильно разбираюсь в OpenGL, но, насколько я понимаю, вы можете добиться визуального эффекта подпредставлений с помощью Quartz Extreme с использованием представлений со слоистой поддержкой; Однако это может быть проблематично. Поскольку подпредставления не поддерживаются напрямую, любое решение может быть взломано.
Действительно, решение в этой ссылке фактически взламывает второе окно, которое появляется поверх вашего дисплея OpenGL, второе окно, отображающее представления Какао, которые вы желаете.
Следующий код (из приведенной выше ссылки) - это то, что я не тестировал (опять же, не являясь парнем из OpenGL по своей природе - пока), но выглядит как довольно умный подход:
// 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];
Опять же, я не проверял это, но похоже, что он даст вам визуальный эффект, который вы хотите.
1) NSOpenGLView может иметь подпредставление. Это может иметь много даже.
2) Причина, по которой некоторые представления, элементы управления и другие элементы подвергаются издевательствам со стороны NSOpenGLView, связана с процессом загрузки при запуске приложения. Т.е., если вы добавите ползунок или текстовое поле выше и в представление содержимого окна, в котором также находится NSOpenGLView, при запуске приложения это текстовое поле, скорее всего, окажется под NSOpenGLView.
Это ошибка Apple. И они знают об этом.
Вы можете решить это довольно легко, даже не добавляя подпредставление для NSOpenGLView...
В Интерфейсном Разработчике перетащите то есть CustomView на холст (не вид). И установите его так, как вы хотите, с помощью ползунков, текста, а что нет. Затем создайте выход (назовите его, т.е. topView) в вашем контроллере представления. Тогда где-нибудь в вашем коде... Возможно (applicationDidFinishLaunching) добавить эту строку...
[_window.contentView addSubview: _topView]; (Сделайте свое позиционирование и макет) Это будет делать то же самое, как если бы вы перетаскивали его в contentView внутри IB. Только он нарисует чертову вещь в правильном Z-положении.
Таким образом, вы теряете ограничения IB и вынуждены делать это вручную
Можно также просто создать подкласс и CAOpenGLLayer и использовать его в качестве вспомогательного слоя внутри обычного NSView. Там тоже нарисовано правильно...
Вот способ Apple, желающий сделать это. CALayers являются находкой;)
Введите следующую строку ** NSOpenGLLayer** в поиске и нажмите Enter, чтобы добраться до места, где она находится... NSOpenGLLayer
Надеюсь это поможет....
Текст может быть преобразован в текстуру - я просто использовал это для проекта, много искал пример кода и в конечном итоге нашел демонстрационный код Apple GLString, который был абсолютной попыткой с практическими рекомендациями:
http://developer.apple.com/library/mac/
Я не пробовал добавлять кнопки, но вы, конечно, можете нарисовать свои собственные и сравнить позиции событий нажатия с позициями ваших кнопок...