Skip to content

Interaction Indicator Text and position management #343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions GameBaseFramework.uplugin
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@
{
"Name": "ChaosCaching",
"Enabled": true
},
{
"Name": "ModelViewViewModel",
"Enabled": true
}
]
}
3 changes: 2 additions & 1 deletion Source/GameBaseFramework/GameBaseFramework.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public GameBaseFramework( ReadOnlyTargetRules Target )
"StateTreeModule",
"LevelSequence",
"MovieScene",
"ChaosCaching"
"ChaosCaching",
"ModelViewViewModel"
}
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,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();
Expand All @@ -62,6 +63,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 )
Expand All @@ -85,8 +91,8 @@ void UGBFGameplayAbility_Interact::InteractableTargetContext::Reset()
}
}

WidgetInfosHandle.Reset();
BindActionHandles.Reset();
WidgetInfosHandles.Reset();
OptionHandles.Reset();
InteractionsId = INDEX_NONE;
}
Expand Down Expand Up @@ -151,7 +157,7 @@ void UGBFGameplayAbility_Interact::UpdateIndicators()
}
Indicators.Reset();

const auto add_indicator = [ & ]( const UGBFInteractableComponent * interactable_component, const FGBFInteractionWidgetInfos & widget_infos ) {
const auto add_indicator = [ & ]( UGBFInteractableComponent * interactable_component, const FGBFInteractionWidgetInfos & widget_infos, TArrayView< const OptionHandle > options ) {
if ( widget_infos.InteractionWidgetClass == nullptr )
{
return;
Expand All @@ -161,19 +167,31 @@ void UGBFGameplayAbility_Interact::UpdateIndicators()
auto * indicator = NewObject< UGBFIndicatorDescriptor >();
indicator->SetDataObject( interactable_target_actor );
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 );
indicator->SetBoundingBoxAnchor( widget_infos.BoundingBoxAnchor );

TArray< FGBFInteractionOption > interaction_options;
interaction_options.Reserve( options.Num() );

for ( const auto & option : options )
{
interaction_options.Emplace( option.InitialInteractionOption );
}

interactable_component->CustomizeIndicator( indicator, interaction_options );

indicator_manager->AddIndicator( indicator );

Indicators.Add( indicator );
};

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 );
}
}
}
Expand Down Expand Up @@ -325,7 +343,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() ) )
{
Expand Down Expand Up @@ -354,10 +372,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 )
{
Expand All @@ -384,7 +401,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 )
{
Expand Down Expand Up @@ -413,6 +430,6 @@ void UGBFGameplayAbility_Interact::RegisterInteraction( const InteractableTarget
}
}

context.WidgetInfosHandles.Emplace( interactable_component, option.WidgetInfos );
context.OptionHandles.Emplace( MoveTemp( option_handle ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ void UGBFInteractableComponent::RemoveInteractions()

void UGBFInteractableComponent::CustomizeInteractionEventData_Implementation( FGameplayEventData & event_data, FGameplayTag event_tag )
{
}
}

void UGBFInteractableComponent::CustomizeIndicator_Implementation( UGBFIndicatorDescriptor * indicator_descriptor, const TArray< FGBFInteractionOption > & options )
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ 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
{
world_location = component->GetComponentLocation();
}

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:
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -97,6 +90,8 @@ class GAMEBASEFRAMEWORK_API UGBFGameplayAbility_Interact : public UGBFGameplayAb
{
}

void Reset();

TWeakObjectPtr< UGBFInteractableComponent > InteractableComponent;
FGBFInteractionWidgetInfos WidgetInfos;
};
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
24 changes: 17 additions & 7 deletions Source/GameBaseFramework/Public/Interaction/GBFInteractionOption.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "UI/IndicatorSystem/GBFIndicatorDescriptor.h"

#include <Abilities/GameplayAbility.h>

#include "GBFInteractionOption.generated.h"
Expand All @@ -21,9 +23,21 @@ struct FGBFInteractionWidgetInfos
UPROPERTY( EditAnywhere, BlueprintReadWrite )
TSoftClassPtr< UUserWidget > InteractionWidgetClass;

UPROPERTY( EditAnywhere, BlueprintReadWrite )
FVector InteractionWorldOffset = FVector::ZeroVector;

UPROPERTY( EditAnywhere, BlueprintReadWrite )
FVector2D InteractionWidgetOffset = FVector2D::ZeroVector;

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;
};

Expand Down Expand Up @@ -80,18 +94,15 @@ 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 )
TObjectPtr< const UInputAction > InputAction = nullptr;

UPROPERTY( EditAnywhere, BlueprintReadOnly )
FGBFInteractionWidgetInfos WidgetInfos;

bool operator==( const FGBFInteractionOption & other ) const;
bool operator!=( const FGBFInteractionOption & other ) const;
};
Expand All @@ -100,8 +111,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
Expand Down
Loading
Loading