Mugichoko's blog

Mugichoko’s blog

プログラミングを中心としたメモ書き.

ImGui + Native File Dialog

前回はImGui + GLFW + GLEWを使ってGLFWのウィンドウ内にImGuiのウィジェットを表示させる公式のサンプルを動かしました.今回は,自分のコードにImGuiを導入するとともに,ImGuiには欠けているダイアログ機能を追加します.

mugichoko.hatenablog.com

前回不明だったこと

  • ダイアログボックスを表示させてファイル入出力を管理する方法
  • OpenGLでの3DレンダリングとImGuiの組み合わせ方

実装

開発環境

Native File Dialogの設定

前回の最後に紹介したNative File Dialog (NFD)ライブラリを使ってダイアログを操作してみます.

GitHubからクローンしたzipファイルを展開します.以降,その場所をNFD_PATHとしましょう.NFD_PATH/build/vs2010/内に入っているプロジェクトをビルドするとライブラリが生成されます.Visual Studioには,以下を設定する必要があります.

  • 追加のインクルードディレクト
    • NFD_PATH/src/include
  • 追加のライブラリディレクト
    • Debug:NFD_PATH/build/lib/Debug/x64
    • Release:NFD_PATH/build/lib/Release/x64
  • 追加の依存ファイル
    • Debug:nfd_d.lib
    • Release:nfd.lib

サンプルのコードにもありますが,以下の様にすると,例えば,「開く」を実装できます.具体的には,以下の2行目でOSに準じたダイアログボックスが立ち上がり,選択したファイルへの絶対パスoutPathに格納されます.短いコードで実装できて楽です.

nfdchar_t *outPath = new nfdchar_t;
nfdresult_t result = NFD_OpenDialog("png,jpg;pdf", NULL, &outPath);

ImGuiの設定

ImGuiのフォルダ直下をIMGUI_PATHとして話を進めます.前回は単にNFD_PATH/examples/example_glfw_open3にあるプロジェクトを実行しただけでした.

今回分かったことなのですが,このプロジェクト内で使われているexample_glfw_opengl3プロジェクトの実装部分が今後も必要になってきそうだったので,まず,ライブラリ化しておきました.これをexample_glfw_opengl3.libとします.

Visual Studioには,以下を設定する必要があります.

  • 追加のインクルードディレクト
    • IMGUI_PATH
    • IMGUI_PATH/examples
  • 追加のライブラリディレクト
    • Debug:IMGUI_PATH/examples/example_glfw_opengl3/Debug
    • Release:IMGUI_PATH/examples/example_glfw_opengl3/Release
  • 追加の依存ファイル
    • Debug:example_glfw_opengl3.lib
    • Release:example_glfw_opengl3.lib

疑似コード

限りなく実例に近いコードです.これだけでは当然動かないので悪しからず.CGのレンダリングをImGuiよりも先に行わないと,レンダリングされたCGの後ろにImGuiのウィジェットが隠れてしまいます.

#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <nfd.h>

void render()
{
    glm::vec4 clearColor(0.2f, 0.8f, 0.6f, 1.0f);
    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        clearBuffers(clearColor.r, clearColor.g, clearColor.b, clearColor.a);

        // ここでOpenGLによるCGのレンダリング

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        if (ImGui::BeginMainMenuBar())
        {
            if (ImGui::BeginMenu("File"))
            {
                if (ImGui::MenuItem("Open", "CTRL+O"))
                {
                    nfdchar_t *outPath = new nfdchar_t;
                    nfdresult_t result = NFD_OpenDialog("png,jpg;pdf", NULL, &outPath);
                    if (result == NFD_OKAY)
                    {
                        std::cout << "[NFD::Open] " << outPath << std::endl;
                        delete outPath;
                    }
                    // do error handling
                }
                if (ImGui::MenuItem("Save", "CTRL+S")) { /* do something */ }
    
                ImGui::EndMenu();
            }
        }
        ImGui::EndMainMenuBar();
    }
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

    swapBuffers();
}

結果

以下の様に,ボタンが押されたときにダイアログが立ち上がり,ファイルを選択すると,先のコードの30行目にあるstd::coutで,得られた絶対パスコマンドプロンプトに表示されました.尚,ダイアログボックスが出ているときは,OpenGLでの描画は止まっているようでした.

f:id:Mugichoko:20181027070511p:plain