// Fill out your copyright notice in the Description page of Project Settings. #include "SettingsMenuWidget.h" #include "Components/Button.h" #include "Components/WidgetSwitcher.h" #include "ConfirmDialogWidget.h" #include "InputCoreTypes.h" #include "SettingsTabWidget.h" #include "SurvivalUserSettings.h" #define LOCTEXT_NAMESPACE "Reglages" namespace { // Ordre des pages dans le WidgetSwitcher. Les trois dernieres n'existent pas // encore : leur bouton se grise tout seul tant que la page est absente. constexpr int32 TabIndexGameplay = 0; constexpr int32 TabIndexDisplay = 1; constexpr int32 TabIndexGraphics = 2; constexpr int32 TabIndexAudio = 3; } USettingsMenuWidget::USettingsMenuWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { // Sans ce drapeau le widget ne peut pas prendre le focus clavier, et // NativeOnKeyDown ne serait jamais appele. Il ne se change qu'a la // construction, d'ou sa presence ici et pas dans Open(). SetIsFocusable(true); ResetDialogMessage = LOCTEXT("ResetConfirm", "Réinitialiser cet onglet ?"); } void USettingsMenuWidget::NativeConstruct() { Super::NativeConstruct(); if (BackButton) { BackButton->OnClicked.AddDynamic(this, &USettingsMenuWidget::HandleBackClicked); } if (ResetButton) { ResetButton->OnClicked.AddDynamic(this, &USettingsMenuWidget::HandleResetClicked); } if (GameplayTabButton) { GameplayTabButton->OnClicked.AddDynamic(this, &USettingsMenuWidget::HandleGameplayTabClicked); } if (DisplayTabButton) { DisplayTabButton->OnClicked.AddDynamic(this, &USettingsMenuWidget::HandleDisplayTabClicked); } if (GraphicsTabButton) { GraphicsTabButton->OnClicked.AddDynamic(this, &USettingsMenuWidget::HandleGraphicsTabClicked); } if (AudioTabButton) { AudioTabButton->OnClicked.AddDynamic(this, &USettingsMenuWidget::HandleAudioTabClicked); } if (ResetDialog) { ResetDialog->OnConfirmed.AddDynamic(this, &USettingsMenuWidget::HandleResetConfirmed); ResetDialog->OnCancelled.AddDynamic(this, &USettingsMenuWidget::HandleResetCancelled); ResetDialog->Close(); } UpdateTabButtonStates(); } void USettingsMenuWidget::NativeDestruct() { if (BackButton) { BackButton->OnClicked.RemoveDynamic(this, &USettingsMenuWidget::HandleBackClicked); } if (ResetButton) { ResetButton->OnClicked.RemoveDynamic(this, &USettingsMenuWidget::HandleResetClicked); } Super::NativeDestruct(); } void USettingsMenuWidget::Open() { SetVisibility(ESlateVisibility::Visible); // L'ecran a pu etre ouvert, referme, puis rouvert apres un changement fait // ailleurs : on relit toujours plutot que de faire confiance a l'affichage. if (USettingsTabWidget* ActiveTab = GetActiveTab()) { ActiveTab->RefreshFromSettings(); } // Le focus doit etre repris a CHAQUE ouverture, sinon Echap reste sans effet. SetKeyboardFocus(); } void USettingsMenuWidget::Close() { if (ResetDialog) { ResetDialog->Close(); } bResetDialogOpen = false; SetVisibility(ESlateVisibility::Collapsed); // La sauvegarde a lieu ici et pas a chaque clic de fleche : ecrire le .ini // vingt fois pendant qu'on cherche la bonne sensibilite ne sert a rien. if (USurvivalUserSettings* Settings = USurvivalUserSettings::Get()) { Settings->SaveSettings(); } } FReply USettingsMenuWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) { const FKey Key = InKeyEvent.GetKey(); if (Key == EKeys::Escape) { // La boite de confirmation gere Echap elle-meme quand elle a le focus. // Si elle l'a perdu, on annule ici plutot que de fermer tout l'ecran en // laissant la question affichee. if (bResetDialogOpen) { HandleResetCancelled(); return FReply::Handled(); } OnCloseRequested.Broadcast(); // Handled : sans ca la touche continue de remonter et le menu de pause // la consommerait une seconde fois. return FReply::Handled(); } return Super::NativeOnKeyDown(InGeometry, InKeyEvent); } USettingsTabWidget* USettingsMenuWidget::GetActiveTab() const { return TabSwitcher ? Cast(TabSwitcher->GetActiveWidget()) : nullptr; } void USettingsMenuWidget::ShowTab(int32 Index) { if (!TabSwitcher || Index < 0 || Index >= TabSwitcher->GetNumWidgets()) { return; } TabSwitcher->SetActiveWidgetIndex(Index); if (USettingsTabWidget* ActiveTab = GetActiveTab()) { ActiveTab->RefreshFromSettings(); } } void USettingsMenuWidget::UpdateTabButtonStates() { const int32 PageCount = TabSwitcher ? TabSwitcher->GetNumWidgets() : 0; if (GameplayTabButton) { GameplayTabButton->SetIsEnabled(PageCount > TabIndexGameplay); } if (DisplayTabButton) { DisplayTabButton->SetIsEnabled(PageCount > TabIndexDisplay); } if (GraphicsTabButton) { GraphicsTabButton->SetIsEnabled(PageCount > TabIndexGraphics); } if (AudioTabButton) { AudioTabButton->SetIsEnabled(PageCount > TabIndexAudio); } } void USettingsMenuWidget::HandleBackClicked() { OnCloseRequested.Broadcast(); } void USettingsMenuWidget::HandleResetClicked() { // Sans boite assignee on ne bloque pas le joueur : on reinitialise. if (!ResetDialog) { HandleResetConfirmed(); return; } bResetDialogOpen = true; ResetDialog->Open(ResetDialogMessage); } void USettingsMenuWidget::HandleResetConfirmed() { bResetDialogOpen = false; if (ResetDialog) { ResetDialog->Close(); } // Uniquement l'onglet visible : un "Reinitialiser" qui remettrait aussi la // resolution et le volume serait une mauvaise surprise. if (USettingsTabWidget* ActiveTab = GetActiveTab()) { ActiveTab->ResetToDefaults(); } SetKeyboardFocus(); } void USettingsMenuWidget::HandleResetCancelled() { bResetDialogOpen = false; if (ResetDialog) { ResetDialog->Close(); } SetKeyboardFocus(); } void USettingsMenuWidget::HandleGameplayTabClicked() { ShowTab(TabIndexGameplay); } void USettingsMenuWidget::HandleDisplayTabClicked() { ShowTab(TabIndexDisplay); } void USettingsMenuWidget::HandleGraphicsTabClicked() { ShowTab(TabIndexGraphics); } void USettingsMenuWidget::HandleAudioTabClicked() { ShowTab(TabIndexAudio); } #undef LOCTEXT_NAMESPACE