diff --git a/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp b/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp index 99f2ea0d..75dfb128 100644 --- a/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp +++ b/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp @@ -10,6 +10,13 @@ UGBFInteractableComponent::UGBFInteractableComponent() bIsEnabled = true; } +#if WITH_EDITOR +EDataValidationResult UGBFInteractableComponent::IsDataValid( FDataValidationContext & context ) const +{ + return InteractionOptionContainer.IsDataValid( context ); +} +#endif + void UGBFInteractableComponent::UpdateInteractions( UGBFInteractionOptionsData * options_data ) { if ( options_data == nullptr ) diff --git a/Source/GameBaseFramework/Private/Interaction/GBFInteractionOption.cpp b/Source/GameBaseFramework/Private/Interaction/GBFInteractionOption.cpp index b9219dda..50018e6f 100644 --- a/Source/GameBaseFramework/Private/Interaction/GBFInteractionOption.cpp +++ b/Source/GameBaseFramework/Private/Interaction/GBFInteractionOption.cpp @@ -1,5 +1,26 @@ #include "Interaction/GBFInteractionOption.h" +#include "DVEDataValidator.h" + +#if WITH_EDITOR +EDataValidationResult FGBFInteractionWidgetInfos::IsDataValid( FDataValidationContext & context ) const +{ + return FDVEDataValidator( context ) + .NotNull( VALIDATOR_GET_PROPERTY( InteractionWidgetClass ) ) + .Result(); +} +#endif + +#if WITH_EDITOR +EDataValidationResult FGBFInteractionOption::IsDataValid( FDataValidationContext & context ) const +{ + return FDVEDataValidator( context ) + .NotEmpty( VALIDATOR_GET_PROPERTY( Text ) ) + .NotNull( VALIDATOR_GET_PROPERTY( InteractionAbility ) ) + .Result(); +} +#endif + FGBFInteractionOptionContainer::FGBFInteractionOptionContainer() : InteractionsId( INDEX_NONE ) { @@ -26,4 +47,28 @@ void FGBFInteractionOptionContainer::ResetOptions() { Options.Reset(); IncrementId(); -} \ No newline at end of file +} + +#if WITH_EDITOR +EDataValidationResult FGBFInteractionOptionContainer::IsDataValid( FDataValidationContext & context ) const +{ + CommonWidgetInfos.IsDataValid( context ); + + for ( const auto & option : Options ) + { + option.IsDataValid( context ); + + if ( DefaultInputAction == nullptr && option.InputAction == nullptr ) + { + context.AddError( FText::FromString( TEXT( "No default input action is defined, and the option does not have any InputAction either" ) ) ); + } + else if ( DefaultInputAction == option.InputAction ) + { + context.AddWarning( FText::FromString( TEXT( "The same input action is defined for the default and for the option" ) ) ); + } + } + + return FDVEDataValidator( context ) + .Result(); +} +#endif \ No newline at end of file diff --git a/Source/GameBaseFramework/Private/Interaction/GBFInteractionOptionsData.cpp b/Source/GameBaseFramework/Private/Interaction/GBFInteractionOptionsData.cpp index caecb98d..caa721e0 100644 --- a/Source/GameBaseFramework/Private/Interaction/GBFInteractionOptionsData.cpp +++ b/Source/GameBaseFramework/Private/Interaction/GBFInteractionOptionsData.cpp @@ -1,7 +1,27 @@ #include "Interaction/GBFInteractionOptionsData.h" +#include "DVEDataValidator.h" + UGBFInteractionOptionsData::UGBFInteractionOptionsData() : bOverrideContainer( false ), bRemoveAllOptions( false ) { -} \ No newline at end of file +} + +#if WITH_EDITOR +EDataValidationResult UGBFInteractionOptionsData::IsDataValid( FDataValidationContext & context ) const +{ + if ( bOverrideContainer ) + { + OptionContainer.IsDataValid( context ); + } + + for ( const auto & option : Options ) + { + option.IsDataValid( context ); + } + + return FDVEDataValidator( context ) + .Result(); +} +#endif \ No newline at end of file diff --git a/Source/GameBaseFramework/Private/Pickupable/GBFPickupable.cpp b/Source/GameBaseFramework/Private/Pickupable/GBFPickupable.cpp index 05cd2c2c..ef1fa68c 100644 --- a/Source/GameBaseFramework/Private/Pickupable/GBFPickupable.cpp +++ b/Source/GameBaseFramework/Private/Pickupable/GBFPickupable.cpp @@ -49,6 +49,7 @@ EDataValidationResult AGBFPickupable::IsDataValid( FDataValidationContext & cont { return FDVEDataValidator( context ) .NotNull( VALIDATOR_GET_PROPERTY( EquipmentDefinition ) ) + .CombineWith( InteractableComponent ) .Result(); } diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h index 6d66fbc7..92e1e6b3 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h @@ -26,6 +26,10 @@ class GAMEBASEFRAMEWORK_API UGBFInteractableComponent : public UActorComponent FGBFOnInteractableInteractionRadiusStateChangedDelegate & OnInteractableLeftRadius(); FGBFOnInteractionsUpdatedDelegate & OnInteractionsUpdated(); +#if WITH_EDITOR + EDataValidationResult IsDataValid( FDataValidationContext & context ) const override; +#endif + const FGBFInteractionOptionContainer & GetInteractableOptions() const; bool IsEnabled() const; void SetEnabled( bool enabled ); diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h index b4f2e085..89bae3ad 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h @@ -19,6 +19,10 @@ struct FGBFInteractionWidgetInfos { GENERATED_BODY() +#if WITH_EDITOR + EDataValidationResult IsDataValid( FDataValidationContext & context ) const; +#endif + /** The widget to show for this kind of interaction. */ UPROPERTY( EditAnywhere, BlueprintReadWrite ) TSoftClassPtr< UUserWidget > InteractionWidgetClass; @@ -76,6 +80,10 @@ struct FGBFInteractionOption FGBFInteractionOption() = default; +#if WITH_EDITOR + EDataValidationResult IsDataValid( FDataValidationContext & context ) const; +#endif + /** Simple text the interaction might return */ UPROPERTY( EditAnywhere, BlueprintReadOnly ) FText Text = FText::GetEmpty(); @@ -132,6 +140,10 @@ struct FGBFInteractionOptionContainer const TArray< FGBFInteractionOption > & GetOptions() const; int GetInteractionsId() const; +#if WITH_EDITOR + EDataValidationResult IsDataValid( FDataValidationContext & context ) const; +#endif + UPROPERTY( EditAnywhere, BlueprintReadOnly ) TSoftObjectPtr< UInputMappingContext > InputMappingContext; diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOptionsData.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOptionsData.h index cc93ecde..980ee55d 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOptionsData.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOptionsData.h @@ -15,6 +15,10 @@ class GAMEBASEFRAMEWORK_API UGBFInteractionOptionsData final : public UDataAsset public: UGBFInteractionOptionsData(); +#if WITH_EDITOR + EDataValidationResult IsDataValid( FDataValidationContext & context ) const override; +#endif + UPROPERTY( EditAnywhere, meta = ( InlineEditConditionToggle ) ) uint8 bOverrideContainer : 1;