top of page
- Detail -
RADNODZのUnreal Engine 5用プラグインを使用してRIGDOCKSのAPIを使用し、Reaperを操作するアプリを作成します。
本プロジェクトではReaperのトラック情報を取得し、それをUnreal Engine 5で作成したUIパーツで表示します。
- Images -
- Link -
- Youtube -
- Sources -
RadnodzDemoWidget.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "RadnodzDemoWidget.generated.h"
class UButton;
class UEditableTextBox;
class UTextBlock;
class URadnodzClient;
class UScrollBox;
class UTrackCardWidget;
/**
* REAPER に接続し、選択中のメディアアイテムのうち 1 つ目の名前を変更するデモ画面。
*/
UCLASS()
class REAPERCONTROLLER_API URadnodzDemoWidget : public UUserWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
virtual void NativeDestruct() override;
// ---- UMG のパーツと結びつける ----
// ここの変数名は、Widget Blueprint 側のパーツ名と完全に一致させること
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UEditableTextBox> IpTextBox;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UEditableTextBox> PortTextBox;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UButton> ConnectButton;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UTextBlock> StatusText;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UScrollBox> TrackList;
UPROPERTY(BlueprintReadWrite)
TObjectPtr<URadnodzClient> Client;
UPROPERTY(EditDefaultsOnly, Category = "UI|TrackCard")
TSubclassOf<UTrackCardWidget> TrackCardClass;
private:
UFUNCTION()
void OnConnectClicked();
/** 未接続なら Connect する。成功したら true。失敗理由は StatusText に出す。 */
bool EnsureConnected();
void SetStatus(const FString& Message);
// エラー情報からステータス表示
void DisplayError();
// トラックリスト取得
void GetTrackList();
};
RadnodzDemoWidget.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "RadnodzDemoWidget.h"
#include "TrackCardWidget.h"
#include "RadnodzClient.h"
#include "RigdocksError.h"
#include "RigdocksSilver_Track.h" // トラック操作
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"
#include "Components/ScrollBox.h"
namespace
{
// 選択中のメディアアイテムのうち 1 つ目
constexpr int FirstSelectedItemID = 0;
}
void URadnodzDemoWidget::NativeConstruct()
{
Super::NativeConstruct();
StatusText->SetText(FText::GetEmpty());
// ボタンが押されたら OnRenameClicked を呼ぶよう登録する
if (ConnectButton)
{
ConnectButton->OnClicked.AddDynamic(this, &URadnodzDemoWidget::OnConnectClicked);
}
}
void URadnodzDemoWidget::NativeDestruct()
{
if (Client && Client->IsConnected())
{
Client->Disconnect();
}
Super::NativeDestruct();
}
void URadnodzDemoWidget::SetStatus(const FString& Message)
{
if (StatusText)
{
StatusText->SetText(FText::FromString(Message));
}
UE_LOG(LogTemp, Log, TEXT("[RADNODZ] %s"), *Message);
}
bool URadnodzDemoWidget::EnsureConnected()
{
// クライアントは初回だけ生成し、以降は使い回す
if (!Client)
{
Client = URadnodzClient::CreateRadnodzClient();
}
if (Client->IsConnected())
{
return true;
}
if (!IpTextBox || !PortTextBox)
{
SetStatus(TEXT("IP / ポートの入力欄が見つかりません"));
return false;
}
const FString Ip = IpTextBox->GetText().ToString().TrimStartAndEnd();
const FString PortString = PortTextBox->GetText().ToString().TrimStartAndEnd();
if (Ip.IsEmpty())
{
SetStatus(TEXT("IP を入力してください"));
return false;
}
if (!PortString.IsNumeric())
{
SetStatus(TEXT("ポートは数字で入力してください"));
return false;
}
const int Port = FCString::Atoi(*PortString);
Client->Connect(Ip, Port);
// 成否は戻り値ではなく GetError() で判定する
const FRigdocksError Error = Client->GetError();
if (Error.ErrorCode != static_cast<int>(AZ_ErrorCode::Success) || !Client->IsConnected())
{
SetStatus(FString::Printf(TEXT("接続失敗 (%d): %s"), Error.ErrorCode, *Error.Message));
return false;
}
return true;
}
void URadnodzDemoWidget::DisplayError()
{
FRigdocksError error = Client->GetError();
SetStatus(FString::Printf(TEXT("接続失敗 (%d): %s %s"), error.ErrorCode, *error.Message, *error.Details));
}
// トラックリスト取得
void URadnodzDemoWidget::GetTrackList()
{
// Designer で作った WBP_TrackCard を生成しないと、画面構成が無く何も表示されない
if (!TrackCardClass)
{
SetStatus(TEXT("TrackCardClass が未設定です"));
return;
}
// リスト全削除
TrackList->ClearChildren();
TArray<FTrackDetail> TrackDetails = URigdocksSilver_Track::AZ_GetTrackListDetail(Client, 0);
// 成否判定
if (Client->GetError().ErrorCode != static_cast<int>(AZ_ErrorCode::Success))
{
DisplayError();
return;
}
for (const FTrackDetail& trackDetail : TrackDetails)
{
UTrackCardWidget* Card = CreateWidget<UTrackCardWidget>(this, TrackCardClass);
Card->SetTrackDetail(trackDetail);
TrackList->AddChild(Card);
}
SetStatus(FString::Printf(TEXT("トラックを %d 件取得しました"), TrackDetails.Num()));
}
void URadnodzDemoWidget::OnConnectClicked()
{
// ---- 1. クライアントを用意する(初回だけ生成し、以降は使い回す)----
if (!Client)
{
Client = URadnodzClient::CreateRadnodzClient();
}
// ---- 2. 接続する ----
const FString Ip = IpTextBox->GetText().ToString();
const FString Port = PortTextBox->GetText().ToString();
if (!Client->Connect(Ip, FCString::Atoi(*Port)))
{
DisplayError();
return;
}
SetStatus(TEXT("接続に成功しました"));
// ---- 3. トラックリスト表示 ----
GetTrackList();
// ---- 4. 切断 ----
Client->Disconnect();
}TrackCardWidget.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "DataClass/FTrackDetail.h"
#include "TrackCardWidget.generated.h"
class UTextBlock;
class UEditableTextBox;
UCLASS()
class REAPERCONTROLLER_API UTrackCardWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SetTrackDetail(FTrackDetail trackDetail);
/** トラックのインデックス */
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UTextBlock> IndexText;
/** トラック名 */
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UEditableTextBox> TrackNameText;
/** 音量 */
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
TObjectPtr<UTextBlock> VolumeText;
/** トラック詳細(保存用) */
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn = true))
FTrackDetail TrackDetail;
protected:
virtual void NativePreConstruct() override;
private:
// 表示内容更新
void RefreshTexts();
};
TrackCardWidget.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "TrackCardWidget.h"
#include "Components/TextBlock.h"
#include "Components/EditableTextBox.h"
// ============================================================
// 表示内容
// ============================================================
void UTrackCardWidget::NativePreConstruct()
{
Super::NativePreConstruct();
RefreshTexts();
}
void UTrackCardWidget::SetTrackDetail(FTrackDetail trackDetail)
{
TrackDetail = trackDetail;
RefreshTexts();
}
void UTrackCardWidget::RefreshTexts()
{
if (IndexText)
{
IndexText->SetText(FText::FromString(FString::FromInt(TrackDetail.Index + 1)));
}
if (TrackNameText)
{
TrackNameText->SetText(FText::FromString(TrackDetail.Name));
}
if (VolumeText)
{
FNumberFormattingOptions Opts;
Opts.SetMinimumFractionalDigits(0) // 最低0桁
.SetMaximumFractionalDigits(2); // 最大0桁
VolumeText->SetText(FText::AsNumber(TrackDetail.Volume, &Opts));
}
}







