174 lines
4.5 KiB
C++
174 lines
4.5 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "KeyCaptureWidget.h"
|
|
|
|
#include "Components/Button.h"
|
|
#include "Components/TextBlock.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "Reglages"
|
|
|
|
UKeyCaptureWidget::UKeyCaptureWidget(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
// Sans ce drapeau le widget ne peut pas prendre le focus clavier, et
|
|
// NativeOnKeyDown ne serait jamais appele -- le voile resterait affiche sans
|
|
// jamais rien capturer. Meme piege que UConfirmDialogWidget.
|
|
SetIsFocusable(true);
|
|
|
|
PromptFormat = LOCTEXT("CapturePrompt", "Appuie sur une touche pour « {0} »\nÉchap pour annuler");
|
|
}
|
|
|
|
void UKeyCaptureWidget::NativeOnInitialized()
|
|
{
|
|
Super::NativeOnInitialized();
|
|
|
|
if (ConfirmButton)
|
|
{
|
|
ConfirmButton->OnClicked.AddDynamic(this, &UKeyCaptureWidget::HandleConfirmClicked);
|
|
}
|
|
|
|
if (CancelButton)
|
|
{
|
|
CancelButton->OnClicked.AddDynamic(this, &UKeyCaptureWidget::HandleCancelClicked);
|
|
}
|
|
}
|
|
|
|
void UKeyCaptureWidget::BeginCapture(const FText& ActionLabel)
|
|
{
|
|
State = EKeyCaptureState::Capturing;
|
|
|
|
if (PromptText)
|
|
{
|
|
PromptText->SetText(FText::Format(PromptFormat, ActionLabel));
|
|
}
|
|
|
|
UpdateButtonVisibility();
|
|
|
|
SetVisibility(ESlateVisibility::Visible);
|
|
|
|
// Le focus se reprend a CHAQUE ouverture : le refermer le rend a l'ecran de
|
|
// reglages, et un voile visible mais sans focus ignorerait le clavier.
|
|
SetKeyboardFocus();
|
|
}
|
|
|
|
void UKeyCaptureWidget::ShowConflict(const FText& Message)
|
|
{
|
|
State = EKeyCaptureState::Conflict;
|
|
|
|
if (PromptText)
|
|
{
|
|
PromptText->SetText(Message);
|
|
}
|
|
|
|
UpdateButtonVisibility();
|
|
|
|
// Le voile n'a pas bouge, mais le focus a pu partir sur un bouton qui vient
|
|
// d'apparaitre : on le reprend pour qu'Echap continue de repondre.
|
|
SetKeyboardFocus();
|
|
}
|
|
|
|
void UKeyCaptureWidget::EndCapture()
|
|
{
|
|
State = EKeyCaptureState::Idle;
|
|
|
|
UpdateButtonVisibility();
|
|
SetVisibility(ESlateVisibility::Collapsed);
|
|
}
|
|
|
|
void UKeyCaptureWidget::UpdateButtonVisibility()
|
|
{
|
|
// Collapsed et non Hidden : replies, les boutons ne doivent pas reserver la
|
|
// place qu'ils occuperont, sinon la consigne de capture serait decentree.
|
|
const ESlateVisibility ButtonVisibility = State == EKeyCaptureState::Conflict
|
|
? ESlateVisibility::Visible
|
|
: ESlateVisibility::Collapsed;
|
|
|
|
if (ConfirmButton)
|
|
{
|
|
ConfirmButton->SetVisibility(ButtonVisibility);
|
|
}
|
|
|
|
if (CancelButton)
|
|
{
|
|
CancelButton->SetVisibility(ButtonVisibility);
|
|
}
|
|
}
|
|
|
|
FReply UKeyCaptureWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
|
|
{
|
|
const FKey Key = InKeyEvent.GetKey();
|
|
|
|
if (State == EKeyCaptureState::Conflict)
|
|
{
|
|
// Echap vaut Annuler, comme partout ailleurs dans les menus.
|
|
if (Key == EKeys::Escape)
|
|
{
|
|
OnConflictAnswered.Broadcast(false);
|
|
}
|
|
|
|
// Aucune autre touche n'est lue : on ne capture plus, on attend une
|
|
// reponse. Sans ce garde-fou, appuyer sur une touche pour "repondre"
|
|
// relancerait un remappage a l'insu du joueur.
|
|
return FReply::Handled();
|
|
}
|
|
|
|
return CaptureKey(Key);
|
|
}
|
|
|
|
FReply UKeyCaptureWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
|
|
{
|
|
if (State == EKeyCaptureState::Conflict)
|
|
{
|
|
// Les clics sur les boutons ne remontent pas jusqu'ici, ils sont traites
|
|
// avant. Tout le reste est avale pour garder le voile modal.
|
|
return FReply::Handled();
|
|
}
|
|
|
|
// La souris passe par le meme chemin que le clavier : Souris 4 et Souris 5
|
|
// sont des touches comme les autres pour Enhanced Input.
|
|
return CaptureKey(InMouseEvent.GetEffectingButton());
|
|
}
|
|
|
|
FReply UKeyCaptureWidget::CaptureKey(const FKey& Key)
|
|
{
|
|
if (Key == EKeys::Escape)
|
|
{
|
|
OnCaptureCancelled.Broadcast();
|
|
return FReply::Handled();
|
|
}
|
|
|
|
// Les touches de modification seules ne sont pas capturees : Enhanced Input
|
|
// les traite comme des touches a part entiere, mais assigner "Maj" tout court
|
|
// rendrait inutilisable toute combinaison la contenant.
|
|
if (Key.IsModifierKey())
|
|
{
|
|
return FReply::Handled();
|
|
}
|
|
|
|
// Un axe analogique n'est pas assignable a une action Digital : on ignore
|
|
// plutot que de laisser MapPlayerKey echouer plus loin sans explication.
|
|
if (Key.IsAxis1D() || Key.IsAxis2D() || Key.IsAxis3D())
|
|
{
|
|
return FReply::Handled();
|
|
}
|
|
|
|
OnKeyCaptured.Broadcast(Key);
|
|
|
|
// Handled dans tous les cas : le voile est modal, rien ne doit passer a
|
|
// travers pendant qu'il attend une touche.
|
|
return FReply::Handled();
|
|
}
|
|
|
|
void UKeyCaptureWidget::HandleConfirmClicked()
|
|
{
|
|
OnConflictAnswered.Broadcast(true);
|
|
}
|
|
|
|
void UKeyCaptureWidget::HandleCancelClicked()
|
|
{
|
|
OnConflictAnswered.Broadcast(false);
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|