Changing editability is pretty easy: Override CanEditChange. Assuming that your enum flags is used as such, a bitmask of flags:
bool UMyGameCard::CanEditChange( const UProperty* InProperty ) const
{
bool bIsEditable = Super::CanEditChange( InProperty );
if( bIsEditable && InProperty != NULL )
{
const FName PropertyName = InProperty->GetFName();
// Randomizing variant without randomizing gender is okay, but
// randomizing gender without randomizing variant makes no sense
if( PropertyName == GET_MEMBER_NAME_CHECKED( UMyGameCard, CardFlags ) )
{
bIsEditable = ( CardFlags & ECardFlags::GivesCard ) != 0;
}
}
return bIsEditable;
}
If it’s just a bool flag, simply replace the bitmask check with a bool check.
Changing visibility is a bit trickier but still very straightforward once you get the hang of editor details customizations. Details customization, as the name says, lets you control how your properties are being displayed. It’s an incredibly powerful feature and there thankfully is plenty of examples in the form of the editor’s own source code. But basically, you need to create a class customization for your card class, then bind a delegate to your card name’s visibility.
First, you need to register the class customization:
void FMyGameEditorModule::StartupModule()
{
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>( "PropertyEditor" );
PropertyModule.RegisterCustomClassLayout( "MyGameCard", FOnGetDetailCustomizationInstance::CreateStatic( &FMyGameCardDetails::MakeInstance ) );
PropertyModule.NotifyCustomizationModuleChanged();
}
If you don’t already have an editor module, you’ll need to create one as the property editor module pulls editor dependencies you cannot have in a game module.
Then, the actual implementation:
TSharedRef<IDetailCustomization> FMyGameCardDetails::MakeInstance()
{
return MakeShareable( new FMyGameCardDetails );
}
void FMyGameCardDetails::CustomizeDetails( IDetailLayoutBuilder& DetailBuilder )
{
// This needs to be whatever category your card flag is using
IDetailCategoryBuilder& CardFlagsCategory = DetailBuilder.EditCategory( "CardFlags" );
// Store this property in a TSharedPtr<IPropertyHandle> member variable for access within the delegate
CardFlagsProperty = DetailBuilder.GetProperty( GET_MEMBER_NAME_CHECKED( UMyGameCard, CardFlags ) );
TSharedPtr<IPropertyHandle> GivenCardNameProperty = DetailBuilder.GetProperty( GET_MEMBER_NAME_CHECKED( UMyGameCard, GivenCardName ) );
CardFlagsCategory.AddProperty( GivenCardNameProperty )
.Visibility( TAttribute<EVisibility>::Create( TAttribute<EVisibility>::FGetter::CreateSP( this, &FMyGameCardDetails::GetGivenCardNameVisibility ) );
}
EVisibility FMyGameCardDetails::GetGivenCardNameVisibility() const
{
ECardFlags::Type CardFlagsValue;
if( CardFlagsProperty->GetValue( CardFlagsValue ) == FPropertyAccess::Success )
{
if( ( CardFlagsValue & ECardFlags::GivesCard ) != 0 )
{
return EVisibility::Visible;
}
}
return EVisibility::Collapsed;
}
An important thing to note when dealing with details customization: You want to manipulate your properties through the provided IPropertyHandles. The reason is that they allow you to handle multiple selection trivially. If you have multiple customized objects selected, IPropertyHandle::GetValue will return FPropertyAccess::Success if the value is the same and therefore can be displayed, or FPropertyAccess::MultipleValues if the values differ. In the above example, if you were to somehow select multiple cards and they did not all have the same flags, then the FPropertyAccess::Success conditional would fail and the card name property would thus disappear.
This should get you started if you want to go down the route of editor customization.