[UE4]プロパティ指定子"EditCondition"でできること

変数宣言時に設定するプロパティ指定子、UPROPERTY(Hogehoge)。
種類豊富な指定子の中でもメタデータに指定する"EditCondition"というものについてできることとできないことを掘り下げる。

# 概要
EditConditionとは宣言したプロパティの入力を制限できるメタデータ指定子で、任意の条件で入力可能/入力不可能を切り替えたいときに非常に役立つ指定子だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548800/bffb7ecd-875b-c416-7cd4-f359348bfc5e.png)


# 基本的な使い方

```c++:MyFileName.h
UPROPERTY(EditAnywhere, meta = (EditCondition = "false"))
float Value = 0.0f;
```

メタデータ指定子内のEditConditionにboolステータス（true/false）, bool型変数名, 演算式を指定することで、このUPROPERTYがついた変数は任意条件で入力制御が可能になる。
関数の指定はできないのが難儀である。

```c++:できる例
// boolステータスの直接指定=============================================
UPROPERTY(EditAnywhere, meta = (EditCondition = "false"))
float Value1 = 0.0f;

// bool型変数の指定=====================================================
bool IsInputValue = true;

UPROPERTY(EditAnywhere, meta = (EditCondition = "IsInputValue"))
float Value2 = 0.0f;

UPROPERTY(EditAnywhere, meta = (EditCondition = "!IsInputValue"))
float Value3 = 0.0f;

// float型変数を用いた式================================================
UPROPERTY(EditAnywhere)
float TargetValue = 0.f;

UPROPERTY(EditAnywhere, meta = (EditCondition = "TargetValue > 0.5"))
float Value4 = 0.0f;
```

```c++:できない例
bool IsControlInput() { return false; };

UPROPERTY(EditAnywhere, meta = (EditCondition = "IsControlInput()"))
float Value = 0.0f;
```


# 関数による制御をしたい！

関数が指定できないのがつらかったため、関数内でbool値を変えたらどうかと思い、以下のようなコードを作ってみた。

```c++:MyFileName.h
bool IsMyParameterControl = true;

UPROPERTY(EditAnywhere, meta = (EditCondition = "IsMyParameterControl"))
float Value = 0.0f;

void SetControlParameter(const bool bIn) { IsMyParameterControl = bIn; };
```

任意タイミングでSetControlParameter()を呼び出し、EditConditionに設定したbool値を書き換える。
が、しかしこれだとIsMyParameterControlがBlueprintからアクセスできないため制御ができなかった。

----

なのでbool変数にUPROPERTYを付け、アクセス修飾子をいろいろ変更して挙動を確認してみた。

```c++:MyFileName.h

	bool IsControl_UPropertyNothing = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_UPropertyNothing"))
	float Param_UpropertyNothing = 0.0f;

	UPROPERTY(EditAnywhere)
	bool IsControl_EditAnywhere = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_EditAnywhere"))
	float Param_EditAnywhere = 0.0f;

	UPROPERTY(EditDefaultsOnly)
	bool IsControl_EditDefaultOnly = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_EditDefaultOnly"))
	float Param_EditDefaultsOnly = 0.0f;

	UPROPERTY(EditInstanceOnly)
	bool IsControl_EditInstanceOnly = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_EditInstanceOnly"))
	float Param_EditInstanceOnly = 0.0f;

	UPROPERTY(VisibleAnywhere)
	bool IsControl_VisibleAnywhere = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_VisibleAnywhere"))
	float Param_VisibleAnywhere = 0.0f;

	UPROPERTY(VisibleDefaultsOnly)
	bool IsControl_VisibleDefaultOnly = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_VisibleDefaultOnly"))
	float Param_VisibleDefaultsOnly = 0.0f;

	UPROPERTY(VisibleInstanceOnly)
	bool IsControl_VisibleInstanceOnly = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_VisibleInstanceOnly"))
	float Param_VisibleInstanceOnly = 0.0f;

	UPROPERTY()
	bool IsControl_UpropertyOnly = true;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (EditCondition = "IsControl_UpropertyOnly"))
	float Param_UpropertyOnly = 0.0f;

	void SetChangeControlFlag(const bool bPossible) { IsControl_UPropertyNothing = IsControl_EditAnywhere = IsControl_EditDefaultOnly = IsControl_EditInstanceOnly = IsControl_VisibleAnywhere = IsControl_VisibleDefaultOnly = IsControl_VisibleInstanceOnly = IsControl_UpropertyOnly = bPossible; };

```

これのIsControl_Hogehoge系bool型変数はそれぞれ異なるアクセス修飾子持ち、レベルエディタでの制御・Overlapなどのイベント発火（SetControlParameter()の呼び出し）によるプログラム制御が可能か調べる。

まず、レベルエディタでの見た目はこうなった。各パラメータをブロックで分けている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548800/d79fe7d3-bfb2-9458-163e-8c9873b88ce4.png)

赤い枠で囲ったプロパティはIsControl_Hogehoge系のチェックボックスが表示されているため、レベルエディタでの制御が可能であった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548800/aba9fa63-9781-daa4-efc3-cf9fc9b5259a.png)

緑と青の枠で囲ったプロパティはSetControlParameter()呼び出しによって入力可能/不可状態が切り替わっているものであり、プログラム制御が可能だったものだ。
ただ注意しなければならないのが、青枠のプロパティはプログラムで制御していてもレベルエディタ側にチェックボックスがあるため上書きが可能な点である。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548800/f1c2b45e-1b34-87f8-a3e5-a6228388f3ac.png)

# まとめ
結果を表にまとめる。

| アクセス修飾子 | レベルエディタ制御 | プログラム制御 | BPでの編集 |
|:-:|:-:|:-:|:-:|
| UPROPERTYなし | x | x | x |
| EditAnywhere | o | o | o |
| EditDefaultsOnly | x | o | o |
| EditInstanceOnly | o | o | x |
| VisibleAnywhere | x (表示あり) | o | x |
| VisibleDefaultsOnly | x | o | x |
| VisibleInstanceOnly | x (表示あり) | o | x |
| 空のUPROPERTY | o | o | x |


bool型変数に付けたアクセス修飾子はそれぞれレベルエディタからの閲覧、編集はもちろんのこと、Blueprintからの閲覧、編集のアクセスがあるかどうかも示している。
そのためプログラム制御を行いたい場合はそれがBlueprintからなのか、ソースコードからなのかを決めることで適切なアクセス修飾子を選択することが可能だ。

レベルエディタのみで制御したい場合は"EditDefaultsOnly"か"EditInstanceOnly"、そして"空のUPROPERTY"に設定して置く必要があるが、私は断然"空のUPROPERTY"をオススメする。
余計なプロパティ名が表示されず、レベルエディタで実際に作業するアーティストやレベルデザイナーにとって直感的にわかりやすい見た目になるからである。（見た目はMaterialInstanceのプロパティに近い）

また、プログラムのみで制御したい場合は、Blueprintでの制御ならEditDefaultsOnly、ソースコードでの制御ならVisibleDefaultsOnlyに設定するのが良さそうだ。