※この記事で使用しているUnrealのVersionは05.3.0 Preview1です。
まだPreview版なので、正式リリース時に記事にある内容と差が出る可能性があります。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト

皆さんはレベルエディタ上で作業をしているときに、「Outlinerウィンドウ増やしたい…」と思ったことはありませんでしょうか?
一応現在のUnrealでは、Outlinerウィンドウは最大4つまで増やすことができます。

UE5からWorldPartitionが入り、Level上に置かれるアクターの数も多くなりがちな今日この頃で、通常のOutlinerだけではなかなか作業がしづらい場面も多くなってくるかと思います。

実は5.2から、Blueprintだけで自分だけのオリジナルOutlinerを作ることができるようになってるんです!うれしいね!🐟
(ただ、5.2だといくつかうまく動作しないものがあるので、5.3以降での使用をお勧めします)

UE5からWorldPartitionが入り、Level上に置かれるアクターの数も多くなりがちな今日この頃で、通常のOutlinerだけではなかなか作業がしづらい場面も多くなってくるかと思います。

そんな中、登場したのがObjectMixerというEditor専用のWidgetです!

BPだけで独自のOutlinerを作る レベル【★★☆】

ひとまずは、独自Outliner用のEditorUtilityWidgetを作ってみましょう!

ContentBrowser左上のAddボタンから、EditorUtilitiesEditorUtilityWidgetを選択します。
(以降EditorUtilityWidgetはEUWと略す)

そうそう、UE5.3からEditorUtilityWidgetを作成するときに、RootとなるWidgetを最初に設定できるようになりました。

ひとまず、Panel系であれば何でもいいのでStackBoxを使ってみます
StackBoxVerticalBoxHorizontalBoxを任意で切り替えられるものだと思ってください)


※5.2まではCanvasPanelが暗黙的にデフォルトのRootだったので、5.2までと同じ構造のWidgetを作成したい場合はCanvasPanelを選択しましょう

EUWを作成しましたら、ダブルクリック等でWidgetEditorを開きます。

そして、PaletteウィンドウからObjecttMixer(Generic)を選びDesignerウィンドウにドラッグ&ドロップします。その後Sizeプロパティの部分をFillとします。
(CanvasPanelを使う方はいい感じにサイズを調整してください)

もうすでにOutlinerっぽい見た目していますね!

ただ、ObjectMixerウィジェットそのものにはカスタマイズを行える機能はなく、ただ単にOutlinerのような見た目でアクター等のオブジェクトを表示するためのものです。
これだけではカスタマイズできないため、もう一つBlueprintを作成します。

ContentBrowser左上のAddボタンから、EditorUtilitiesEditorUtilityBlueprintを選択します。
(以降EditorUtilityBlueprintはEUBPと略す)

すると、親クラスを選択する画面が出てくるかと思いますので、ObjectMixerBlueprintObjectFilterを選択してください。

このクラスは、先ほど作成したEUWのほうのObjectMixerに設定することができ、このクラスにいくつかの処理をBlueprintで書くことによって、カスタマイズされたOutlinerを作成できます!

EUBPを作成しましたら、ダブルクリック等でBlueprintEditorを開きましょう。

何の変哲もないただのBlueprintですが、オーバーライド可能な関数がいくつかあります。
すべての説明は後程しますので、ひとまずは最低限の実装をしてみます。

まず、GetObjectClassesToFilterという関数をオーバーライドします。

以下のようにBlueprintを組んでみます。

もう一つ、GetObjectClassesToPlaceという関数をオーバーライドします。

できましたら、一旦ObjectMixerBlueprintObjectFilterを閉じ、先ほど作成したEUW内のObjectMixerのDetailウィンドウ内のObjectMixerWidgetUserConfig->DefaultFilterClassに作成したObjectMixerBlueprintObjectFilterを設定します。

できましたらEUWを実行します。
EUWのウィンドウ内にあるRunUtilityWidgetボタンを押します。

先ほどGetObjectClassessToFilterDirectionalLightクラスを設定しましたが、これによってDirectionalLightのみを表示するOutlinerができました。

また、Widget左上の「+Add」からDirectionalLightを配置することもできます。

GetObjectClassessToPlaceDirectionalLightクラスを設定しましたが、これによって「+Add」からDirectionalLightを配置することができるようになりました。

また、ObjectMixerにはもう一つ大きな特徴があります。

それは、任意のプロパティをカラムとして表示することができ、Widget内で編集することができる、というものです。

試しに、GetObjectClassessToFilterActorを設定します。
その後EUWを実行してから、ItemListやLabelと書かれた部分を右クリックすると、ベースとなる表示可能な項目に加えてActorが持っている編集可能な単一のプロパティが表示されるかと思います。

任意のプロパティにチェックを入れてみましょう(↓はCanBeDamage

プロパティのカラムを表示すると、そのプロパティの値も一緒に表示することができます。
そして、このカラム上でプロパティを編集することができます。とても便利ですね!!

ここで、ObjectMixerウィジェットの各種UIの説明をします。

まとめると、ObjectMixerは

1.任意のクラスのみを表示できる
2.アクター追加ボタンに任意のアクタークラスを設定できる
3.プロパティのカラムを表示し、Widget内で編集することができる

という3つの大きな特徴があります。

これらの特徴を生かして、作業にあった独自Outlinerを作成してみてください!

ObjectMixerBlueprintObjectFilterのオーバーライド関数について

以下がObjectMixerBlueprintObjectFilterオーバーライド可能な関数とその説明になります。

※尚、プロパティのいくつかは「Set」と呼ばれる型を使用することになります。
使い方は以下をご覧ください。

また、プロパティ名を指定する項目がいくつかありますが、Editor上のUIで表示されている名前ではなくC++で定義されている名前を指定します。
尚、Editor上のプロパティを右クリック→CopyInternalNameを行うことでもC++で定義された名前を取得することができます。
(ただし、一部は特殊なプロパティの構造をしておりこの方法では取得できないプロパティもあります)

GetColumnsToExclude

ここに指定した名前のプロパティは、
ObjectMixer上のカラム表示の選択ができなくなります。

GetColumnsToShowByDefault

「RestoreDefaultColumns」を押した際に表示するプロパティのカラム

GetForceAddedColumns

GetObjectMixerPropertyInheritanceInclusionOptionsにて表示が抑制されているプロパティや、
UPROPERTYマクロがついているがEditor上で見える設定ではないプロパティのカラムを強制的に表示可能にする。
(例えばSceneComponent::RelativeLocationは通常だと表示できないが、ここに設定することでカラムとして表示できる)
GetObjectMixerPropertyInheritanceInclusionOptionsにて表示が抑制されているプロパティのほうは、GetObjectClassesToFilterで指定しているクラスかその親が指定したプロパティを持っている必要がある。

GetObjectClassesToFilter

表示するオブジェクトのクラスを設定する
基本的には、AActorUActorComponentを継承したクラスを指定する
(全表示したいならAActorUActorComponentを指定する)

GetObjectClassesToPlace

ObjectMixerWidget左上の「+Add」ボタンから配置できるアクターのクラスを設定する。
※独自のBP等のクラスは今のところ設定できず、UActorFactoryにてFactoryが定義されているActorクラスのみ配置可能。簡単に言うと、デフォルトでPlaceActorsウィンドウにあるクラスであれば表示可能。

GetObjectMixerPlacementClassInclusionOptions

配置するアクタークラスでGetObjectClassesToPlaceで指定したクラスを基準に、親クラスや子クラスを含むかどうかを設定することができます(Default=Noneで、指定クラスのみが表示される)
詳しくは少し↓の「EObjectMixerInheritanceInclusionOptionsの説明」をご覧ください。

GetObjectMixerPropertyInheritanceInclusionOptions

表示するプロパティのカラムで、GetObjectClassesToFilterで指定したクラスを基準に、親クラスや子クラスのプロパティを含むかどうかを設定することができます(Default=Noneで、指定クラスのみのプロパティが表示される)
詳しくは少し↓の「EObjectMixerInheritanceInclusionOptionsの説明」をご覧ください。

尚、GetObjectMixerPlacementClassInclusionOptionsGetObjectMixerPropertyInheritanceInclusionOptionsで指定するEObjectMixerInheritanceInclusionOptionsの説明は以下になります。

EObjectMixerInheritanceInclusionOptionsの説明

説明
None指定したクラスのみ
IncludeOnlyImmediateParent指定したクラスおよびその親クラス(直近の親のみ)
IncludeOnlyImmediateChildren指定したクラスおよびその子クラス(直近の子のみ)
IncludeOnlyImmediateParentAndChildren指定したクラスおよびその親と子クラス(直近の親と子のみ)
IncludeAllParents指定したクラスおよびその親クラス(Uclassとしてたどれる限りのすべての親)
IncludeAllChildren指定したクラスおよびその子クラス(すべての子)
IncludeAllParentsAndChildren指定したクラスおよびその親と子クラス(Uclassとしてたどれる限りのすべての親とすべての子)
IncludeAllParentsAndOnlyImmediateChildren 指定したクラスおよびその親と子クラス(Uclassとしてたどれる限りのすべての親と直近の子)
IncludeOnlyImmediateParentAndAllChildren 指定したクラスおよびその親と子クラス(直近の親とすべての子)

GetPropertiesThatRequireListRefresh

指定したプロパティが更新されたときに、ObjectMixerで表示しているObjectのリスト表示を更新をするようにします。
(Property更新時にConstructionScript等でComponent等が生成されたりする場合等に使用したりします)

GetShowTransientObjects

Transientなアクター(保存できないアクター)の表示をするか否かを制御できます(Default=False

ShouldIncludeUnsupportedProperties

Trueにすることで、通常は表示されないプロパティ(UPROPERTYでEdit設定されていないもの)や配列・構造体などの単一な値でないプロパティを表示することができます(Default=False
※ただし、表示ができてもウィンドウ内で変更できないプロパティもあります。

このあたりの表示できるものが何かを制御している部分が気になる方はSObjectMixerEditorList.cppのSObjectMixerEditorList::AddUniquePropertyColumnInfoをご覧ください。

現状確認できる不具合のような挙動について レベル【★★★☆】

ObjectMixerを明示的にリフレッシュしたい場合(Filter側の処理を変えた場合等)は、内部的にWidgetをRebuildすればいい→つまりRemoveFromParentしてから再度AddChild等でWidgetを構築してあげれば、ウィンドウ内の項目が再度作り直されます。
尚、どうやら5.2まではObjectMixerWidget内の設定→ObjectFilterClassApplyボタンでリフレッシュできていたのですが、5.3だと設定の保存はされるがリフレッシュがされないようです

それと、EditorUtilityWidget上にObjectMixerウィジェットを配置すると、ContentBrowserで右クリックメニューと変数などのプルダウンで該当のEUWが含まれるような条件で、メニューやプルダウンが表示されない現象が起きます。

これは、ObjectMixerウィジェットが表示される際に「検索ボックスをフォーカスする」というような処理が入っており(SObjectMixerEditorList::Constructにて固定値で定義SSceneOutliner::Tick内で判定)この処理が行われると開かれているメニューなどのWidgetが閉じられてしまいます。(FSlateApplication::RequestDestroyWindowでクローズ)
ContentBrowser内でウィジェットにフォーカスを充てると毎フレームWidgetのプレビューがされ、結果的に毎フレームメニューが閉じる処理が行われます。プルダウンの場合は表示時にプレビューがされます。
これを回避するには、WidgetEditor内のObjectMixerウィジェットの目玉の表示 (EditorVisibility)を閉じておきましょう。
こうすることでプレビュー時にObjectMixerウィジェットのプレビューは走らないので意図しないEditorのメニュー等のWidgetのクローズを避けることができます。

まあこのあたりは今後のアップデート何かしら改善が入るんじゃないかなぁと思います(まだ入ったばかりですし)

※追記:5.3.2では、右クリックメニューが表示されない問題は修正されているようでした。

ちょいたし-Place機能から独自のBPアクターを配置できるようにする レベル【★★★☆】

さて、Outlinerとしての機能に関してはかなり充実した拡張ができるので、とても使えるかなと思いますが、せっかくObjectMixerウィジェットの左上にあるAddボタンから追加できるアクターをフィルターできるのに、登録して表示できるアクターはActorFactoryというクラスを1クラスごとにC++で定義する必要があります。

独自のBPが追加出来たらいいのに…ということで、そういった機能を持つプラグインを簡単にですが作ってみました(サンプルプロジェクトに入っているので、良ければご覧ください)

・使い方

プラグインで独自に定義した、UActorFactoryBPClassというクラスをEditorUtilityBlueprintで継承します。

作成したBPを開き、ActorClassというプロパティに任意のBPアクタークラスを選択します。

その後プラグインフォルダの、
/CustomObjectMixerPlaceClass/DA_ActorClassListというDataAssetを開きます。

BPActorFactoriesという項目に先ほど作成したEUBPを設定します。

あとはObjectMixerFilterクラスの、GetObjectClassessToPlaceに指定したActorクラスを設定します。

最後にEditorを再起動することで使えるようになります。

具体的な実装を見たい場合はプロジェクトをダウンロードしてみてください。
※ノリで作ったものなので、Engineアップデートでの動作保証やつくり的な部分の甘さ(参照のさせ方とか)はまああると思います。あくまでサンプルですので、実用的なものはご自身で作成していただければと思います。

毎度粗末な感じですが以上となります。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です