1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[JUCE][MacOS]JUCEのNSViewComponentをフロントに持ってくる方法 改善版

Posted at

前回この記事で紹介した、NSViewComponentのZ-Orderを変えるやりかた。

もっと簡単でシンプルな方法がありましたので、そちらを書きます。

前回の記事では、JUCEライブラリの奥にアクセスして、該当箇所に直接コードを書き足していましたが、必要なメンバを呼び出して変更するやり方です。
よって、JUCEライブラリ自体を書き換える必要はありません。

前回に引き続きお断りですが、このやり方はNSViewを直接呼び出して処理を行うので、macOSでしか有効ではありません。

#実装

クラス、NSViewManager を作成します。

NSViewManager.hpp

class NSViewManager
{
public:
    IRNSViewManager(){}
    ~IRNSViewManager(){}
    
    // works only on macOS
    void bringOpenGLContextFront(juce::Component* owner, NSViewComponent* view);
}

NSViewManager.cpp

#include "NSViewManager.hpp"

// Empty

まず、NSViewManagerクラスのhpp, cpp ファイルを作成。
cppファイルは空で構いません。
次に、Objective-C++ファイルを作成し、NSViewManager.cpp ファイルをインクルードします。

NSViewManager_mac.mm

#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を持つクラスに対して、

AnyComponent.cpp

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型の変数ポインタを取得する必要がありました。

juce_VideoComponent.h

    void*  getPimpl() { return pimpl.get(); }

OpenGLContext

上では、より一般的にNSViewのコントロール方法、次は、OpenGLContextです。
今回は、Z-Orderだけではなく、OpenGLContextのアルファ値を変更するメソッドも追加で紹介します。
OpenGLContextを使用した際、背景を透過させたい時に使用してください。

ただし、setOpenGLContextAlphaメソッドは、該当ComponentをaddAndMakeVisibleにてバインドした後に実行する必要があります。

OpenGLManager.hpp

class OpenGLManager
{
public:
    OpenGLManager(OpenGLContext* context) : context(context)
    {
        
    }
    ~OpenGLManager()
    {
        
    }
    
    void setOpenGLContextAlpha(GLint aValue = 0);
    void bringOpenGLContextFront(juce::Component* owner);
    
private:
    OpenGLContext* context;
};

OpenGLManager.cpp

#include "OpenGLManager.hpp"

OpenGLManager_mac.mm
#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()];
}

#使い方

AnyComponent.hpp

void bringViewToFront() { //this->openGLContext.bringViewToFront();
        IROpenGLManager manager(&this->openGLContext);
        manager.bringOpenGLContextFront(this);
        
    }

背景を透過する時は、OpenGLRendererを継承し、

AnyComponent.hpp
// inherit
public OpenGLRenderer

    void newOpenGLContextCreated()override
    {
    }
       
        virtual void renderOpenGL()override
    {
        // make the background transparent
        OpenGLHelpers::clear(Colours::transparentBlack);
    }
    
    virtual void openGLContextClosing() override
    {
        
    }

背景色を透明にする必要があります。
OpenGLManagerを使用する際は、JUCEライブラリをいじる必要はありません。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?