ぼっちプログラマのメモ

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

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

はじめに

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

何故StaticSwitchParameterの使用に慎重にならないといけないかについては
↓のスライドを見て頂くとして…

www.slideshare.net

この話が出た時、
「Static Switch Parameterをロックできるフラグがあるといいね」
というツイートを幾つか見ました。

ということで、今回もエディタ拡張してみました!
f:id:pafuhana1213:20170125230015g:plain

Lockフラグを有効にしたらStaticSwitchParameterを全グレーアウトしたかったのですが、
予想以上に難しそうなので、「StaticSwitchParameterのOverrideフラグをロック」する形にしました。

具体的な実装手順については続きにて。エンジンのバージョンはUE4.15です。

※ エンジン拡張した場合、その後の動作は保証できない上に
  バージョンアップ時のマージ対応が必要になります。ご注意下さい!

エンジン拡張

前回のエディタ拡張記事に比べるとコードの追加量は少し多いです。

MaterialEditorInstanceDetailCustomization.cpp

void FMaterialInstanceParameterDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout)
{
・・・
	CreateGroupsWidget(ParameterGroupsProperty, GroupsCategory);

	// ここから
        // MaterialEditorInstanceConstatntのbLockStaticSwichを取得
	TSharedPtr<IPropertyHandle> LockProperty = DetailLayout.GetProperty("bLockStaticSwich");
        // マテリアルインスタンスのパラメータグループに"Option"グループを追加
	IDetailGroup& DetailGroup = GroupsCategory.AddGroup(TEXT("Option"), FText::FromName(TEXT("Option")), false, true);
        // "Option"グループにStaticSwitchParameterのロック用プロパティを追加        
	IDetailPropertyRow& LockPropertyRow = DetailGroup.AddPropertyRow(LockProperty.ToSharedRef());
	LockPropertyRow
		.DisplayName(LockProperty->GetPropertyDisplayName())
		.ToolTip(LockProperty->GetToolTipText());
        // ここまで!
・・・
void FMaterialInstanceParameterDetails::OnOverrideParameter(bool NewValue, class UDEditorParameterValue* Parameter)
{
	// ここから
        // ロックフラグがONかつ対象のパタメータがStaticSwitchの場合はチェックボックスを無反応に
	if (Cast<UDEditorStaticSwitchParameterValue>(Parameter))
	{
		if (MaterialEditorInstance->bLockStaticSwich == 1)
		{
			return;
		}
	}
	// ここまで!
・・・

MaterialEditorInstanceConstant.h

UCLASS(hidecategories=Object, collapsecategories)
class UNREALED_API UMaterialEditorInstanceConstant : public UObject
{
・・・
	UPROPERTY(EditAnywhere, editfixedsize, Category=MaterialEditorInstanceConstant)
	TArray<struct FEditorParameterGroup> ParameterGroups;

        // ここから
	// エディタ側のロックフラグ管理用変数
	UPROPERTY(EditAnywhere, Category = MaterialEditorInstanceConstant)
	uint32 bLockStaticSwich : 1;
        // ここまで!
・・・

PreviewMaterial.cpp

void UMaterialEditorInstanceConstant::CopyToSourceInstance()
・・・
		SourceInstance->bOverrideSubsurfaceProfile = bOverrideSubsurfaceProfile;
		SourceInstance->SubsurfaceProfile = SubsurfaceProfile;

                // ここから
		// エディタの編集結果をアセット側のフラグに反映
		SourceInstance->bLockStaticSwich = bLockStaticSwich;
                // ここまで!
・・・
void UMaterialEditorInstanceConstant::SetSourceInstance(UMaterialInstanceConstant* MaterialInterface)
・・・
	bOverrideSubsurfaceProfile = SourceInstance->bOverrideSubsurfaceProfile;
	SubsurfaceProfile = SourceInstance->SubsurfaceProfile;

        // ここから
	// エディタ側のフラグにアセットに保存されたデータをコピー
	bLockStaticSwich = SourceInstance->bLockStaticSwich;
        // ここまで
・・・
MaterialInstance.h
UCLASS(abstract, BlueprintType,MinimalAPI)
class UMaterialInstance : public UMaterialInterface
・・・
	UPROPERTY()
	bool bOverrideBaseProperties_DEPRECATED;

	// ここから
	// アセット側のロックフラグ管理用変数
	UPROPERTY()
	uint32 bLockStaticSwich : 1;
	// ここまで
・・・

これらのコードを反映すれば、ロックフラグを追加できます!(…な、長い)

それぞれのコードが何を意味しているのかはコメントに記載してます。
それらを参考に周辺のコードを見ると、
どんな処理・流れになっているかが理解しやすいかと思います。
(…いや、具体的な説明をサボった訳ではなく…ゴニョゴニョ…)

最後に

はじめのスライドにあるように、不用意にStaticSwitchParameterを触ると、
後々に大変な事態に陥る可能性があります。
人間は基本的にミスをしてしまう生き物なので、
こういった制限を掛けることでトラブル回避していきたいですね!

次回は、Material Property Overrideのロックフラグ追加について
(地味な記事が続くなぁ…)