UI interactable cleanup, Cutscene system and UI

This commit is contained in:
Oleg Petruny 2024-06-20 22:23:35 +02:00
parent a52d2aaa4a
commit ce84cc2a9f
47 changed files with 497 additions and 155 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"FileVersion": 3,
"EngineAssociation": "5.4",
"EngineAssociation": "{42CC8720-4DDD-EF11-BECE-CEBF292119D8}",
"Category": "",
"Description": "",
"Modules": [

View File

@ -6,15 +6,10 @@ public class Lost_Edge : ModuleRules {
public Lost_Edge(ReadOnlyTargetRules Target) : base(Target) {
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OpenCV" }); // "OpenCVHelper"
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OpenCV" });
//PrivateIncludePaths.AddRange(new string[] { "OpenCV/Private" });
PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput", "UMG", "RHI", "RenderCore", "Lost_EdgeShaders", "TextureCompressor" }); // "Slate", "SlateCore"
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput", "UMG", "RHI", "RenderCore", "Lost_EdgeShaders", "TextureCompressor",
"LevelSequence", "MovieScene" }); // "Slate", "SlateCore"
// UE_LOG(LogTemp, Log, TEXT("capture: %s"), (capture ? TEXT("true") : TEXT("false")));
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("1"));

View File

@ -0,0 +1,169 @@
// Oleg Petruny proprietary.
#include "CutsceneManager.h"
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "LevelSequence.h"
#include "LevelSequencePlayer.h"
#include "CustomGameInstanceBase.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "Widgets/CutsceneSkipWidget.h"
#include "Widgets/InputAnimatedWidgetInterface.h"
#include "Widgets/WidgetsManager.h"
UCutsceneManager::UCutsceneManager()
{
_inputContext = { FSoftObjectPath{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Cutscene.IMC_Cutscene'") } };
if(auto world = GetWorld())
{
if(auto GI = Cast<UCustomGameInstanceBase>(world->GetGameInstance()))
{
GI->inputContexts.Add(_inputContext);
}
}
}
void UCutsceneManager::EnqueueSequence(ULevelSequence* sequence, FCutsceneEndCallback endCallback)
{
if(!sequence)
return;
if(_nextSequences.IsEmpty() && !_sequencePlayer) // most first sequence, so widgets and binds don't exist
{
if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{
_lastPlayer = Cast<APlayerBase>(PC->GetPawn());
if(_lastPlayer)
{
_lastPlayer->LockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true });
auto& mapping = _inputContext.LoadSynchronous()->GetMapping(0);
int32 handler1 = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Started, this, &UCutsceneManager::OnInputHold).GetHandle();
int32 handler2 = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UCutsceneManager::OnInputUnhold).GetHandle();
_handlers = { handler1, handler2 };
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
WM->HideWidgets();
static FSkipCutsceneDelegate skipCutsceneDelegate;
if(!skipCutsceneDelegate.IsBound())
skipCutsceneDelegate.BindDynamic(this, &UCutsceneManager::SkipSequence);
WM->EnableCutsceneWidget(mapping.Key.GetDisplayName(false), skipCutsceneDelegate);
}
}
}
}
_nextSequences.Enqueue(sequence);
_endCallbacks.Enqueue(endCallback);
PlayNextSequence();
}
void UCutsceneManager::PlayNextSequence()
{
if(_sequencePlayer)
{
if(_sequencePlayer->IsPlaying())
return;
else
_sequencePlayer->MarkAsGarbage();
}
ULevelSequence* sequence;
_nextSequences.Dequeue(sequence);
_sequencePlayer = ULevelSequencePlayer::CreateLevelSequencePlayer(GetWorld(), sequence, FMovieSceneSequencePlaybackSettings{}, _sequencePlayerActor);
_sequencePlayer->OnStop.AddDynamic(this, &UCutsceneManager::OnSequenceEnd);
_sequencePlayer->Play();
}
void UCutsceneManager::SkipSequence()
{
if(!_sequencePlayer || !_sequencePlayer->IsPlaying())
return;
_lastlySkipped = true;
_sequencePlayer->GoToEndAndStop();
}
void UCutsceneManager::ClearQueue()
{
if(!_nextSequences.IsEmpty())
_nextSequences.Empty();
if(!_endCallbacks.IsEmpty())
_endCallbacks.Empty();
}
void UCutsceneManager::LockCallback(bool lock)
{
_lockCallback = lock;
}
void UCutsceneManager::OnSequenceEnd()
{
if(_lockCallback)
return;
_sequencePlayer->MarkAsGarbage();
_sequencePlayer = nullptr;
FCutsceneEndCallback callback;
_endCallbacks.Dequeue(callback);
if(callback.IsBound())
callback.Execute();
if(!_nextSequences.IsEmpty())
{
PlayNextSequence();
if(_lastlySkipped)
{
_lastlySkipped = false;
if(_holding)
{
OnInputHold();
}
}
return;
}
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
WM->DisableCutsceneWidget();
WM->ShowWidgets();
}
if(_lastPlayer)
{
_lastPlayer->UnlockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true });
_lastPlayer->inputComponent->RemoveBindingByHandle(_handlers.Key);
_lastPlayer->inputComponent->RemoveBindingByHandle(_handlers.Value);
_lastPlayer = nullptr;
}
}
void UCutsceneManager::OnInputHold()
{
_holding = true;
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
WM->AnimateCutsceneWidget(EInputAnimatedWidgetAnimation::Hold);
}
}
void UCutsceneManager::OnInputUnhold()
{
_holding = false;
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
WM->AnimateCutsceneWidget(EInputAnimatedWidgetAnimation::Unhold);
}
}

View File

@ -0,0 +1,48 @@
// Oleg Petruny proprietary.
#pragma once
#include "UObject/Object.h"
#include "CutsceneManager.generated.h"
DECLARE_DYNAMIC_DELEGATE(FCutsceneEndCallback);
UCLASS(BlueprintType)
class UCutsceneManager : public UObject
{
GENERATED_BODY()
public:
UCutsceneManager();
UFUNCTION(BlueprintCallable)
void EnqueueSequence(class ULevelSequence* sequence, FCutsceneEndCallback endCallback);
UFUNCTION(BlueprintCallable)
void SkipSequence();
void ClearQueue();
void LockCallback(bool lock);
private:
void PlayNextSequence();
UFUNCTION()
void OnSequenceEnd();
void OnInputHold();
void OnInputUnhold();
class ULevelSequencePlayer* _sequencePlayer = nullptr;
class ALevelSequenceActor* _sequencePlayerActor = nullptr;
TQueue<class ULevelSequence*> _nextSequences;
TQueue<FCutsceneEndCallback> _endCallbacks;
class APlayerBase* _lastPlayer = nullptr;
TSoftObjectPtr<class UInputMappingContext> _inputContext;
TPair<int32, int32> _handlers;
bool _lockCallback = false;
bool _lastlySkipped = false;
bool _holding = false;
};

View File

@ -5,7 +5,7 @@
#include "Components/SceneComponent.h"
#include "CoreMinimal.h"
#include "../Interactable.h"
#include "Interactable/Interactable.h"
#include "InteractableActivator.generated.h"

View File

@ -5,10 +5,10 @@
#include "Kismet/GameplayStatics.h"
#include "../MainGameModeBase.h"
#include "../PlayerBase.h"
#include "../Widgets/WidgetsManager.h"
#include "MainGameModeBase.h"
#include "Modificators/InteractableModificator.h"
#include "PlayerBase.h"
#include "Widgets/WidgetsManager.h"
int32 AInteractable::GetActivatedFlags()
{
@ -90,7 +90,7 @@ void AInteractable::_Activate(EActivatorType type)
|| !activationLockers.IsEmpty())
return;
if(auto WM = AMainGameModeBase::GetWidgetManager())
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
for(const auto& modificator : modificators)
{
@ -119,7 +119,7 @@ void AInteractable::_Deactivate(EActivatorType type)
|| !activationLockers.IsEmpty())
return;
if(auto WM = AMainGameModeBase::GetWidgetManager())
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
for(const auto& modificator : modificators)
{

View File

@ -7,8 +7,9 @@
#include "Interactable.generated.h"
#define INTERACTABLE_DEBUG
//#define INTERACTABLE_DEBUG
//#define INTERACTABLE_ACTIVATOR_DEBUG
//#define INTERACTABLE_MODIFICATOR_DEBUG
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
enum class EActivatorType : uint8

View File

@ -51,6 +51,6 @@ void UActivateInteractableModificator::Unbind_Implementation()
void UActivateInteractableModificator::ActivateInteractable()
{
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 0, EInteractableHintWidgetAnimation::Click);
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 0, EInputAnimatedWidgetAnimation::Click);
OnActivated.Broadcast();
}

View File

@ -3,7 +3,7 @@
#include "EditInteractableModificator.h"
#include "../Interactable.h"
#include "Interactable/Interactable.h"
UEditInteractableModificator::UEditInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)

View File

@ -31,11 +31,10 @@ public:
virtual void Unbind_Implementation() {}
protected:
UPROPERTY(EditDefaultsOnly)
UPROPERTY(EditDefaultsOnly, NoClear)
TSoftObjectPtr<class UInputMappingContext> inputMapping;
UPROPERTY(EditAnywhere, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
UPROPERTY(EditDefaultsOnly, NoClear, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
int32 activatorTypes = 0;
};

View File

@ -99,30 +99,30 @@ void UMoveInteractableModificator::TurnOnHolding()
holding = true;
ProcessState();
distance = (player->GetCameraLocation() - actor->GetActorLocation()).Length();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 0, EInteractableHintWidgetAnimation::Hold);
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 0, EInputAnimatedWidgetAnimation::Hold);
OnHolding.Broadcast();
}
void UMoveInteractableModificator::TurnOffHolding()
{
holding = false;
ProcessState();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 0, EInteractableHintWidgetAnimation::Unhold);
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 0, EInputAnimatedWidgetAnimation::Unhold);
}
void UMoveInteractableModificator::TurnOnRotating()
{
rotating = true;
player->cameraLocked = true;
player->LockPlayer({ .camera = true });
ProcessState();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 1, EInteractableHintWidgetAnimation::Hold);
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 1, EInputAnimatedWidgetAnimation::Hold);
OnRotating.Broadcast();
}
void UMoveInteractableModificator::TurnOffRotating()
{
rotating = false;
player->cameraLocked = false;
player->UnlockPlayer({ .camera = true });
ProcessState();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 1, EInteractableHintWidgetAnimation::Unhold);
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 1, EInputAnimatedWidgetAnimation::Unhold);
}
void UMoveInteractableModificator::ProcessState()
@ -150,10 +150,24 @@ void UMoveInteractableModificator::UpdatePosition()
auto camLoc = player->GetCameraLocation();
auto dir = player->GetCameraDirection();
auto newLoc = camLoc + dir * distance;
//auto oldLoc = actor->GetActorLocation();
auto oldLoc = actor->GetActorLocation();
//auto interpLoc = FMath::VInterpTo(oldLoc, newLoc, GetWorld()->GetDeltaSeconds(), 20.0f);
//auto interpLoc = FMath::Lerp(oldLoc, newLoc, 0.5f);
actor->SetActorLocation(newLoc, true, nullptr, ETeleportType::None);
FHitResult hit;
actor->SetActorLocation(newLoc, true, &hit, ETeleportType::None);
static bool indicating = false;
if(hit.bBlockingHit && !indicating)
{
indicating = true;
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 0, EInputAnimatedWidgetAnimation::TurnOnIndication);
}
else if(!hit.bBlockingHit && indicating)
{
indicating = false;
AMainGameModeBase::GetWidgetsManager()->AnimateInteractionHint(this, 0, EInputAnimatedWidgetAnimation::TurnOffIndication);
}
}
void UMoveInteractableModificator::Zooming(const FInputActionValue& value)

View File

@ -3,7 +3,7 @@
#include "SawInteractableModificator.h"
#include "../Interactable.h"
#include "Interactable/Interactable.h"
USawInteractableModificator::USawInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)

View File

@ -9,39 +9,53 @@
#include "UObject/ScriptInterface.h"
#include "CustomGameInstanceBase.h"
#include "CutsceneManager.h"
#include "Widgets/WidgetsManager.h"
UWidgetsManager* AMainGameModeBase::_widgetsManager = nullptr;
UCutsceneManager* AMainGameModeBase::_cutsceneManager = nullptr;
void AMainGameModeBase::StartPlay()
{
_widgetsManager = NewObject<UWidgetsManager>(this, widgetManagerClass);
_cutsceneManager = NewObject<UCutsceneManager>(this);
AGameModeBase::StartPlay();
_widgetsManager = NewObject<UWidgetsManager>(this, widgetManagerClass);
_widgetsManager->Init();
}
void AMainGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
_cutsceneManager->LockCallback(true);
_cutsceneManager->ClearQueue();
}
bool AMainGameModeBase::SetPause(APlayerController* PC, FCanUnpause CanUnpauseDelegate)
{
if(_widgetsManager)
{
if(IsPaused())
{
_widgetsManager->HideOverlayWidgets();
_widgetsManager->HideWidgets();
}
else
{
_widgetsManager->ShowOverlayWidgets();
_widgetsManager->ShowWidgets();
}
}
return AGameModeBase::SetPause(PC, CanUnpauseDelegate);
}
UWidgetsManager* AMainGameModeBase::GetWidgetManager()
UWidgetsManager* AMainGameModeBase::GetWidgetsManager()
{
return _widgetsManager;
}
UCutsceneManager* AMainGameModeBase::GetCutsceneManager()
{
return _cutsceneManager;
}
void AMainGameModeBase::SwitchCameraMode()
{
@ -72,6 +86,6 @@ void AMainGameModeBase::SwitchCameraMode()
if(_widgetsManager)
{
_widgetsManager->UpdateOverlayWidgetsOwner();
_widgetsManager->UpdateWidgetsOwner();
}
}

View File

@ -14,11 +14,15 @@ class AMainGameModeBase : public AGameModeBase
public:
virtual void StartPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual bool SetPause(APlayerController* PC, FCanUnpause CanUnpauseDelegate = FCanUnpause()) override;
void SwitchCameraMode();
static class UWidgetsManager* GetWidgetManager();
UFUNCTION(BlueprintCallable)
static class UWidgetsManager* GetWidgetsManager();
UFUNCTION(BlueprintCallable)
static class UCutsceneManager* GetCutsceneManager();
protected:
UPROPERTY(EditDefaultsOnly)
@ -26,4 +30,5 @@ protected:
private:
static class UWidgetsManager* _widgetsManager;
static class UCutsceneManager* _cutsceneManager;
};

View File

@ -14,6 +14,7 @@
#include "CustomGameInstanceBase.h"
#include "CustomGameUserSettings.h"
#include "Interactable/Activators/InteractableActivator.h"
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "MainGameModeBase.h"
@ -87,26 +88,22 @@ void APlayerBase::BeginPlay()
LoadInteractablesActivators();
}
APlayerBase* APlayerBase::LockCamera(UWorld* world, bool locked)
void APlayerBase::LockPlayer(FPlayerLock lock)
{
if(auto PC = UGameplayStatics::GetPlayerController(world, 0))
{
if(auto pawn = Cast<APlayerBase>(PC->GetPawn()))
{
pawn->cameraLocked = locked;
return pawn;
}
}
return nullptr;
walkLocked += lock.walk;
jumpLocked += lock.jump;
runLocked += lock.run;
interactionLocked += lock.interaction;
cameraLocked += lock.camera;
}
void APlayerBase::AttachToCamera(AActor* actor)
void APlayerBase::UnlockPlayer(FPlayerLock lock)
{
if(!actor)
return;
actor->AttachToComponent(camera, FAttachmentTransformRules::KeepWorldTransform);
walkLocked -= lock.walk;
jumpLocked -= lock.jump;
runLocked -= lock.run;
interactionLocked -= lock.interaction;
cameraLocked -= lock.camera;
}
FVector APlayerBase::GetCameraDirection()
@ -142,7 +139,7 @@ void APlayerBase::MoveCamera(FVector2D value)
void APlayerBase::MoveCharacter(FVector2D value)
{
if(moveLocked)
if(walkLocked)
return;
moveVector = GetActorRightVector() * value.X;

View File

@ -2,16 +2,27 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Interactable/Interactable.h"
#include "PlayerBase.generated.h"
enum class EActivatorType : uint8;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPlayerMovedDelegate);
UCLASS()
USTRUCT(BlueprintType)
struct FPlayerLock
{
GENERATED_BODY()
uint8 walk : 1;
uint8 jump : 1;
uint8 run : 1;
uint8 interaction : 1;
uint8 camera : 1;
};
UCLASS(Blueprintable, BlueprintType)
class APlayerBase : public ACharacter
{
GENERATED_BODY()
@ -22,21 +33,18 @@ public:
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
static APlayerBase* LockCamera(UWorld* world, bool locked);
void AttachToCamera(AActor* actor);
FVector GetCameraLocation();
FVector GetCameraDirection();
bool IsMoving() { return isMoving; }
void LockPlayer(const FPlayerLock lock);
void UnlockPlayer(const FPlayerLock lock);
UPROPERTY(BlueprintAssignable)
FPlayerMovedDelegate OnPlayerMoved;
FVector moveVector;
class UEnhancedInputComponent* inputComponent;
UPROPERTY(EditAnywhere)
bool interactionLocked = false;
UPROPERTY(EditAnywhere)
bool cameraLocked = false;
protected:
virtual void BeginPlay() override;
@ -61,12 +69,16 @@ protected:
UPROPERTY(EditAnywhere)
float runSpeedMultiplier = 4;
UPROPERTY(EditAnywhere)
bool moveLocked = false;
UPROPERTY(EditAnywhere)
bool jumpLocked = false;
UPROPERTY(EditAnywhere)
bool runLocked = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
uint8 walkLocked = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
uint8 jumpLocked = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
uint8 runLocked = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
uint8 interactionLocked = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
uint8 cameraLocked = 0;
APlayerCameraManager* cameraManager;
class UCameraComponent* camera;
@ -80,8 +92,8 @@ protected:
private:
void LoadInteractablesActivators();
void InteractableActivated(AInteractable* interactable, EActivatorType type);
void InteractableDeactivated(AInteractable* interactable, EActivatorType type);
void InteractableActivated(class AInteractable* interactable, EActivatorType type);
void InteractableDeactivated(class AInteractable* interactable, EActivatorType type);
FVector oldLocation;
FRotator rotationInput;

View File

@ -0,0 +1,27 @@
// Oleg Petruny proprietary.
#pragma once
#include "InputAnimatedWidgetInterface.h"
#include "ResolutionResponsiveUserWidget.h"
#include "CutsceneSkipWidget.generated.h"
DECLARE_DYNAMIC_DELEGATE(FSkipCutsceneDelegate);
UCLASS(Blueprintable)
class UCutsceneSkipWidget : public UResolutionResponsiveUserWidget, public IInputAnimatedWidgetInterface
{
GENERATED_BODY()
public:
FSkipCutsceneDelegate skipCutsceneDelegate;
UPROPERTY(meta = (BindWidget))
class UTextBlock* keyText;
protected:
UFUNCTION(BlueprintCallable)
void SkipCutscene() { skipCutsceneDelegate.Execute(); }
};

View File

@ -0,0 +1,65 @@
// Oleg Petruny proprietary.
#pragma once
#include "UObject/Interface.h"
#include "InputAnimatedWidgetInterface.generated.h"
UENUM(BlueprintType)
enum class EInputAnimatedWidgetAnimation : uint8
{
Click,
Hold,
Unhold,
TurnOnIndication,
TurnOffIndication
};
UINTERFACE(MinimalAPI, Blueprintable)
class UInputAnimatedWidgetInterface : public UInterface
{
GENERATED_BODY()
};
class IInputAnimatedWidgetInterface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "InputAnimatedWidget")
void OnClick();
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "InputAnimatedWidget")
void OnHold();
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "InputAnimatedWidget")
void OnUnhold();
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "InputAnimatedWidget")
void OnTurnOnIndication();
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "InputAnimatedWidget")
void OnTurnOffIndication();
// Unsafe C++ shortcut
void RunAnimation(const EInputAnimatedWidgetAnimation animation)
{
switch(animation)
{
case EInputAnimatedWidgetAnimation::Click:
Execute_OnClick(this->_getUObject());
break;
case EInputAnimatedWidgetAnimation::Hold:
Execute_OnHold(this->_getUObject());
break;
case EInputAnimatedWidgetAnimation::Unhold:
Execute_OnUnhold(this->_getUObject());
break;
case EInputAnimatedWidgetAnimation::TurnOnIndication:
Execute_OnTurnOnIndication(this->_getUObject());
break;
case EInputAnimatedWidgetAnimation::TurnOffIndication:
Execute_OnTurnOffIndication(this->_getUObject());
break;
default:
break;
}
}
};

View File

@ -1,4 +0,0 @@
// Oleg Petruny proprietary.
#include "InteractableHintWidget.h"

View File

@ -2,34 +2,17 @@
#pragma once
#include "CoreMinimal.h"
#include "InputAnimatedWidgetInterface.h"
#include "ResolutionResponsiveUserWidget.h"
#include "InteractableHintWidget.generated.h"
UENUM(BlueprintType)
enum class EInteractableHintWidgetAnimation : uint8
{
Click,
Hold,
Unhold
};
UCLASS(Blueprintable)
class UInteractableHintWidget : public UResolutionResponsiveUserWidget
class UInteractableHintWidget : public UResolutionResponsiveUserWidget, public IInputAnimatedWidgetInterface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintImplementableEvent)
void OnClick();
UFUNCTION(BlueprintImplementableEvent)
void OnHold();
UFUNCTION(BlueprintImplementableEvent)
void OnUnhold();
UPROPERTY(meta = (BindWidget))
class UTextBlock* keyText;
UPROPERTY(meta = (BindWidget))

View File

@ -12,10 +12,16 @@
#include "Widgets/InteractableHintWidget.h"
void UInteractableHintWidgetManager::Append(const class UInteractableModificator* modificator)
void UInteractableHintWidgetManager::Append(const UInteractableModificator* modificator)
{
FScopeLock Lock(&hintsLock);
if(!modificator)
{
hints->SetVisibility(ESlateVisibility::Visible);
return;
}
if(hintsMap.Contains(modificator))
return;
@ -46,10 +52,16 @@ void UInteractableHintWidgetManager::Append(const class UInteractableModificator
hintsMap.Add(modificator, { count - mappings.Num() + skipped, mappings.Num() - skipped });
}
void UInteractableHintWidgetManager::Remove(const class UInteractableModificator* modificator)
void UInteractableHintWidgetManager::Remove(const UInteractableModificator* modificator)
{
FScopeLock Lock(&hintsLock);
if(!modificator)
{
hints->SetVisibility(ESlateVisibility::Hidden);
return;
}
if(!hintsMap.Contains(modificator))
return;
@ -66,8 +78,8 @@ void UInteractableHintWidgetManager::Remove(const class UInteractableModificator
hintsMap.Remove(modificator);
}
void UInteractableHintWidgetManager::AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index,
const EInteractableHintWidgetAnimation animation)
void UInteractableHintWidgetManager::AnimateInteractionHint(const UInteractableModificator* modificator, const int32 index,
const EInputAnimatedWidgetAnimation animation)
{
FScopeLock Lock(&hintsLock);
@ -76,18 +88,5 @@ void UInteractableHintWidgetManager::AnimateInteractionHint(const class UInterac
auto& indexAndCount = hintsMap[modificator];
auto hint = Cast<UInteractableHintWidget>(hints->GetChildAt(indexAndCount.Key + index));
switch(animation)
{
case EInteractableHintWidgetAnimation::Click:
hint->OnClick();
break;
case EInteractableHintWidgetAnimation::Hold:
hint->OnHold();
break;
case EInteractableHintWidgetAnimation::Unhold:
hint->OnUnhold();
break;
default:
break;
}
hint->RunAnimation(animation);
}

View File

@ -6,6 +6,8 @@
#include "InteractableHintWidgetManager.generated.h"
enum class EInputAnimatedWidgetAnimation : uint8;
UCLASS(Blueprintable)
class UInteractableHintWidgetManager : public UUserWidget
{
@ -14,7 +16,7 @@ class UInteractableHintWidgetManager : public UUserWidget
public:
void Append(const class UInteractableModificator* modificator);
void Remove(const class UInteractableModificator* modificator);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInteractableHintWidgetAnimation animation);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInputAnimatedWidgetAnimation animation);
protected:
UPROPERTY(EditDefaultsOnly)

View File

@ -4,6 +4,7 @@
#include "WidgetsManager.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "Engine/World.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
@ -13,6 +14,7 @@
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "InteractableHintWidgetManager.h"
#include "Widgets/CutsceneSkipWidget.h"
void UWidgetsManager::Init()
{
@ -37,66 +39,73 @@ void UWidgetsManager::Init()
if(auto instance = CreateWidget<UInteractableHintWidgetManager>(PC, interactableHintWidgetManagerClass))
{
interactableHintWidgetManager = instance;
instance->AddToViewport();
interactableHintWidgetManager->AddToViewport();
}
if(auto instance = CreateWidget<UCutsceneSkipWidget>(PC, cutsceneSkipWidgetClass))
{
cutsceneSkipWidget = instance;
cutsceneSkipWidget->SetVisibility(ESlateVisibility::Hidden);
cutsceneSkipWidget->AddToViewport();
}
}
}
void UWidgetsManager::HideOverlayWidgets()
void UWidgetsManager::HideWidgets()
{
for(auto& widget : overlayWidgetsInstances)
{
if(widget.IsValid())
{
widget->SetVisibility(ESlateVisibility::Hidden);
}
}
if(interactableHintWidgetManager)
interactableHintWidgetManager->Remove(nullptr);
}
void UWidgetsManager::ShowOverlayWidgets()
void UWidgetsManager::ShowWidgets()
{
for(auto& widget : overlayWidgetsInstances)
{
if(widget.IsValid())
{
widget->SetVisibility(ESlateVisibility::Visible);
}
}
if(interactableHintWidgetManager)
interactableHintWidgetManager->Append(nullptr);
}
void UWidgetsManager::UpdateOverlayWidgetsOwner()
void UWidgetsManager::UpdateWidgetsOwner()
{
if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{
for(auto& widget : permaOverlayWidgetsInstances)
{
if(widget.IsValid())
{
widget->SetOwningPlayer(PC);
}
}
for(auto& widget : overlayWidgetsInstances)
{
if(widget.IsValid())
{
widget->SetOwningPlayer(PC);
}
}
}
}
void UWidgetsManager::ShowInteractionHints(const UInteractableModificator* modificator)
{
if(interactableHintWidgetManager.IsValid())
if(interactableHintWidgetManager)
interactableHintWidgetManager->Append(modificator);
}
void UWidgetsManager::HideInteractionHints(const UInteractableModificator* modificator)
{
if(interactableHintWidgetManager.IsValid())
if(interactableHintWidgetManager)
interactableHintWidgetManager->Remove(modificator);
}
void UWidgetsManager::AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInteractableHintWidgetAnimation animation)
void UWidgetsManager::AnimateInteractionHint(const UInteractableModificator* modificator, const int32 index, const EInputAnimatedWidgetAnimation animation)
{
if(interactableHintWidgetManager.IsValid())
if(interactableHintWidgetManager)
interactableHintWidgetManager->AnimateInteractionHint(modificator, index, animation);
}
void UWidgetsManager::EnableCutsceneWidget(FText keyText, FSkipCutsceneDelegate& skipCutsceneDelegate)
{
cutsceneSkipWidget->keyText->SetText(keyText);
cutsceneSkipWidget->skipCutsceneDelegate = skipCutsceneDelegate;
cutsceneSkipWidget->SetVisibility(ESlateVisibility::Visible);
}
void UWidgetsManager::DisableCutsceneWidget()
{
cutsceneSkipWidget->SetVisibility(ESlateVisibility::Hidden);
}
void UWidgetsManager::AnimateCutsceneWidget(const EInputAnimatedWidgetAnimation animation)
{
cutsceneSkipWidget->RunAnimation(animation);
}

View File

@ -2,12 +2,11 @@
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "WidgetsManager.generated.h"
enum class EInteractableHintWidgetAnimation : uint8;
enum class EInputAnimatedWidgetAnimation : uint8;
UCLASS(Blueprintable)
class UWidgetsManager : public UObject
@ -17,24 +16,32 @@ class UWidgetsManager : public UObject
public:
void Init();
void HideOverlayWidgets();
void ShowOverlayWidgets();
void UpdateOverlayWidgetsOwner();
void ShowWidgets();
void HideWidgets();
void UpdateWidgetsOwner();
void ShowInteractionHints(const class UInteractableModificator* modificator);
void HideInteractionHints(const class UInteractableModificator* modificator);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInteractableHintWidgetAnimation animation);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInputAnimatedWidgetAnimation animation);
void EnableCutsceneWidget(FText keyText, class FSkipCutsceneDelegate& skipCutsceneDelegate);
void DisableCutsceneWidget();
void AnimateCutsceneWidget(const EInputAnimatedWidgetAnimation animation);
protected:
UPROPERTY(EditDefaultsOnly)
TSet<TSubclassOf<class UUserWidget>> permaOverlayWidgets; // never hidden
TArray<TWeakObjectPtr<class UUserWidget>> permaOverlayWidgetsInstances;
TArray<class UUserWidget*> permaOverlayWidgetsInstances;
UPROPERTY(EditDefaultsOnly)
TSet<TSubclassOf<class UUserWidget>> overlayWidgets; // hidden in pause
TArray<TWeakObjectPtr<class UUserWidget>> overlayWidgetsInstances;
TArray<class UUserWidget*> overlayWidgetsInstances;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidgetManager> interactableHintWidgetManagerClass;
TWeakObjectPtr<class UInteractableHintWidgetManager> interactableHintWidgetManager;
class UInteractableHintWidgetManager* interactableHintWidgetManager = nullptr;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UCutsceneSkipWidget> cutsceneSkipWidgetClass;
class UCutsceneSkipWidget* cutsceneSkipWidget = nullptr;
};