From b43bca02f137f49c47f532ff3d14e3d712329f15 Mon Sep 17 00:00:00 2001 From: Thibaut Spreux Date: Wed, 29 Jan 2025 08:39:11 +0100 Subject: [PATCH 1/6] expose tag requirements --- .../Public/Interaction/GBFInteractionOption.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h index f6fecc2b..d83c0931 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h @@ -80,10 +80,10 @@ struct FGBFInteractionOption UPROPERTY( EditAnywhere, Instanced ) TObjectPtr< UGBFInteractionEventCustomization > EventCustomization; - UPROPERTY( EditAnywhere ) + UPROPERTY( EditAnywhere, BlueprintReadOnly ) FGameplayTagRequirements InteractableTargetTagRequirements; - UPROPERTY( EditAnywhere ) + UPROPERTY( EditAnywhere, BlueprintReadOnly ) FGameplayTagRequirements InstigatorTagRequirements; UPROPERTY( EditAnywhere, BlueprintReadOnly ) From fb35711061c41c85e66e7623af69684f2b8061e6 Mon Sep 17 00:00:00 2001 From: Thibaut Spreux Date: Wed, 29 Jan 2025 17:14:30 +0100 Subject: [PATCH 2/6] add target component and socket management --- .../Interaction/Abilities/GBFGameplayAbility_Interact.cpp | 8 +++++++- .../Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp | 2 +- .../Public/Interaction/GBFInteractionOption.h | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp b/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp index ad1ec9f7..a80cbbc2 100644 --- a/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp +++ b/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp @@ -160,7 +160,13 @@ void UGBFGameplayAbility_Interact::UpdateIndicators() auto * interactable_target_actor = interactable_component->GetOwner(); auto * indicator = NewObject< UGBFIndicatorDescriptor >(); indicator->SetDataObject( interactable_target_actor ); - indicator->SetSceneComponent( interactable_target_actor->GetRootComponent() ); + + static const FName MeshComponentIndicatorTarget( TEXT( "GBFIndicatorTarget" ) ); + + const auto target_components = interactable_target_actor->GetComponentsByTag( USceneComponent::StaticClass(), MeshComponentIndicatorTarget ); + + indicator->SetSceneComponent( target_components.IsEmpty() ? interactable_target_actor->GetRootComponent() : Cast< USceneComponent >( target_components[ 0 ] ) ); + indicator->SetComponentSocketName( widget_infos.SocketName ); indicator->SetIndicatorClass( widget_infos.InteractionWidgetClass ); indicator->SetScreenSpaceOffset( widget_infos.InteractionWidgetOffset ); indicator_manager->AddIndicator( indicator ); diff --git a/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp b/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp index 1e991df6..2dd4e636 100644 --- a/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp +++ b/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp @@ -12,7 +12,7 @@ bool FGBFIndicatorProjection::Project( const UGBFIndicatorDescriptor & indicator TOptional< FVector > world_location; if ( indicator_descriptor.GetComponentSocketName() != NAME_None ) { - world_location = component->GetSocketTransform( indicator_descriptor.GetComponentSocketName() ).GetLocation(); + world_location = component->GetSocketLocation( indicator_descriptor.GetComponentSocketName() ); } else { diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h index d83c0931..f127bdd7 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h @@ -24,6 +24,9 @@ struct FGBFInteractionWidgetInfos UPROPERTY( EditAnywhere, BlueprintReadWrite ) FVector2D InteractionWidgetOffset = FVector2D::ZeroVector; + UPROPERTY( EditDefaultsOnly, BlueprintReadWrite ) + FName SocketName; + bool operator==( const FGBFInteractionWidgetInfos & other ) const; }; From 8521d2c780d9f6c57557f16f18e1ebc242aa5c0d Mon Sep 17 00:00:00 2001 From: "michael.delva" Date: Fri, 31 Jan 2025 18:35:56 +0100 Subject: [PATCH 3/6] WIP on the interaction indicator --- GameBaseFramework.uplugin | 4 ++ .../GameBaseFramework.Build.cs | 3 +- .../Abilities/GBFGameplayAbility_Interact.cpp | 50 +++++++++----- .../GBFIndicatorDescriptor.cpp | 3 +- .../Abilities/GBFGameplayAbility_Interact.h | 13 ++-- ...eractableIndicatorCustomizationInterface.h | 24 +++++++ .../Public/Interaction/GBFInteractionOption.h | 14 ++-- .../IndicatorSystem/GBFIndicatorDescriptor.h | 69 ++++++++++--------- .../UI/IndicatorSystem/GBFIndicatorLibrary.h | 5 +- 9 files changed, 115 insertions(+), 70 deletions(-) create mode 100644 Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h diff --git a/GameBaseFramework.uplugin b/GameBaseFramework.uplugin index 797fdac6..b73b9ec3 100644 --- a/GameBaseFramework.uplugin +++ b/GameBaseFramework.uplugin @@ -126,6 +126,10 @@ { "Name": "ChaosCaching", "Enabled": true + }, + { + "Name": "ModelViewViewModel", + "Enabled": true } ] } diff --git a/Source/GameBaseFramework/GameBaseFramework.Build.cs b/Source/GameBaseFramework/GameBaseFramework.Build.cs index 7b629621..ab9d58df 100644 --- a/Source/GameBaseFramework/GameBaseFramework.Build.cs +++ b/Source/GameBaseFramework/GameBaseFramework.Build.cs @@ -62,7 +62,8 @@ public GameBaseFramework( ReadOnlyTargetRules Target ) "StateTreeModule", "LevelSequence", "MovieScene", - "ChaosCaching" + "ChaosCaching", + "ModelViewViewModel" } ); } diff --git a/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp b/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp index a80cbbc2..31b9834a 100644 --- a/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp +++ b/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp @@ -3,6 +3,7 @@ #include "Characters/Components/GBFHeroComponent.h" #include "Input/GBFInputComponent.h" #include "Interaction/GBFInteractableComponent.h" +#include "Interaction/GBFInteractableIndicatorCustomizationInterface.h" #include "Interaction/GBFInteractionEventCustomization.h" #include "Interaction/GBFInteractionOption.h" #include "Interaction/GBFInteractionStatics.h" @@ -36,6 +37,7 @@ void UGBFGameplayAbility_Interact::ActivateAbility( const FGameplayAbilitySpecHa LookForInteractables(); } + void UGBFGameplayAbility_Interact::EndAbility( const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo * ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled ) { ResetAllInteractions(); @@ -62,6 +64,11 @@ bool UGBFGameplayAbility_Interact::InputMappingContextInfos::IsValid() const return EnhancedSystem.IsValid() && InputMappingContext.IsValid(); } +void UGBFGameplayAbility_Interact::WidgetInfosHandle::Reset() +{ + InteractableComponent = nullptr; +} + void UGBFGameplayAbility_Interact::InteractableTargetContext::Reset() { for ( const auto context : InputMappingContextInfos ) @@ -85,8 +92,8 @@ void UGBFGameplayAbility_Interact::InteractableTargetContext::Reset() } } + WidgetInfosHandle.Reset(); BindActionHandles.Reset(); - WidgetInfosHandles.Reset(); OptionHandles.Reset(); InteractionsId = INDEX_NONE; } @@ -151,7 +158,7 @@ void UGBFGameplayAbility_Interact::UpdateIndicators() } Indicators.Reset(); - const auto add_indicator = [ & ]( const UGBFInteractableComponent * interactable_component, const FGBFInteractionWidgetInfos & widget_infos ) { + const auto add_indicator = [ & ]( const UGBFInteractableComponent * interactable_component, const FGBFInteractionWidgetInfos & widget_infos, TArrayView< const OptionHandle > options ) { if ( widget_infos.InteractionWidgetClass == nullptr ) { return; @@ -160,15 +167,26 @@ void UGBFGameplayAbility_Interact::UpdateIndicators() auto * interactable_target_actor = interactable_component->GetOwner(); auto * indicator = NewObject< UGBFIndicatorDescriptor >(); indicator->SetDataObject( interactable_target_actor ); - - static const FName MeshComponentIndicatorTarget( TEXT( "GBFIndicatorTarget" ) ); - - const auto target_components = interactable_target_actor->GetComponentsByTag( USceneComponent::StaticClass(), MeshComponentIndicatorTarget ); - - indicator->SetSceneComponent( target_components.IsEmpty() ? interactable_target_actor->GetRootComponent() : Cast< USceneComponent >( target_components[ 0 ] ) ); + indicator->SetSceneComponent( interactable_target_actor->GetRootComponent() ); indicator->SetComponentSocketName( widget_infos.SocketName ); indicator->SetIndicatorClass( widget_infos.InteractionWidgetClass ); + indicator->SetWorldPositionOffset( widget_infos.InteractionWorldOffset ); indicator->SetScreenSpaceOffset( widget_infos.InteractionWidgetOffset ); + indicator->SetProjectionMode( widget_infos.ProjectionMode ); + + if ( interactable_target_actor->Implements< UGBFInteractableIndicatorCustomizationInterface >() ) + { + TArray< FGBFInteractionOption > interaction_options; + interaction_options.Reserve( options.Num() ); + + for ( const auto & option : options ) + { + interaction_options.Emplace( option.InitialInteractionOption ); + } + + IGBFInteractableIndicatorCustomizationInterface::Execute_UpdateIndicator( interactable_target_actor, indicator, interaction_options ); + } + indicator_manager->AddIndicator( indicator ); Indicators.Add( indicator ); @@ -176,10 +194,7 @@ void UGBFGameplayAbility_Interact::UpdateIndicators() for ( const auto & [ actor, context ] : InteractableTargetContexts ) { - for ( const auto & option_container : context.WidgetInfosHandles ) - { - add_indicator( option_container.InteractableComponent.Get(), option_container.WidgetInfos ); - } + add_indicator( context.WidgetInfosHandle.InteractableComponent.Get(), context.WidgetInfosHandle.WidgetInfos, context.OptionHandles ); } } } @@ -331,7 +346,7 @@ void UGBFGameplayAbility_Interact::RegisterInteraction( const InteractableTarget return; } - context.WidgetInfosHandles.Emplace( interactable_component, option_container.CommonWidgetInfos ); + context.WidgetInfosHandle = { interactable_component, option_container.CommonWidgetInfos }; if ( const auto * pc = Cast< APlayerController >( pawn->GetController() ) ) { @@ -360,10 +375,9 @@ void UGBFGameplayAbility_Interact::RegisterInteraction( const InteractableTarget continue; } - auto & option_handle = context.OptionHandles.AddZeroed_GetRef(); + OptionHandle option_handle; option_handle.InteractableComponent = interactable_component; - - const FGameplayAbilitySpec * interaction_ability_spec = nullptr; + option_handle.InitialInteractionOption = option; switch ( option.AbilityTarget ) { @@ -390,7 +404,7 @@ void UGBFGameplayAbility_Interact::RegisterInteraction( const InteractableTarget } // Find the spec - interaction_ability_spec = option_handle.TargetAbilitySystem->FindAbilitySpecFromClass( option.InteractionAbility ); + const auto * interaction_ability_spec = option_handle.TargetAbilitySystem->FindAbilitySpecFromClass( option.InteractionAbility ); if ( interaction_ability_spec == nullptr ) { @@ -419,6 +433,6 @@ void UGBFGameplayAbility_Interact::RegisterInteraction( const InteractableTarget } } - context.WidgetInfosHandles.Emplace( interactable_component, option.WidgetInfos ); + context.OptionHandles.Emplace( MoveTemp( option_handle ) ); } } diff --git a/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp b/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp index 2dd4e636..6fe5bf5f 100644 --- a/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp +++ b/Source/GameBaseFramework/Private/UI/IndicatorSystem/GBFIndicatorDescriptor.cpp @@ -20,9 +20,8 @@ bool FGBFIndicatorProjection::Project( const UGBFIndicatorDescriptor & indicator } const auto project_world_location = world_location.GetValue() + indicator_descriptor.GetWorldPositionOffset(); - const auto projection_mode = indicator_descriptor.GetProjectionMode(); - switch ( projection_mode ) + switch ( const auto projection_mode = indicator_descriptor.GetProjectionMode() ) { case EGBFActorCanvasProjectionMode::ComponentPoint: { diff --git a/Source/GameBaseFramework/Public/Interaction/Abilities/GBFGameplayAbility_Interact.h b/Source/GameBaseFramework/Public/Interaction/Abilities/GBFGameplayAbility_Interact.h index c46150db..b61abd1f 100644 --- a/Source/GameBaseFramework/Public/Interaction/Abilities/GBFGameplayAbility_Interact.h +++ b/Source/GameBaseFramework/Public/Interaction/Abilities/GBFGameplayAbility_Interact.h @@ -73,18 +73,11 @@ class GAMEBASEFRAMEWORK_API UGBFGameplayAbility_Interact : public UGBFGameplayAb { OptionHandle() = default; - OptionHandle( const TWeakObjectPtr< UGBFInteractableComponent > & interactable_component, const TWeakObjectPtr< UAbilitySystemComponent > & target_ability_system, const FGameplayAbilitySpecHandle & interaction_ability_handle, const TWeakObjectPtr< UGBFInteractionEventCustomization > & event_customization ) : - InteractableComponent( interactable_component ), - TargetAbilitySystem( target_ability_system ), - InteractionAbilityHandle( interaction_ability_handle ), - EventCustomization( event_customization ) - { - } - TWeakObjectPtr< UGBFInteractableComponent > InteractableComponent; TWeakObjectPtr< UAbilitySystemComponent > TargetAbilitySystem; FGameplayAbilitySpecHandle InteractionAbilityHandle; TWeakObjectPtr< UGBFInteractionEventCustomization > EventCustomization; + FGBFInteractionOption InitialInteractionOption; }; struct WidgetInfosHandle @@ -97,6 +90,8 @@ class GAMEBASEFRAMEWORK_API UGBFGameplayAbility_Interact : public UGBFGameplayAb { } + void Reset(); + TWeakObjectPtr< UGBFInteractableComponent > InteractableComponent; FGBFInteractionWidgetInfos WidgetInfos; }; @@ -106,7 +101,7 @@ class GAMEBASEFRAMEWORK_API UGBFGameplayAbility_Interact : public UGBFGameplayAb void Reset(); int InteractionsId; - TArray< WidgetInfosHandle > WidgetInfosHandles; + WidgetInfosHandle WidgetInfosHandle; TArray< OptionHandle > OptionHandles; TArray< InputMappingContextInfos > InputMappingContextInfos; TArray< InputBindingInfos > BindActionHandles; diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h new file mode 100644 index 00000000..3894ab62 --- /dev/null +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h @@ -0,0 +1,24 @@ +#pragma once + +#include "UI/IndicatorSystem/GBFIndicatorDescriptor.h" + +#include +#include +#include + +#include "GBFInteractableIndicatorCustomizationInterface.generated.h" + +UINTERFACE( BlueprintType ) +class GAMEBASEFRAMEWORK_API UGBFInteractableIndicatorCustomizationInterface : public UInterface +{ + GENERATED_BODY() +}; + +class IGBFInteractableIndicatorCustomizationInterface +{ + GENERATED_BODY() + +public: + UFUNCTION( BlueprintCallable, BlueprintNativeEvent, Category = "Indicator" ) + void UpdateIndicator( UGBFIndicatorDescriptor * indicator_descriptor, const TArray< FGBFInteractionOption > & options ); +}; diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h index f127bdd7..c99546dc 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h @@ -1,5 +1,7 @@ #pragma once +#include "UI/IndicatorSystem/GBFIndicatorDescriptor.h" + #include #include "GBFInteractionOption.generated.h" @@ -21,12 +23,18 @@ struct FGBFInteractionWidgetInfos UPROPERTY( EditAnywhere, BlueprintReadWrite ) TSoftClassPtr< UUserWidget > InteractionWidgetClass; + UPROPERTY( EditAnywhere, BlueprintReadWrite ) + FVector InteractionWorldOffset = FVector::ZeroVector; + UPROPERTY( EditAnywhere, BlueprintReadWrite ) FVector2D InteractionWidgetOffset = FVector2D::ZeroVector; UPROPERTY( EditDefaultsOnly, BlueprintReadWrite ) FName SocketName; + UPROPERTY( EditAnywhere, BlueprintReadWrite ) + EGBFActorCanvasProjectionMode ProjectionMode = EGBFActorCanvasProjectionMode::ActorBoundingBox; + bool operator==( const FGBFInteractionWidgetInfos & other ) const; }; @@ -92,9 +100,6 @@ struct FGBFInteractionOption UPROPERTY( EditAnywhere, BlueprintReadOnly ) TObjectPtr< const UInputAction > InputAction = nullptr; - UPROPERTY( EditAnywhere, BlueprintReadOnly ) - FGBFInteractionWidgetInfos WidgetInfos; - bool operator==( const FGBFInteractionOption & other ) const; bool operator!=( const FGBFInteractionOption & other ) const; }; @@ -103,8 +108,7 @@ FORCEINLINE bool FGBFInteractionOption::operator==( const FGBFInteractionOption { return InteractionAbility == other.InteractionAbility && Text.IdenticalTo( other.Text ) && - SubText.IdenticalTo( other.SubText ) && - WidgetInfos == other.WidgetInfos; + SubText.IdenticalTo( other.SubText ); } FORCEINLINE bool FGBFInteractionOption::operator!=( const FGBFInteractionOption & other ) const diff --git a/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h b/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h index a3151bcf..1be57ab5 100644 --- a/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h +++ b/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h @@ -5,6 +5,7 @@ #include "GBFIndicatorDescriptor.generated.h" +class UMVVMViewModelBase; class SWidget; class UGBFIndicatorDescriptor; class UGBFIndicatorManagerComponent; @@ -37,26 +38,38 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject GENERATED_BODY() public: - UGBFIndicatorDescriptor() - {} + UGBFIndicatorDescriptor() = default; -public: UFUNCTION( BlueprintCallable ) UObject * GetDataObject() const { return DataObject; } + UFUNCTION( BlueprintCallable ) void SetDataObject( UObject * data_object ) { DataObject = data_object; } + UFUNCTION( BlueprintCallable ) + UMVVMViewModelBase * GetViewModel() const + { + return ViewModel; + } + + UFUNCTION( BlueprintCallable ) + void SetViewModel( UMVVMViewModelBase * view_model ) + { + ViewModel = view_model; + } + UFUNCTION( BlueprintCallable ) USceneComponent * GetSceneComponent() const { return Component; } + UFUNCTION( BlueprintCallable ) void SetSceneComponent( USceneComponent * component ) { @@ -68,6 +81,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return ComponentSocketName; } + UFUNCTION( BlueprintCallable ) void SetComponentSocketName( const FName socket_name ) { @@ -79,22 +93,19 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return IndicatorWidgetClass; } + UFUNCTION( BlueprintCallable ) void SetIndicatorClass( const TSoftClassPtr< UUserWidget > indicator_widget_class ) { IndicatorWidgetClass = indicator_widget_class; } - -public: - // TODO Organize this better. - TWeakObjectPtr< UUserWidget > IndicatorWidget; - -public: + UFUNCTION( BlueprintCallable ) void SetAutoRemoveWhenIndicatorComponentIsNull( const bool can_automatically_remove ) { bAutoRemoveWhenIndicatorComponentIsNull = can_automatically_remove; } + UFUNCTION( BlueprintCallable ) bool GetAutoRemoveWhenIndicatorComponentIsNull() const { @@ -105,11 +116,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return bAutoRemoveWhenIndicatorComponentIsNull && !IsValid( GetSceneComponent() ); } - -public: - // Layout Properties - //======================= - + UFUNCTION( BlueprintCallable ) bool GetIsVisible() const { @@ -127,78 +134,79 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return ProjectionMode; } + UFUNCTION( BlueprintCallable ) void SetProjectionMode( const EGBFActorCanvasProjectionMode projection_mode ) { ProjectionMode = projection_mode; } - // Horizontal alignment to the point in space to place the indicator at. UFUNCTION( BlueprintCallable ) EHorizontalAlignment GetHAlign() const { return HAlignment; } + UFUNCTION( BlueprintCallable ) void SetHAlign( const EHorizontalAlignment h_alignment ) { HAlignment = h_alignment; } - // Vertical alignment to the point in space to place the indicator at. UFUNCTION( BlueprintCallable ) EVerticalAlignment GetVAlign() const { return VAlignment; } + UFUNCTION( BlueprintCallable ) void SetVAlign( const EVerticalAlignment v_alignment ) { VAlignment = v_alignment; } - // Clamp the indicator to the edge of the screen? UFUNCTION( BlueprintCallable ) bool GetClampToScreen() const { return bClampToScreen; } + UFUNCTION( BlueprintCallable ) void SetClampToScreen( const bool value ) { bClampToScreen = value; } - // Show the arrow if clamping to the edge of the screen? UFUNCTION( BlueprintCallable ) bool GetShowClampToScreenArrow() const { return bShowClampToScreenArrow; } + UFUNCTION( BlueprintCallable ) void SetShowClampToScreenArrow( const bool value ) { bShowClampToScreenArrow = value; } - // The position offset for the indicator in world space. UFUNCTION( BlueprintCallable ) FVector GetWorldPositionOffset() const { return WorldPositionOffset; } + UFUNCTION( BlueprintCallable ) void SetWorldPositionOffset( const FVector offset ) { WorldPositionOffset = offset; } - // The position offset for the indicator in screen space. UFUNCTION( BlueprintCallable ) FVector2D GetScreenSpaceOffset() const { return ScreenSpaceOffset; } + UFUNCTION( BlueprintCallable ) void SetScreenSpaceOffset( const FVector2D offset ) { @@ -210,40 +218,38 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return BoundingBoxAnchor; } + UFUNCTION( BlueprintCallable ) void SetBoundingBoxAnchor( const FVector bounding_box_anchor ) { BoundingBoxAnchor = bounding_box_anchor; } -public: - // Sorting Properties - //======================= - - // Allows sorting the indicators (after they are sorted by depth), to allow some group of indicators - // to always be in front of others. UFUNCTION( BlueprintCallable ) int32 GetPriority() const { return Priority; } + UFUNCTION( BlueprintCallable ) void SetPriority( const int32 priority ) { Priority = priority; } -public: - UGBFIndicatorManagerComponent * GetIndicatorManagerComponent() + UGBFIndicatorManagerComponent * GetIndicatorManagerComponent() const { return ManagerPtr.Get(); } + void SetIndicatorManagerComponent( UGBFIndicatorManagerComponent * manager ); UFUNCTION( BlueprintCallable ) void UnregisterIndicator(); private: + friend class SGBFActorCanvas; + UPROPERTY() bool bVisible = true; UPROPERTY() @@ -272,12 +278,12 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject UPROPERTY() FVector WorldPositionOffset = FVector( 0, 0, 0 ); -private: - friend class SGBFActorCanvas; - UPROPERTY() TObjectPtr< UObject > DataObject; + UPROPERTY() + TObjectPtr< UMVVMViewModelBase > ViewModel; + UPROPERTY() TObjectPtr< USceneComponent > Component; @@ -290,6 +296,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject UPROPERTY() TWeakObjectPtr< UGBFIndicatorManagerComponent > ManagerPtr; + TWeakObjectPtr< UUserWidget > IndicatorWidget; TWeakPtr< SWidget > Content; TWeakPtr< SWidget > CanvasHost; }; diff --git a/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorLibrary.h b/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorLibrary.h index fdca11a7..dc93892c 100644 --- a/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorLibrary.h +++ b/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorLibrary.h @@ -5,9 +5,6 @@ #include "GBFIndicatorLibrary.generated.h" class UGBFIndicatorManagerComponent; -class AController; -class UObject; -struct FFrame; UCLASS() class GAMEBASEFRAMEWORK_API UGBFIndicatorLibrary : public UBlueprintFunctionLibrary @@ -19,4 +16,4 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorLibrary : public UBlueprintFunctionLibr UFUNCTION( BlueprintCallable, Category = Indicator ) static UGBFIndicatorManagerComponent * GetIndicatorManagerComponent( AController * controller ); -}; +}; \ No newline at end of file From 1e3fc3a657cc224964b09b70b2b0ff18a163cfdd Mon Sep 17 00:00:00 2001 From: Michael Delva Date: Mon, 3 Feb 2025 16:34:44 +0100 Subject: [PATCH 4/6] Removed interface and let inherited components of UGBFInteractableComponent customize the indicator --- .../Abilities/GBFGameplayAbility_Interact.cpp | 21 +++++++--------- .../Interaction/GBFInteractableComponent.cpp | 6 ++++- .../Interaction/GBFInteractableComponent.h | 3 +++ ...eractableIndicatorCustomizationInterface.h | 24 ------------------- .../Public/Interaction/GBFInteractionOption.h | 9 ++++--- 5 files changed, 23 insertions(+), 40 deletions(-) delete mode 100644 Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h diff --git a/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp b/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp index 31b9834a..b57a29b0 100644 --- a/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp +++ b/Source/GameBaseFramework/Private/Interaction/Abilities/GBFGameplayAbility_Interact.cpp @@ -3,7 +3,6 @@ #include "Characters/Components/GBFHeroComponent.h" #include "Input/GBFInputComponent.h" #include "Interaction/GBFInteractableComponent.h" -#include "Interaction/GBFInteractableIndicatorCustomizationInterface.h" #include "Interaction/GBFInteractionEventCustomization.h" #include "Interaction/GBFInteractionOption.h" #include "Interaction/GBFInteractionStatics.h" @@ -158,7 +157,7 @@ void UGBFGameplayAbility_Interact::UpdateIndicators() } Indicators.Reset(); - const auto add_indicator = [ & ]( const UGBFInteractableComponent * interactable_component, const FGBFInteractionWidgetInfos & widget_infos, TArrayView< const OptionHandle > options ) { + const auto add_indicator = [ & ]( UGBFInteractableComponent * interactable_component, const FGBFInteractionWidgetInfos & widget_infos, TArrayView< const OptionHandle > options ) { if ( widget_infos.InteractionWidgetClass == nullptr ) { return; @@ -173,20 +172,18 @@ void UGBFGameplayAbility_Interact::UpdateIndicators() indicator->SetWorldPositionOffset( widget_infos.InteractionWorldOffset ); indicator->SetScreenSpaceOffset( widget_infos.InteractionWidgetOffset ); indicator->SetProjectionMode( widget_infos.ProjectionMode ); + indicator->SetBoundingBoxAnchor( widget_infos.BoundingBoxAnchor ); - if ( interactable_target_actor->Implements< UGBFInteractableIndicatorCustomizationInterface >() ) - { - TArray< FGBFInteractionOption > interaction_options; - interaction_options.Reserve( options.Num() ); - - for ( const auto & option : options ) - { - interaction_options.Emplace( option.InitialInteractionOption ); - } + TArray< FGBFInteractionOption > interaction_options; + interaction_options.Reserve( options.Num() ); - IGBFInteractableIndicatorCustomizationInterface::Execute_UpdateIndicator( interactable_target_actor, indicator, interaction_options ); + for ( const auto & option : options ) + { + interaction_options.Emplace( option.InitialInteractionOption ); } + interactable_component->CustomizeIndicator( indicator, interaction_options ); + indicator_manager->AddIndicator( indicator ); Indicators.Add( indicator ); diff --git a/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp b/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp index 5f86fee9..e4f9afe7 100644 --- a/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp +++ b/Source/GameBaseFramework/Private/Interaction/GBFInteractableComponent.cpp @@ -40,4 +40,8 @@ void UGBFInteractableComponent::RemoveInteractions() void UGBFInteractableComponent::CustomizeInteractionEventData_Implementation( FGameplayEventData & event_data, FGameplayTag event_tag ) { -} \ No newline at end of file +} + +void UGBFInteractableComponent::CustomizeIndicator_Implementation( UGBFIndicatorDescriptor * indicator_descriptor, const TArray< FGBFInteractionOption > & options ) +{ +} diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h index eba42461..fa2c5292 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractableComponent.h @@ -32,6 +32,9 @@ class GAMEBASEFRAMEWORK_API UGBFInteractableComponent : public UActorComponent UFUNCTION( BlueprintNativeEvent, meta = ( ForceAsFunction ) ) void CustomizeInteractionEventData( UPARAM( ref ) FGameplayEventData & event_data, FGameplayTag event_tag ); + UFUNCTION( BlueprintNativeEvent, meta = ( ForceAsFunction ) ) + void CustomizeIndicator( UGBFIndicatorDescriptor * indicator_descriptor, const TArray< FGBFInteractionOption > & options ); + private: UPROPERTY( EditAnywhere, BlueprintReadOnly, meta = ( AllowPrivateAccess = true ) ) FGBFInteractionOptionContainer InteractionOptionContainer; diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h deleted file mode 100644 index 3894ab62..00000000 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractableIndicatorCustomizationInterface.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "UI/IndicatorSystem/GBFIndicatorDescriptor.h" - -#include -#include -#include - -#include "GBFInteractableIndicatorCustomizationInterface.generated.h" - -UINTERFACE( BlueprintType ) -class GAMEBASEFRAMEWORK_API UGBFInteractableIndicatorCustomizationInterface : public UInterface -{ - GENERATED_BODY() -}; - -class IGBFInteractableIndicatorCustomizationInterface -{ - GENERATED_BODY() - -public: - UFUNCTION( BlueprintCallable, BlueprintNativeEvent, Category = "Indicator" ) - void UpdateIndicator( UGBFIndicatorDescriptor * indicator_descriptor, const TArray< FGBFInteractionOption > & options ); -}; diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h index c99546dc..f3f5a79e 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h @@ -29,12 +29,15 @@ struct FGBFInteractionWidgetInfos UPROPERTY( EditAnywhere, BlueprintReadWrite ) FVector2D InteractionWidgetOffset = FVector2D::ZeroVector; - UPROPERTY( EditDefaultsOnly, BlueprintReadWrite ) - FName SocketName; - UPROPERTY( EditAnywhere, BlueprintReadWrite ) EGBFActorCanvasProjectionMode ProjectionMode = EGBFActorCanvasProjectionMode::ActorBoundingBox; + UPROPERTY( EditAnywhere, BlueprintReadOnly, meta = ( EditCondition = "ProjectionMode != EGBFActorCanvasProjectionMode::ComponentPoint") ) + FVector BoundingBoxAnchor = { 0.5f, 0.5f, 1.0f }; + + UPROPERTY( EditDefaultsOnly, BlueprintReadWrite ) + FName SocketName; + bool operator==( const FGBFInteractionWidgetInfos & other ) const; }; From 1a5f5debeb103036ba60fc0db51853828e589b3b Mon Sep 17 00:00:00 2001 From: Michael Delva Date: Mon, 3 Feb 2025 16:50:18 +0100 Subject: [PATCH 5/6] CS --- .../IndicatorSystem/GBFIndicatorDescriptor.h | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h b/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h index 1be57ab5..c665fccf 100644 --- a/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h +++ b/Source/GameBaseFramework/Public/UI/IndicatorSystem/GBFIndicatorDescriptor.h @@ -45,7 +45,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return DataObject; } - + UFUNCTION( BlueprintCallable ) void SetDataObject( UObject * data_object ) { @@ -57,7 +57,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return ViewModel; } - + UFUNCTION( BlueprintCallable ) void SetViewModel( UMVVMViewModelBase * view_model ) { @@ -69,7 +69,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return Component; } - + UFUNCTION( BlueprintCallable ) void SetSceneComponent( USceneComponent * component ) { @@ -81,7 +81,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return ComponentSocketName; } - + UFUNCTION( BlueprintCallable ) void SetComponentSocketName( const FName socket_name ) { @@ -93,19 +93,19 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return IndicatorWidgetClass; } - + UFUNCTION( BlueprintCallable ) void SetIndicatorClass( const TSoftClassPtr< UUserWidget > indicator_widget_class ) { IndicatorWidgetClass = indicator_widget_class; } - + UFUNCTION( BlueprintCallable ) void SetAutoRemoveWhenIndicatorComponentIsNull( const bool can_automatically_remove ) { bAutoRemoveWhenIndicatorComponentIsNull = can_automatically_remove; } - + UFUNCTION( BlueprintCallable ) bool GetAutoRemoveWhenIndicatorComponentIsNull() const { @@ -116,7 +116,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return bAutoRemoveWhenIndicatorComponentIsNull && !IsValid( GetSceneComponent() ); } - + UFUNCTION( BlueprintCallable ) bool GetIsVisible() const { @@ -134,7 +134,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return ProjectionMode; } - + UFUNCTION( BlueprintCallable ) void SetProjectionMode( const EGBFActorCanvasProjectionMode projection_mode ) { @@ -170,7 +170,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return bClampToScreen; } - + UFUNCTION( BlueprintCallable ) void SetClampToScreen( const bool value ) { @@ -241,7 +241,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject { return ManagerPtr.Get(); } - + void SetIndicatorManagerComponent( UGBFIndicatorManagerComponent * manager ); UFUNCTION( BlueprintCallable ) @@ -249,7 +249,7 @@ class GAMEBASEFRAMEWORK_API UGBFIndicatorDescriptor : public UObject private: friend class SGBFActorCanvas; - + UPROPERTY() bool bVisible = true; UPROPERTY() From d91fc2beaca837fff12254ca13bbdf423ef41e17 Mon Sep 17 00:00:00 2001 From: Michael Delva Date: Tue, 4 Feb 2025 11:56:22 +0100 Subject: [PATCH 6/6] CS --- .../GameBaseFramework/Public/Interaction/GBFInteractionOption.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h index f3f5a79e..b4f2e085 100644 --- a/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h +++ b/Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h @@ -32,7 +32,7 @@ struct FGBFInteractionWidgetInfos UPROPERTY( EditAnywhere, BlueprintReadWrite ) EGBFActorCanvasProjectionMode ProjectionMode = EGBFActorCanvasProjectionMode::ActorBoundingBox; - UPROPERTY( EditAnywhere, BlueprintReadOnly, meta = ( EditCondition = "ProjectionMode != EGBFActorCanvasProjectionMode::ComponentPoint") ) + UPROPERTY( EditAnywhere, BlueprintReadOnly, meta = ( EditCondition = "ProjectionMode != EGBFActorCanvasProjectionMode::ComponentPoint" ) ) FVector BoundingBoxAnchor = { 0.5f, 0.5f, 1.0f }; UPROPERTY( EditDefaultsOnly, BlueprintReadWrite )