2
0

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 1 year has passed since last update.

JUCEAdvent Calendar 2022

Day 23

[JUCE] ホットリローダーの実装

Last updated at Posted at 2022-12-23

hot_reloaderモジュール

各種ファイルのホットリローダーが欲しい時、毎回実装してしまっていたのですがせっかくなのでmodule化して使いまわせるようにしました。
ファイル(もしくはディレクトリの場合は再帰的に子ファイル)の更新状況を監視し、変更があればコールバックを呼びます。
ソースコード一つのみなのでJUCE moduleではなくてソースコードに直接含めるのでもいいかもしれません。

使用方法

projucerの場合は「Modules」でhot_reloaderモジュールを追加し以下のように使用可能です。

    // .h
    std::unique_ptr<HotReloader> fileHotReloader;

    // .cpp
    auto fileReloadCallback = [this](const juce::File& file)
    {
        // ファイル更新時の処理
    };
    fileHotReloader.reset(new HotReloader(/* 監視対象のjuce::File */, fileReloadCallback));

サンプルコード

hotReloaderTest.gif

以下のようなファイル階層でsample.txtとsampleFolderの更新があった場合にコンポーネントの更新を行っています。

Resources/
├ sample.txt
└ sampleFolder/
  ├ sample1.txt
  ├ sample2.txt
  └ ...

sampleFolderフォルダ以下は子を再帰的にチェックしてそのファイルの数だけテキスト表示コンポーネントを追加しています。
(例: sampleFolder/sub/sample.txtファイルを追加するとテキスト表示コンポーネントが追加表示されます。)

projucer設定

  • 「Modules」でhot_reloaderを追加、
  • 「Exporters/Xcode(macOS)」「Custom Xcode Resource Folders」に
    • Resources/sample.txt
    • Resources/sampleFolder を追加

ソースコード

MainComponent.h

#pragma once

#include <JuceHeader.h>

//==============================================================================
class MainComponent  : public juce::Component
{
public:
    //==============================================================================
    MainComponent();
    ~MainComponent() override;

    //==============================================================================
    void paint (juce::Graphics&) override;
    void resized() override;

private:
    //==============================================================================
    // Resources/sample.txt
    std::unique_ptr<HotReloader> fileHotReloader;
    juce::TextEditor fileTextView;

    // Resources/sampleFolderフォルダ
    void resetFolderViewBounds(juce::Rectangle<int> area);
    std::unique_ptr<HotReloader> folderHotReloader;
    juce::OwnedArray<juce::TextEditor> folderFileTextView;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

MainComponent.cpp
#include "MainComponent.h"

//==============================================================================
MainComponent::MainComponent()
{
    juce::File rsrcDir = juce::File::getSpecialLocation(juce::File::SpecialLocationType::currentApplicationFile).getChildFile("Contents/Resources");
    
    //------------------------------------------
    // Resources/sample.txt
    //------------------------------------------
    addAndMakeVisible(fileTextView);
    fileTextView.setMultiLine(true);
    fileTextView.setReadOnly(true);
    
    auto fileReloadCallback = [this](const juce::File& file)
    {
        fileTextView.setText(file.loadFileAsString());
    };
    fileHotReloader.reset(new HotReloader(rsrcDir.getChildFile("sample.txt"), fileReloadCallback));
    
    //------------------------------------------
    // Resources/sampleFolderフォルダ
    //------------------------------------------
    auto folderReloadCallback = [this](const juce::File& folder)
    {
        juce::Array<juce::File> fileList = folder.findChildFiles(juce::File::TypesOfFileToFind::findFiles, true);

        folderFileTextView.clear();
        for (auto& f: fileList)
        {
            auto* textView = new juce::TextEditor();
            addAndMakeVisible(textView);
            textView->setMultiLine(true);
            textView->setReadOnly(true);
            textView->setText(f.loadFileAsString());
            folderFileTextView.add(textView);
        }
        
        auto area = getLocalBounds();
        area.removeFromTop(80);
        resetFolderViewBounds(area);
    };
    folderHotReloader.reset(new HotReloader(rsrcDir.getChildFile("sampleFolder"), folderReloadCallback));
    
    setSize (600, 400);
}

MainComponent::~MainComponent()
{
}

//==============================================================================
void MainComponent::paint (juce::Graphics& g)
{
    g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
}

void MainComponent::resized()
{
    auto area = getLocalBounds();
    fileTextView.setBounds(area.removeFromTop(80));
    resetFolderViewBounds(area);
}

//==============================================================================
void MainComponent::resetFolderViewBounds(juce::Rectangle<int> area)
{
    area.removeFromLeft(20);
    for (auto* const textView : folderFileTextView)
    {
        textView->setBounds(area.removeFromTop(80));
    }
}

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?