ぼっちプログラマのメモ

UE4とかUE5とかについて書いたり書かなかったり。

マテリアルインスタンスのMaterial Property OverrideのOverrideフラグをロックするエディタ拡張について

前回
pafuhana1213.hatenablog.com

前々回
pafuhana1213.hatenablog.com

はじめに

突然ですが、先日開かれたUE4マテリアル管理勉強会(#UE4DD)のスライドに
こんなページがありました。
f:id:pafuhana1213:20170129153703p:plain

www.slideshare.net

ということで、今回はMaterial Property Overrideをロックするフラグを追加します。
具体的な実装手順については続きにて。エンジンのバージョンはUE4.15です。
f:id:pafuhana1213:20170129154027g:plain
※ エンジン拡張した場合、その後の動作は保証できない上に
  バージョンアップ時のマージ対応が必要になります。ご注意下さい!

エディタ拡張

MaterialInstanceBasePropertyOverrides.h

USTRUCT()
struct ENGINE_API FMaterialInstanceBasePropertyOverrides
・・・
	/** Whether the material should support a dithered LOD transition when used with the foliage system. */
	UPROPERTY(EditAnywhere, Category = Material, meta = (editcondition = "bOverride_DitheredLODTransition"))
	uint32 DitheredLODTransition : 1;

	// ここから
	// アセット側のロックフラグ管理用変数
	UPROPERTY(EditAnywhere, Category = Material)
	uint32 Lock : 1;
	// ここまで!

MaterialShared.cpp

FMaterialInstanceBasePropertyOverrides::FMaterialInstanceBasePropertyOverrides()
・・・
	,DitheredLODTransition(0)
	,Lock(0) // 追加(ロック状態を有効にしたい場合は、1を指定)
{

}

bool FMaterialInstanceBasePropertyOverrides::operator==(const FMaterialInstanceBasePropertyOverrides& Other)const
{
・・・
                        ShadingModel == Other.ShadingModel &&
                        // ここから
			DitheredLODTransition == Other.DitheredLODTransition &&
			Lock == Lock;
                        // ここまで
・・・
}

MaterialEditorInstanceDetailCustomization.cpp

void FMaterialInstanceParameterDetails::CreateBasePropertyOverrideWidgets(IDetailLayoutBuilder& DetailLayout)
・・・
	TSharedPtr<IPropertyHandle> DitheredLODTransitionProperty = BasePropertyOverridePropery->GetChildHandle("DitheredLODTransition");
        // ここから
        // ロックフラグのプロパティ取得
	TSharedPtr<IPropertyHandle> LockProperty = BasePropertyOverridePropery->GetChildHandle("Lock");
        // ここまで!
・・・
	IDetailPropertyRow& DitheredLODTransitionPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(DitheredLODTransitionProperty.ToSharedRef());
	DitheredLODTransitionPropertyRow
		.DisplayName(DitheredLODTransitionProperty->GetPropertyDisplayName())
		.ToolTip(DitheredLODTransitionProperty->GetToolTipText())
		.EditCondition(IsOverrideDitheredLODTransitionEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideDitheredLODTransitionChanged));

        // ここから
        // ロックフラグのチェックボックスを追加
        // EditConditionを使用しないことで、左側のOverrideフラグを非表示に
        IDetailPropertyRow& LockPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(LockProperty.ToSharedRef());
	LockPropertyRow
		.DisplayName(LockProperty->GetPropertyDisplayName())
		.ToolTip(LockProperty->GetToolTipText());
        // ここまで!
void FMaterialInstanceParameterDetails::OnOverrideOpacityClipMaskValueChanged(bool NewValue)
{
	// ここから
        // ロックフラグが有効な時は、チェックボックスをクリックしても無反応に
	if(MaterialEditorInstance->BasePropertyOverrides.Lock == 1)
	{
        	return;
	}
	// ここまで!
・・・
}

以下の関数にも同じコードを追加

  • OnOverrideBlendModeChanged
  • OnOverrideShadingModelChanged
  • OnOverrideTwoSidedChanged
  • OnOverrideDitheredLODTransitionChanged

おまけ(エディタ拡張する際の流れ)

コード載せるだけだと微妙なので、ざっくりと僕がエディタ拡張する際の流れについて

  1. エディタ拡張したい部分付近にある文字列を、エンジンコードで全検索
  2. "Engine\Source\Editor"以下のファイルがエディタ部分の実装なので、検索結果からそのフォルダ中にあるファイルを探す
  3. 既存のコードの文字列・フラグを変えたり、コード丸ごとコピペすることでエディタがどう変化するか確認
  4. 確認した内容を元にエディタ拡張
  5. アセット側のコードと連携しないと編集結果が保存されないので、既存コードを参考にアセット側も拡張。エディタ側のコードで何か情報を引っ張ってきている部分が怪しいです。

…うーん、上手く説明できてませんがこんな感じでコード追ってます。

さいごに

複数回に渡って、マテリアルインスタンスのエディタ拡張について紹介しました。
小規模な拡張の場合は案外サクッと実現できることが伝わると嬉しいです!
ただ何度も書いてますが、エンジン改造はご計画的に!

プラグインに切り離せるエディタ拡張を勉強しよっと…)