UE4 DownloadImage を試してみる

# 概要
UnrealEngine の DownloadImage についての試してみたメモ書きです。


## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.25

## 参考
以下を参考にさせて頂きました、ありがとうございます。

[UE4 画像ファイルをURL指定でダウンロードする](http://kagring.blog.fc2.com/blog-entry-258.html)
[UE4 「Download Image」を使ってみる](http://mozpaca.hatenablog.com/entry/20170402/1491089976)
[Download Imageでリアルタイムにテクスチャを更新](https://historia.co.jp/archives/8949/)
[UnrealEngine : UAsyncTaskDownloadImage::DownloadImage](https://docs.unrealengine.com/en-US/API/Runtime/UMG/Blueprint/UAsyncTaskDownloadImage/DownloadImage/index.html)

## 関連ソース
Engine/Source/Runtime/UMG/Public/Blueprint/AsyncTaskDownloadImage.h


# DownloadImageとは
ゲーム外にある画像アセットを取得して表示させるためのノードです。

![downloadimage_node.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/8e991662-7e56-dcef-4595-41b9400b419a.jpeg)

URL指定(http://～)やファイル指定(file:///～)で画像ファイルを取得し、テクスチャ(`Texture2DDynamic型`)として返します。


# ダウンロードした画像を表示する
EditorUtilityWidgetを使ってダウンロードしてきた画像を表示してみます。

## 準備
デザイナウィンドウにて、イメージパレットを置きます、サイズ等を適当に調整します。

![widget_design.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/16ee2b50-a240-8d1e-0dbc-da64b5688405.jpeg)

イメージの詳細から [Brush] -> [バインド] -> [バインディングを作成]を選択し、関数を作ります。
![image_bind.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/bc04f0ea-0f27-2e81-fecb-75aa991a557e.jpeg)

`DownloadImage` は変数として用意し、型は `Texture2DDynamic`です。
`Slate Brush を作成` ノードにつないでリターンします。またこの関数は `純粋` チェックを外してノードにつなげられるようにします。
![func_image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/064d7b80-0e7e-54c8-e0d7-2bc419b21470.jpeg)

イベントグラフウィンドウを開き、コンストラクタにて `DownloadImage`を使い画像があるURLを指定します。ダウンロードしたテクスチャを `DownloadTexture`に設定し、先ほど作成した関数を呼び出します。
![widget_graph.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/2ae3103f-dd6b-841a-caaf-2c12d32087d5.jpeg)


## 結果
再生を実行し、作成したEditorUtilityWidgetを右クリックしてRunすると指定したURLから画像がダウンロードされ貼られます。

![Result.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/7dd24b7c-c42b-66ed-2bed-e57489f3e564.jpeg)

サンプルコードは画像サイズ決め打ちですが、ダウンロードして取得した画像サイズに合わせてあげれば綺麗に出力することもできるかと思います。


## 備考１：C++でのDownloadImageの呼び出し例
C++で呼び出す場合は以下の様になります。
以下サンプルコード。

```cpp:.cpp
#include "Blueprint/AsyncTaskDownloadImage.h"

auto _TaskDownloadImage = UAsyncTaskDownloadImage::DownloadImage(TEXT("https://4.bp.blogspot.com/-u2PJcGUSIN0/W-VEcnRvyII/AAAAAAABQFk/7miGx-JsspIuKCrD7UcZ5ymEOQmDn7yywCLcBGAs/s800/drink_petbottle_coffee.png"));
if(_TaskDownloadImage){
	// 成功時に呼び出す処理を追加
	_TaskDownloadImage->OnSuccess.AddDynamic(this, &ATestActor::SetDownloadTexture);

	// 失敗時に呼び出す処理を追加
	//_TaskDownloadImage->OnFail.AddDynamic(this, &ATestActor::FailDownloadFunc);
}

// 画像ダウンロード成功時に呼び出される処理
void ATestActor::SetDownloadTexture(UTexture2DDynamic* _Tex)
{
// ダウンロードしてきたテクスチャの処理
}

```

必要ならダウンロード失敗時の処理を `OnFail` に処理を追加することができます。
取得失敗時のデフォルト画像を仕込むとよいかと思います。


## 備考２：対応画像フォーマットについて
ソースを確認すると対応している画像フォーマットは `PNG` `JPEG` `BMP` のようです。

```cpp:AsyncTaskDownloadImage.cpp

void UAsyncTaskDownloadImage::HandleImageRequest(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded)
{
#if !UE_SERVER

	RemoveFromRoot();

	if ( bSucceeded && HttpResponse.IsValid() && HttpResponse->GetContentLength() > 0 )
	{
		IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
		TSharedPtr<IImageWrapper> ImageWrappers[3] =
		{
			ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG),
			ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG),
			ImageWrapperModule.CreateImageWrapper(EImageFormat::BMP),
		};

// ...省略...
```



# まとめ
URL指定ができるため外部アカウントのアイコン画像などを取得表示するのが主な使い方かと思います。PhotoShopでの修正テクスチャをリアルタイムで反映させるようなテクニカルな使い方もあるようですが。。