UE4の勉強記録

UE4の勉強の記録です。個人用です。

8章16節 アセットのための新しいカスタムコンテンツメニューのエントリーを作成する

<前文>

f:id:kazuhironagai77:20180225113310p:plain

で勉強しています。

今回は、「8章16節 アセットのための新しいカスタムコンテンツメニューのエントリーを作成する」を勉強します。

***このブログは、このブログの読者が、教科書(Unreal Engine 4 Scripting with C++)を読んでいる前提で書かれています。この教科書を読まないで、このブログを読んでも理解不可能であると考えられます。ご了承ください。***

<本文>

<目的>

アセットのための新しいカスタムコンテンツメニューのエントリー(entry)を作成する。とありますが、エントリー(entry)って何ですかね。正直、良く分からないですね。教科書の先を読むと、

f:id:kazuhironagai77:20180415141047p:plain

こんな図が紹介されていました。この図から推測するに、カスタムアセットのインスタンスを右クリックした時に、表示されるメニューの項目を追加出来る事のようです。この項目をエントリーと呼ぶみたいですね。

<方法>

0.失敗した時の保険のために、前回のプロジェクトを別名保存しておきます。やり方は、前に説明した方法です。

f:id:kazuhironagai77:20180415141236p:plain

1. FAssetTypeAction_Baseを基に、新しいクラスを作ってください。そのヘッダーファイルにhをインクルードする必要があります。

1.1 前回と同じように新しいクラスを作ります。

f:id:kazuhironagai77:20180415141340p:plain

と思ったら、FAssetTypeActions_Base.クラスがありません。Visual studio から作るしかないようです。

Packet Publish社が提供するサンプルコードを見ると、Chapter8Editorフォルダー内にある、MyCustomAssetActions.hとMyCustomAssetActions.cppがここのサンプルコードのようです。このサンプルコードを参考に、Visual studio側 から作ります。

1.1.1 プロジェクトを右クリックしてAdd->New Item…を開き、名前にMyCustomAssetActions.hと書き、LocationにCookbookEditor\Publicを選びます。

f:id:kazuhironagai77:20180415141417p:plain

f:id:kazuhironagai77:20180415141433p:plain

1.1.2 cppファイルも同様にして作成します。Locationは、CookbookEditor\Privateにします。

1.2 作ったヘッダーファイルに、Packet Publish社が提供するサンプルコード内のMyCustomActions.hを参考にして、コードを足していきます。

f:id:kazuhironagai77:20180415141500p:plain

1.3 同様に、cppファイルにも、Packet Publish社が提供するサンプルコード内のMyCustomActions.cppを参考にして、コードを足していきます。

f:id:kazuhironagai77:20180415141538p:plain

Packet Publish社が提供するサンプルコードは、MyCustomAssetActions.hを最後にインクルードしていますが、最初にインクルードします。

ここで、一端ビルドしてみます。

f:id:kazuhironagai77:20180415141623p:plain

一応、ここまでは成功しているみたいです。念のため、実行もしてみましたが、問題なく動きました。

f:id:kazuhironagai77:20180415141645p:plain

2. そのクラス内の以下のバーチャル関数をオーバーライドします。

2.1  Packet Publish社が提供するサンプルコードも参考にしつつ、以下のようにコードを書きました。

f:id:kazuhironagai77:20180415141734p:plain

f:id:kazuhironagai77:20180415141757p:plain

3. 以下の関数を宣言します。

3.1 以下のように宣言しました。

f:id:kazuhironagai77:20180415141831p:plain

f:id:kazuhironagai77:20180415141853p:plain

f:id:kazuhironagai77:20180415141917p:plain

f:id:kazuhironagai77:20180415141937p:plain

4.Cppファイルに宣言した関数を実装します。

4.1以下のようになりました。

f:id:kazuhironagai77:20180415142004p:plain

f:id:kazuhironagai77:20180415142022p:plain

f:id:kazuhironagai77:20180415142040p:plain

5. エディターモジュール内のStartupMode()関数に、以下のコードを足します。

5.1  Packet Publish社が提供するサンプルコードも参考にしつつ、UE4CookbookEditorModule.cppのStartupModule()関数に、以下のようにコードを書きました。

f:id:kazuhironagai77:20180415142148p:plain

f:id:kazuhironagai77:20180415142205p:plain

CreatedAssetTypeActionsがエラーになっています。Packet Publish社が提供するサンプルコード内のUE4CookbookEditorModule.hファイル内に、

f:id:kazuhironagai77:20180415142229p:plain

CreatedAssetTypeActionsオブジェクトの宣言があるので、

5.2そのまま、CreatedAssetTypeActionsオブジェクトの宣言をコピーします。

f:id:kazuhironagai77:20180415142258p:plain

エラーが消えました。

f:id:kazuhironagai77:20180415142325p:plain

この部分は、教科書には、全く記載がないので、Packet Publish社が提供するサンプルコードなしでは、再現は無理だと思われます。

f:id:kazuhironagai77:20180415142350p:plain

6. ShutdownModule()関数に以下のコードを足します。

6.1  Packet Publish社が提供するサンプルコードのUE4CookbookEditorModule.cppファイルを参考にして以下のコードを作りました。

f:id:kazuhironagai77:20180415142440p:plain

<結果>

f:id:kazuhironagai77:20180415142856p:plain

7. プロジェクトをコンパイルしてください。そしてエディターを実行してください。

7.1 ビルトをしたらエラーになってしまいました。

f:id:kazuhironagai77:20180415142953p:plain

スラッシュの向きを直してくださいとあったので、上記のように変えました。その後、もう一度ビルドしたら、成功しました。

f:id:kazuhironagai77:20180415143027p:plain

7.2 実行しました。

f:id:kazuhironagai77:20180415143051p:plain

8.コンテンツブラウザーからカスタムアセットのインスタンスを作成してください。

f:id:kazuhironagai77:20180415143120p:plain

9.コンテンツメニューにあるカスタムコマンドを見るために、新しいアセットを右クリックしてください。

f:id:kazuhironagai77:20180415143156p:plain

見事に出来てました。

<考察>

とりあえず、今回もHow it works…を読んでいきます。今回から、教科書から抜き出したHow it works…とその訳は、考察部分と区別がしやすいように、枠で囲むようにします。

f:id:kazuhironagai77:20180415143306p:plain

まず、FAssetTypeActions_Baseクラスの話からです。ここは、何より、APIを見るべきでしょうか?

f:id:kazuhironagai77:20180415143356p:plain

全てのAssetTypeActionsの基底クラスです。いろいろなタイプに有用なヘルパー関数を提供します。このクラスから派生するかどうかは、選択出来ます。

とあります。両方とも、FAssetTypeActions_Baseクラスについて説明していますが、教科書と、APIは、微妙に違っているように思えます。教科書は、FAssetTypeActions_Baseクラスの機能は、アセットタイプ用のコンテンツメニューコマンドとなっていますが、APIは、シンプルにAssetTypeActionsとなっています。教科書のアセットタイプ用のコンテンツメニューコマンドが何であるかが、まず分からないので、ここはとりあえず飛ばして、次を見てみます。

f:id:kazuhironagai77:20180415143507p:plain

FAssetTypeActions_BaseクラスのAPIに、IAssetTypeActions.hの中のバーチャル関数についての解説があります。

f:id:kazuhironagai77:20180415143532p:plain

サンプルコード内、MyCustomAssetActions.hファイル内でオーバーライドしているバーチャル関数は、以下に示す通りです。

f:id:kazuhironagai77:20180415143629p:plain

この中で、FAssetTypeActions_BaseクラスのAPI 中に紹介されているIAssetTypeActions.hの中のバーチャル関数は、

f:id:kazuhironagai77:20180415143659p:plain

f:id:kazuhironagai77:20180415143711p:plain

の二つです。ちなみに、UE4のコード規約では、以下に示すように、Iはインターフェイスを表しています。Fは、T,U,A,S,Iで表せない場合に使用します。

f:id:kazuhironagai77:20180415143734p:plain

f:id:kazuhironagai77:20180415144018p:plain

ここで、カスタムコンテンツメニューエントリー(custom context menu entry)とバインドする関数も宣言するとあります。サンプルコードのMyCustomAssetActions.hには、以下の関数がまだありますが、多分、MyCustomAssetContext_Clicked関数のみがこれに当たると思います。

f:id:kazuhironagai77:20180415143819p:plain

f:id:kazuhironagai77:20180415143837p:plain

IAssetTypeActions.hの中のバーチャル関数の一つであるHasActions関数について説明しています。まず、HasAction関数がエンジンコードから呼ばれる関数であると言っています。更に、エンジンコードから呼ばれた後、アクションを保持しているかどうかをチェックするための関数とあります。と言う事は、True かFalseを返すはずです。APIを見ても、サンプルコードを見ても、返す変数は、boolとなっていました。では、どんなアクションを持っている場合なのでしょうか?ここでは、選択されたオブジェクトに対応するアクションとあります。この選択されたオブジェクトが良く分かりません。パラメーターに、UObjectをパスしていますが、これの事でしょうか?

f:id:kazuhironagai77:20180415144142p:plain

次は、GetAction関数の説明がされています。まずこの関数は、先程のHasAction関数がTrueを返した時のみ、働くとあります。次に、もしHasAction関数がTrueを返したら、MenuBuilderにある関数を呼ぶとあります。MenuBuilderは、FMenuBuilderクラスから作成されたオブジェクトで、この関数にパスされています。FMenuBuilderクラスのAPIを見てみると、remarkには、以下の説明があります。

f:id:kazuhironagai77:20180415144258p:plain

垂直なメニューのためのビルダー

このオブジェクトを呼ぶ理由は、メニューオプションを作成するためとありますので、見事にマッチしています。このクラスの関数を使って我々が新しく作った項目をメニューに表示させ、かつ我々が提供するアクションをこの項目が選択された場合に、起動するのでしょう。

f:id:kazuhironagai77:20180415144436p:plain

ここで、GetName関数について説明しています。驚いたことに、GetName関数は、IAssetTypeActionsクラスの関数でした。FAssetTypeActions_BaseのAPIには、IAssetTypeActionsクラスからオーバーライドした関数が紹介されていますが、GetName関数はありませんでした。IAssetTypeActionクラスそのもののAPIを見てみます。

f:id:kazuhironagai77:20180415144538p:plain

このタイプの名前を返す

GetName関数がありました。どうも、この関数で返す名前の指定をするようです。通常のGet関数と同じと考えると、このクラスに名前を指定する変数があり、その名前を返す関数と考えられます。

以下に、MyCustomAssetActions.hファイル中のGetName関数の宣言を示します。

f:id:kazuhironagai77:20180415145046p:plain

f:id:kazuhironagai77:20180415145142p:plain

f:id:kazuhironagai77:20180415145223p:plain

GetSupportedClass関数もIAssetTypeActionsクラスの関数でした。

f:id:kazuhironagai77:20180415145253p:plain

特定のオブジェクトが、このタイプに操作されるかどうかをチェックする。

APIのremarkは、間違っていると思います。少なくとも、この関数が返す値はUClassでBoolではありません。教科書の説明にある我々のアクションクラスがサポートするUClassのインスタンスを返すが正しいようにみえます。

f:id:kazuhironagai77:20180415145402p:plain

f:id:kazuhironagai77:20180415145417p:plain

GetTypeColor関数もIAssetTypeActionsクラスから調べて見ます。

f:id:kazuhironagai77:20180415145453p:plain

このタイプに関連する色を返します。

クラスはともかく、このタイプとか、アクションに色があるのかが良く分からないですが、兎に角、色を返す事だけは分かりました。

f:id:kazuhironagai77:20180415145556p:plain

最後に紹介されてるのが、GetGategories関数です。

f:id:kazuhironagai77:20180415145631p:plain

そのアセットタイプのカテゴリーを返します。

これも、IAssetTypeActionsクラスの関数でした。あらゆるアセットタイプは、何らかのカテゴリーに属しているので、そのアセットタイプのカテゴリーを調べる関数であると理解しました。9の訳は少し変ですね。直そうと思ったのですが、The category under which the actions show in the context menuが良く分からないのです。The actions show under the category in the context menuなのか、The action show in the context menu under the categoryなのがまず分かりません。アセットタイプにカテゴリーがある事は分かります。でも、アクションやコンテンツメニューにカテゴリーってあるんでしょうか? 段々、訳がおかしくなってきたのですが、原因は、このアクションが実際、何を示しているかが分からないからです。現状、改善しようがないですので、このまま行きます。

f:id:kazuhironagai77:20180415150229p:plain

ここから、4.から9.までで、説明された関数の実装部分についての説明に入ります。

10.の説明は、MyCustomAssetActions.cppのHasActions関数の実装についてです。以下に実際のコードを示しますが、Trueしか返しません。

f:id:kazuhironagai77:20180415150258p:plain

4.で「・・・アクションを保持しているかどうかをチェックするための関数とあります。・・・」とありましたが、少なくともこのサンプルコード内では、HasAction関数は、アクションを保持しているかどうかをチェックはせず、闇雲に、全ての条件に対してTrueを返しています。

本来は、

If(InObject.something.something)

{

     return ture;

}

else

{

     return false;

}

みたくなるのでしょうか?

恐らく、この教科書では、サンプルコードは必要最低限することで、学習者が理解しやすいようにしたのでしょう。その方針は、正しいと思いますが、このInObject.something.somethingの部分が、ここで、紹介されていれば、この節におけるアクションが、具体的に何を示すのか分かったので、少し残念です。

f:id:kazuhironagai77:20180415152011p:plain

GetActions関数の実装部分について説明しています。以下にGetAction関数のコードを示します。

f:id:kazuhironagai77:20180415152103p:plain

MenuBuilderオブジェクトは、そのメンバー関数であるAddMenuEntryを呼んでいます。この関数については、次の12以降で詳しく説明しているので、ここでは、踏み込みません。レファレンス云々はC++の基本なのでこれも踏み込みません。

f:id:kazuhironagai77:20180415152554p:plain

f:id:kazuhironagai77:20180415152714p:plain

12.13.で述べられている事の再確認をしましょう。現在、カスタムコンテンツメニューのエントリーは以下のように、表示されています。

f:id:kazuhironagai77:20180415152820p:plain

これを、AddMenuEntry関数の最初と二番目の関数を変えて、実際に表示が変わるか試してみたいと思います。以下に示すように変えてみました。

f:id:kazuhironagai77:20180415152920p:plain

その結果、以下に示すように、教科書の説明通りの変化を示しました。

f:id:kazuhironagai77:20180415153033p:plain

f:id:kazuhironagai77:20180415153114p:plain

AddMenuEntry関数の三番目の関数についてですが、アイコンのイメージを指定しています。コードを以下に示します。

f:id:kazuhironagai77:20180415153139p:plain

このアイコンについては、新しいツールボタンを作るで、さんざん勉強したので、ここでは、このままにしておきます。

f:id:kazuhironagai77:20180415153227p:plain

ここで、MyCustomAssetContext_Clicked関数をデリゲートとしてパスしています。

f:id:kazuhironagai77:20180415153320p:plain

このデリゲートとして、ある関数を、CreateRaw関数を使用して、バインドする方法も、新しいツールボタンを作るで勉強したので、ここでは、深く検証はしません。

―追加文ー

一言だけ、追加しておきたい事があったので、ここに書いておきます。新しいツールボタンを作るで、CreatRaw関数を使用した理由は、デリゲートする関数のあるクラスが生のC++クラスだからと説明されていました。今回は、どうなんでしょうか?MyCustomAssetContext_Clicked関数があるFMyCUstomAssetActionクラスは、FAssetTypeActions_Baseクラスを継承していますし、生のC++クラスとは、言えないのじゃないのでしょうか?

この疑問について、今日は時間がないので、確認できませんが、時間が許されるときに、検証してみます。検証結果は、ここに記載します。

―追加文終ー

f:id:kazuhironagai77:20180415154933p:plain

これは、知らなかったです。試してみましょう。

f:id:kazuhironagai77:20180415155008p:plain

Cookbook Windowが開かれました。MyCustomAssetContext_Clicked()のコードを以下に示します。

f:id:kazuhironagai77:20180415155034p:plain

これを見ると、ウィンドウが開かれるのが分かります。個々のコードは、「8章14節 新しい編集用ウィンドウの作成」で勉強した内容とほぼ同じですので、ここでは、省略します。

f:id:kazuhironagai77:20180415155101p:plain

以下にGetName関数のコードを示します。GetName関数が、アセットタイプの名前を返すように、実装されています。

f:id:kazuhironagai77:20180415155208p:plain

6.で、「このクラスに名前を指定する変数があり、その名前を返す関数と考えられます。」と述べましたが、サンプルコードでは、名前そのものも、ここで、決定していますね。これは、サンプルコードを出来るだけシンプルにするための便宜的なものと理解しておきます。

サムネイル云々については良く分かりませんが以下の事でしょうか?

f:id:kazuhironagai77:20180415155646p:plain

試しに、StringをMy Custom Assetから以下に示すように、My Custom Asset11111に変更してみます。

f:id:kazuhironagai77:20180415155709p:plain

その結果、

f:id:kazuhironagai77:20180415155735p:plain

となりました。ここでは、説明されていませんが、サムネイルは、ぜひ作りたいです。後で、やり方を研究してみましょう。

後、分からないのは、メニューセクションのタイトルだけです。

f:id:kazuhironagai77:20180415160049p:plain

これの事でしょか?

f:id:kazuhironagai77:20180415160135p:plain

以下にGetSupportedClass関数の実装を示します。

f:id:kazuhironagai77:20180415160234p:plain

我々がアクションに操作してほしいアセットタイプは、UMyCustomAsset::StaticClass()であると述べていますが、今一、実感がありません。

7.の宣言部分の説明と合わせて、読んでみても、このクラスの中で、もっとも意味不明な、get関数です。このオブジェクト変数が一体何なのかが分からないだけでなく、この関数から返されたオブジェクトを、何に、使用するのかも見当が付きません。

f:id:kazuhironagai77:20180415160411p:plain

以下にGetTypeColor関数の実装を示します。教科書に述べてあるように、エメラルド色を返しています。

f:id:kazuhironagai77:20180415160949p:plain

どんな色でも良いとあるので、色を変えてみましょう。白くしてみました。

f:id:kazuhironagai77:20180415161051p:plain

f:id:kazuhironagai77:20180415161109p:plain

サムネイルも白くなりました。エメラルド色の方がきれいですね。

8.でアクションやタイプに色があるのか?とこの関数の解説に対して沢山の疑問をかけていましたが、それらに対する回答は得られなかったですね。

GetName関数で述べたのと、同じように、ここでも、色そのものを、この関数内で決定していますが、実際は、このクラスに色を指定する変数を作り、その色をこの関数にパスすると思います。

f:id:kazuhironagai77:20180415162111p:plain

その通りですが、もう一回、「8章14節 新しい編集用ウィンドウの作成」で勉強した、ウィンドウの作り方をここで、復習するつもりは、ありません。軽く流していきます。

f:id:kazuhironagai77:20180415162900p:plain

はい、作っていますね。(下に実際のコードを示します。)

f:id:kazuhironagai77:20180415162936p:plain

f:id:kazuhironagai77:20180415162956p:plain

SWindowについては、さんざん勉強したので、ここでは、復習しません。

f:id:kazuhironagai77:20180415164117p:plain

f:id:kazuhironagai77:20180415164133p:plain

All the functions that are chained…ではなく、All the functions are chained と思うのですが。ここでは、SWindowの全ての関数が、チェーン化して使えると言っています。

f:id:kazuhironagai77:20180415164610p:plain

この事を言っています。

f:id:kazuhironagai77:20180415164657p:plain

上記に示した、チェーン化されたSWindowクラスの個々の関数についての説明です。

f:id:kazuhironagai77:20180415165011p:plain

f:id:kazuhironagai77:20180415165032p:plain

f:id:kazuhironagai77:20180415165045p:plain

f:id:kazuhironagai77:20180415165100p:plain

f:id:kazuhironagai77:20180415165114p:plain

26から30までは、「8章14節 新しい編集用ウィンドウの作成」で勉強した内容とほぼ一緒なので、今回はスキップします。

f:id:kazuhironagai77:20180415165150p:plain

But we need to actually tell the engine that …の文の訳がグドグドですが、ここから次のクラス、EditorModuleクラスに追加したコードについての解説が始まります。

f:id:kazuhironagai77:20180415165221p:plain

f:id:kazuhironagai77:20180415165235p:plain

我々が、前に作成したFUE4CookbookEditorModuleクラスのStartupModule関数とShutdownModule関数を用います。

f:id:kazuhironagai77:20180415165350p:plain

以下に実際のコードを示します。

f:id:kazuhironagai77:20180415165424p:plain

アセットツールモジュール(Asset Tools Module)クラスと、IAssetToolsクラスの関係が良く分かりませんが、こういうものと覚えます。兎に角、ロードは出来ました。

f:id:kazuhironagai77:20180415165559p:plain

実際のコード:

f:id:kazuhironagai77:20180415165622p:plain

前述の我々が作成したMyCusntomAssetActionクラスのインスタンスを指す新しいSharedポインターを、作成します。

f:id:kazuhironagai77:20180415165733p:plain

実際のコード:

f:id:kazuhironagai77:20180415165757p:plain

35.に36.をResigerAssetTypeActions関数を使ってパスします。

f:id:kazuhironagai77:20180415165822p:plain

実際のコード:

f:id:kazuhironagai77:20180415165903p:plain

37。の説明を読む限り、CreateAssetTypeActionsが、アクションインスタンスですが、アクションインスタンスの定義自体が不明です。ひょっとしたら、UE4の基底クラスにアクションというのがあって、そこから派生したクラスは、全てアクションクラスで、そのクラスのインスタンスは、アクションインスタンスなのかもしれません。

f:id:kazuhironagai77:20180415165929p:plain

CreateAssetTypeActionsは、IAssetTypeActionsクラスのインスタンスです。UE4のAPIによると、

f:id:kazuhironagai77:20180415165952p:plain

AssetTypeActionsは、アセットタイプのアクションとその他の情報を提供する。

とあります。兎に角、このIAssetTypeActionsクラスのインスタンスであるCreateAssetTypeActionsをAdd関数を使ってパスします。

この33.から37.までの流れは何故こうやるのかを考えるのではなく、これが正しいやり方なので、覚えるようにと考えるべきかもしれません。

f:id:kazuhironagai77:20180415170057p:plain

まず、配列を使って作られたオブジェクトは、CreateAssetTypeActionsです。38.は、CreateAssetTypeActionsの事を述べているのでしょうか?CreateAssetTypeActionsは、IAssetTypeActionsクラスのインスタンスであるので、その通りだと思います。ここで、分からないのは、an array of all the created asset action です。全ての作成されたアセットアクションの配列、と訳しましたが、まずその意味が不明です。アセットアクションですら、具体的に何を指しているのか不明なのですから。しかし、分かる事もあります。将来的に、他のクラスのために、カスタムアクションを追加したい場合、この方法で出来るという事です。

f:id:kazuhironagai77:20180415170226p:plain

ここから、ShutdownModule内の話になります。以下にShutdownModule内に追加したコードを示します。

f:id:kazuhironagai77:20180415170359p:plain

39.で、アセットツールモジュールのインスタンスをもう一度、検索しますとあります。以下に示すコードの事でしょう。

f:id:kazuhironagai77:20180415170650p:plain

f:id:kazuhironagai77:20180415170711p:plain

大分、ごちゃごちゃした訳ですが意味は通ります。以下に、ここで解説している部分のコードを示します。

f:id:kazuhironagai77:20180415170741p:plain

レンジベースのforループとは、for (auto Action : CreatedAssetTypeActions)の事です。40.では、設置されたアクションクラスとなっていますが、CreateAssetTypeActionsの配列にセットされたのは、インスタンスです。StartupModule関数で、レジスターしたので、ここでアンレジスターする必要があります。

f:id:kazuhironagai77:20180415170823p:plain

話は全然変わりますが、今まで、翻訳を、英語―>日本語とやっていました。これが、大変時間がかかるのと、訳した文が大変おかしい場合が多く、どうしてこうなるのか不思議でした。41.は、どう訳しても、変になるので、やり方を変えて、英語で理解―>日本語で説明としてみました。41.の訳は、学校の英語のクラスの英文和訳なら0点かもしれませんが、日本語がおかしくないですし、英文と日本文の意味する処は、大変近くなっていると感じます。いわゆる超訳というやつですね。

41.は、クラスがレジスターされた場合、エディターがそのレジスターされたクラスに、何をするのかについて説明しています。ShutdownModule内に追加したコードについての説明は、40.でお終いでした。41.から最後までは、レジスターに関する解説みたいですね。個々のレジスターの説明に関しては、私は特に知識がありませんので、ただ、はい分かりました。としか言えません。ただ、ここでも、レジスターされるのは、クラスとなっていて、インスタンスではありませんね。ここで、アセットといっているのは、

f:id:kazuhironagai77:20180415170954p:plain

これらの事です。

f:id:kazuhironagai77:20180415171019p:plain

42.の説明文に対する私の解釈はこうです。まず、エディターは、アセットが、右クリックされたら、そのアセットが、カスタムアセットクラスから作られたかどうかチェックします。その方法は、そのアセットのStaticClassと、GetSupportedClass関数が返す値と比較し、両者が一致するかです。もし一致した場合は、そのアセットはカスタムアセットクラスから作成されたアセットであると判断されます。もし一致した場合、エディターは、GetAction関数を呼び出し実行します。

以下に我々が作成したFMyCustomAssetActions クラス内のGetSupportedClass関数を示します。

f:id:kazuhironagai77:20180415171104p:plain

単に、StaticClassを返しているので、このクラスから作成されたアセットのstaticClassとこの関数が返す値は一致するのは確実です。

―追加文ー

7.で、GetSupportedClass関数の「APIのremarkは、間違っている。」と、断言しました。7.を読んだ時点では、完全には、分かっていなかったですが、

特定のオブジェクトが、このタイプに操作されるかどうかをチェックする。

APIがチェックすると断言している事に対して、UClass のオブジェクトを返しているのに、チェックすると言うのは、おかしいと述べました。この私の指摘は、正しいですし、APIが間違っているのは、確実ですが、このAPIが、完全に間違っていたわけでもない事も、ここで、分かりました。

このAPIは、GetSupportedClass関数について説明していたのでは、なくて、ResigerAssetTypeActions関数内で、GetSupportedClass関数が果たす役割について説明していたのです。

勿論、それは、GetSupportedClass関数のAPIとしては、間違いですし、私の主張が正しい事に代わりはないですが、この説明文にも、意味があったのです。

―追加文終ー

さらに、FMyCustomAssetActions クラス内のGetAction関数を下に示します。

f:id:kazuhironagai77:20180415171137p:plain

この関数の中身については、11.から16.に詳しく解説していますので、省略しますが、兎に角、この関数が実行されます。

f:id:kazuhironagai77:20180415180428p:plain

アセットを右クリックしましたが、表示されたメニューが、見事に、GetActions関数で指定した内容になっています。

f:id:kazuhironagai77:20180415180459p:plain

我々のサンプルの場合、CustomAssetActionボタンの名前は、CustomAssetAction1111なので、それをクリックすると、MyCustomAssetContext_Clicked関数が呼ばれ、MyCustomAssetContext_Clicked関数が指定したウィンドウが開きました。

<まとめ>

  • MyCustomAssetActionsクラスが、カスタムアセットの名前、サムネイルの形状、右クリックした時に現れる、メニューバーの内容、実際にクリックした時に発動する機能など、カスタムアセットに関する総てを司っています。このクラスは、FAssetTypeAction_Baseクラスを継承する事により、HasActions関数、 GetActions関数、 MyCustomAssetContext_Clicked関数、 GetName関数、GetSupportedClass関数、 GetTypeColor関数などのカスタムアセットの全てを決定する関数が使えるようになります。
  • ただし、そのクラスを実際にエディターから使用するためには、EdiorModuleクラスから、そのクラスを呼ぶ必要があります。今回は、IAssetToolsクラス、FModuleManagerクラス、FAssetToolsModuleクラス、RegisterAssetTypeActions関数、IAssetTypeActionsクラスなどを用い、MyCustomAssetActionsクラスを実際にエディターから呼ぶようにしました。

f:id:kazuhironagai77:20180415180605p:plain

  • 以下に示す、アセットのための新しいカスタムコンテンツメニューのエントリー(項目)の設定は、MyCustomAssetActionsクラスのGetActions関数によってコントロールされています。

    f:id:kazuhironagai77:20180415180643p:plain

<おまけ>

別名保存は念のためにやっているので、時間を取られる事自体が不本意なのですが、今回、何回やってもエラーになって保存出来ない事態に成ってしまいました。具体的にいうと、

f:id:kazuhironagai77:20180415180720p:plain

この表示が出た後に、はい(Y)を、押すと、

f:id:kazuhironagai77:20180415180740p:plain

上記の表示になってエラーになります。30分近く格闘して原因が判明したのですが、原因は、CustomAssetFactory.cppファイルのインクルードの順番が、以下の様に成っていて、ビルトをするとエラーになるからでした。

f:id:kazuhironagai77:20180415180806p:plain

CustomAssetFactory.hファイルは最初にインクルードしないといけないという大原則を忘れていました。

f:id:kazuhironagai77:20180415180830p:plain

以上のように直した処、正常の別名で保存出来ました。

なぜ、前回は、間違った順番で、ヘッダーファイルをインクルードしたにも関わらず、正常にビルド出来たのか不思議ですが、こんなつまらないミスで30分以上無駄にしてしまいました。