前回この記事で紹介した、NSViewComponentのZ-Orderを変えるやりかた。
もっと簡単でシンプルな方法がありましたので、そちらを書きます。
前回の記事では、JUCEライブラリの奥にアクセスして、該当箇所に直接コードを書き足していましたが、必要なメンバを呼び出して変更するやり方です。
よって、JUCEライブラリ自体を書き換える必要はありません。
前回に引き続きお断りですが、このやり方はNSViewを直接呼び出して処理を行うので、macOSでしか有効ではありません。
#実装
クラス、NSViewManager を作成します。
class NSViewManager
{
public:
IRNSViewManager(){}
~IRNSViewManager(){}
// works only on macOS
void bringOpenGLContextFront(juce::Component* owner, NSViewComponent* view);
}
#include "NSViewManager.hpp"
// Empty
まず、NSViewManagerクラスのhpp, cpp ファイルを作成。
cppファイルは空で構いません。
次に、Objective-C++ファイルを作成し、NSViewManager.cpp ファイルをインクルードします。
#import <AppKit/AppKit.h>
#include "IRNSViewManager.cpp"
void IRNSViewManager::bringOpenGLContextFront(juce::Component* owner, NSViewComponent* view)
{
auto* peer = owner->getPeer();
auto v = (NSView*) view->getView();
if(peer != nullptr)
{
auto peerView = (NSView*) peer->getNativeHandle();
[v retain];
[v removeFromSuperview];
[peerView addSubview: v];
[v release];
}
[v setHidden: ! owner->isShowing()];
}
使い方
例えば、VideoComponentを持つクラスに対して、
void bringViewToFront()
{
#if JUCE_MAC
NSViewComponent* view = static_cast<NSViewComponent*>(this->player_with_controller->getPimpl());
if(view == nullptr) return;
IRNSViewManager manager;
manager.bringOpenGLContextFront(this, view);
#endif
}
と、ここですみません。前言撤回。JuceのVideoComponentヘッダーファイルに一行足して、Pimpl型の変数ポインタを取得する必要がありました。
void* getPimpl() { return pimpl.get(); }
OpenGLContext
上では、より一般的にNSViewのコントロール方法、次は、OpenGLContextです。
今回は、Z-Orderだけではなく、OpenGLContextのアルファ値を変更するメソッドも追加で紹介します。
OpenGLContextを使用した際、背景を透過させたい時に使用してください。
ただし、setOpenGLContextAlphaメソッドは、該当ComponentをaddAndMakeVisibleにてバインドした後に実行する必要があります。
class OpenGLManager
{
public:
OpenGLManager(OpenGLContext* context) : context(context)
{
}
~OpenGLManager()
{
}
void setOpenGLContextAlpha(GLint aValue = 0);
void bringOpenGLContextFront(juce::Component* owner);
private:
OpenGLContext* context;
};
#include "OpenGLManager.hpp"
#import <AppKit/AppKit.h>
#include "OpenGLManager.cpp"
void IROpenGLManager::setOpenGLContextAlpha(GLint aValue)
{
NSOpenGLContext* context = (NSOpenGLContext*)this->context->getRawContext();
if(context != nullptr)
[context setValues:&aValue forParameter:NSOpenGLCPSurfaceOpacity];
else
std::cout << "Error : IROpenGLManager::setOpenGLContextAlpha() : could not get NSOpenGLContext : nullptr\n";
}
void IROpenGLManager::bringOpenGLContextFront(juce::Component* owner)
{
NSOpenGLContext* context = (NSOpenGLContext*)this->context->getRawContext();
if(context == nullptr)
{
std::cout << "Error : IROpenGLManager::bringOpenGLContextFront() : could not get NSOpenGLContext : nullptr\n";
return;
}
auto* peer = owner->getPeer();
if(peer != nullptr)
{
auto peerView = (NSView*) peer->getNativeHandle();
[context.view retain];
[context.view removeFromSuperview];
[peerView addSubview: context.view];
[context.view release];
}
[context.view setHidden: ! owner->isShowing()];
}
#使い方
void bringViewToFront() { //this->openGLContext.bringViewToFront();
IROpenGLManager manager(&this->openGLContext);
manager.bringOpenGLContextFront(this);
}
背景を透過する時は、OpenGLRendererを継承し、
// inherit
public OpenGLRenderer
void newOpenGLContextCreated()override
{
}
virtual void renderOpenGL()override
{
// make the background transparent
OpenGLHelpers::clear(Colours::transparentBlack);
}
virtual void openGLContextClosing() override
{
}
背景色を透明にする必要があります。
OpenGLManagerを使用する際は、JUCEライブラリをいじる必要はありません。