// Fill out your copyright notice in the Description page of Project Settings. #include "SettingRowWidget.h" #include "Components/Button.h" #include "Components/ProgressBar.h" #include "Components/TextBlock.h" void USettingRowWidget::NativeOnInitialized() { Super::NativeOnInitialized(); // NativeOnInitialized et non NativeConstruct : l'onglet parent appelle // SetupAs... depuis SON NativeConstruct, et rien ne garantit l'ordre entre // le construct du parent et celui de ses enfants. Initialize, lui, tourne // une seule fois a la creation de l'arbre, avant tout le monde. if (LeftArrowButton) { LeftArrowButton->OnClicked.AddDynamic(this, &USettingRowWidget::HandleLeftClicked); } if (RightArrowButton) { RightArrowButton->OnClicked.AddDynamic(this, &USettingRowWidget::HandleRightClicked); } } void USettingRowWidget::SetupAsChoice(const FText& Label, const TArray& Options, int32 Index) { bNumeric = false; ChoiceLabels = Options; StepCount = FMath::Max(Options.Num(), 1); CurrentIndex = FMath::Clamp(Index, 0, StepCount - 1); if (LabelText) { LabelText->SetText(Label); } // Une barre de remplissage sur "Maintien / Bascule" ne veut rien dire : elle // serait vide ou pleine sans que ca informe de quoi que ce soit. On la // masque plutot que d'imposer un second WBP juste pour les choix. if (ValueBar) { ValueBar->SetVisibility(ESlateVisibility::Collapsed); } Refresh(); } void USettingRowWidget::SetupAsNumber(const FText& Label, float Min, float Max, float Step, float Value, const FText& Suffix) { bNumeric = true; ChoiceLabels.Reset(); NumericMin = Min; NumericStep = FMath::Max(Step, KINDA_SMALL_NUMBER); NumericSuffix = Suffix; // +1 : les deux extremites comptent. 70 a 120 par 5 fait 11 paliers, pas 10. StepCount = FMath::Max(FMath::FloorToInt((Max - Min) / NumericStep) + 1, 1); if (LabelText) { LabelText->SetText(Label); } // HitTestInvisible et non Visible : la barre est un decor, elle ne doit pas // intercepter les clics destines aux fleches qui l'encadrent. if (ValueBar) { ValueBar->SetVisibility(ESlateVisibility::HitTestInvisible); } SetNumericValueSilently(Value); } float USettingRowWidget::GetNumericValue() const { return NumericMin + CurrentIndex * NumericStep; } void USettingRowWidget::SetIndexSilently(int32 NewIndex) { CurrentIndex = FMath::Clamp(NewIndex, 0, StepCount - 1); Refresh(); } void USettingRowWidget::SetNumericValueSilently(float Value) { SetIndexSilently(FMath::RoundToInt((Value - NumericMin) / NumericStep)); } void USettingRowWidget::HandleLeftClicked() { StepIndex(-1); } void USettingRowWidget::HandleRightClicked() { StepIndex(1); } void USettingRowWidget::StepIndex(int32 Delta) { const int32 NewIndex = FMath::Clamp(CurrentIndex + Delta, 0, StepCount - 1); // Pas de bouclage, volontairement : passer de 100 a 5 de sensibilite d'un // clic de trop rendrait le jeu injouable sans qu'on comprenne pourquoi. if (NewIndex == CurrentIndex) { return; } CurrentIndex = NewIndex; Refresh(); OnIndexChanged.Broadcast(CurrentIndex); } void USettingRowWidget::Refresh() { if (ValueText) { if (bNumeric) { FNumberFormattingOptions Format; Format.MaximumFractionalDigits = 0; const FText Number = FText::AsNumber(GetNumericValue(), &Format); // FormatOrdered plutot qu'une concatenation : selon la langue, l'unite // ne se colle pas forcement du meme cote ni avec la meme espace. ValueText->SetText(NumericSuffix.IsEmpty() ? Number : FText::FormatOrdered(NSLOCTEXT("Reglages", "ValeurAvecUnite", "{0}{1}"), Number, NumericSuffix)); } else if (ChoiceLabels.IsValidIndex(CurrentIndex)) { ValueText->SetText(ChoiceLabels[CurrentIndex]); } } if (ValueBar) { // Un seul palier : la barre n'a aucun sens, on la remplit entierement // plutot que de diviser par zero. ValueBar->SetPercent(StepCount > 1 ? static_cast(CurrentIndex) / static_cast(StepCount - 1) : 1.f); } // Les fleches se grisent aux extremites : le joueur voit qu'il est au bout // au lieu de cliquer dans le vide. if (LeftArrowButton) { LeftArrowButton->SetIsEnabled(CurrentIndex > 0); } if (RightArrowButton) { RightArrowButton->SetIsEnabled(CurrentIndex < StepCount - 1); } }