Thomas Sampson

Unreal Engine UPROPERTY Edit Conditions


Intro #

UPROPERTIES in Unreal Engine have a bunch of useful Meta-data Specifiers which can be applied to add additional validation and functionality. This blog post explains how to use the EditCondition (and EditConditionHides) specifiers to selectively show, disable or hide properties in the editor, based upon the value of another UPROPERTY. Shout-out to Jack Magnay and Connel Reed for their contributions to the "Advanced Usage" snippet.
 
GitHub Gist: https://git.io/JJ3QC
 

Basic Usage #

This example below disables the MyNumber property when MyFlag is false.

UPROPERTY(EditAnywhere, Category="Demo")
bool MyFlag = true;
UPROPERTY(EditAnywhere, Category="Demo", meta=(EditCondition="MyFlag"))
int MyNumber = 0;

editcondition
 

Basic Usage (Inverted) #

This example below is similar to the first, but disables the MyNumber property when MyFlag is true.

UPROPERTY(EditAnywhere, Category="Demo")
bool MyFlag = true;
UPROPERTY(EditAnywhere, Category="Demo", meta=(EditCondition="!MyFlag"))
int MyNumber = 0;

editcondition
 

Basic Usage (Hiding) #

This example below is similar to the first, but fully hides the MyNumber property when MyFlag is true by adding the EditConditionHides specifier.

UPROPERTY(EditAnywhere, Category="Demo")
bool MyFlag = true;
UPROPERTY(EditAnywhere, Category="Demo", meta=(EditCondition="MyFlag", EditConditionHides))
int MyNumber = 0;

editcondition
 

Advanced Usage (Enum) #

As of UE4 4.23 (see release notes) "The EditCondition meta tag is no longer limited to a single boolean property. It is now evaluated using a full-fledged expression parser, meaning you can include a full C++ expression." - This means we can do things like disabling a properties based on the value of an enum UPROPERTY, as shown below.
 
NOTE: If you're checking a pointer value as part of your condition, make sure to use 'MyPointer == nullptr' rather than '!MyPointer', as the latter is not currently supported.

//------------------------------------------------------------------------------------------------------------------------------

UENUM(BlueprintType)
enum class EMovementConfig : uint8
{
ConstantSpeed,
Increment
};

//------------------------------------------------------------------------------------------------------------------------------

UPROPERTY(EditAnywhere, Category="Demo")
EMovementConfig MovementConfig = EMovementConfig::ConstantSpeed;
UPROPERTY(EditAnywhere, Category="Demo", meta=(EditCondition="MovementConfig == EMovementConfig::ConstantSpeed"))
float Speed = 10.0f;
UPROPERTY(EditAnywhere, Category = "Demo", meta = (EditCondition="MovementConfig == EMovementConfig::Increment"))
float Increment = 1.0f;

//------------------------------------------------------------------------------------------------------------------------------

editcondition
 

Advanced++ Usage (C++ Custom Override) #

If none of the simpler methods described above quite cut it, you may want to consider overriding UObject::CanEditChange. This function allows you to provide completely custom logic, offering much finer-grained control over when each property in your class is allowed to be edited.

 
NOTE: This function is only invoked when modifying properties directly from within the editor UI, and does not prevent external code or systems from editing your properties at runtime.

//------------------------------------------------------------------------------------------------------------------------------

#if WITH_EDITOR
virtual bool UMyClass::CanEditChange(const FProperty* InProperty) const override
{
// Respect parent class decision to prevent this edit
// NOTE: This is generally recommended, but could be conditionally ommited when
// attempting to allow a specific edit, usually prohibited by the parent class.
if(!Super::CanEditChange(InProperty))
{
return false;
}

// Specific logic associated with "MyProperty"
const FName PropertyName = InProperty->GetFName();
if(PropertyName == GET_MEMBER_NAME_CHECKED(UMyClass, MyProperty))
{
return CustomLogicHere();
}

// Default behaviour
return true;
}
#endif

//------------------------------------------------------------------------------------------------------------------------------