624 lines
25 KiB
C++
624 lines
25 KiB
C++
// Copyright Pacificao. All Rights Reserved.
|
|
|
|
#include "AgrarianMvpFrontendWidget.h"
|
|
|
|
#include "Blueprint/WidgetTree.h"
|
|
#include "Components/Border.h"
|
|
#include "Components/Button.h"
|
|
#include "Components/ButtonSlot.h"
|
|
#include "Components/HorizontalBox.h"
|
|
#include "Components/HorizontalBoxSlot.h"
|
|
#include "Components/SizeBox.h"
|
|
#include "Components/Slider.h"
|
|
#include "Components/TextBlock.h"
|
|
#include "Components/VerticalBox.h"
|
|
#include "Components/VerticalBoxSlot.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
#include "InputCoreTypes.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "Styling/CoreStyle.h"
|
|
#include "TimerManager.h"
|
|
|
|
namespace
|
|
{
|
|
FButtonStyle MakeAgrarianButtonStyle(const FLinearColor& NormalColor, const FLinearColor& HoveredColor)
|
|
{
|
|
FButtonStyle ButtonStyle = FCoreStyle::Get().GetWidgetStyle<FButtonStyle>(TEXT("Button"));
|
|
ButtonStyle.Normal.TintColor = FSlateColor(NormalColor);
|
|
ButtonStyle.Hovered.TintColor = FSlateColor(HoveredColor);
|
|
ButtonStyle.Pressed.TintColor = FSlateColor(FLinearColor(
|
|
FMath::Min(HoveredColor.R + 0.12f, 1.0f),
|
|
FMath::Min(HoveredColor.G + 0.12f, 1.0f),
|
|
FMath::Min(HoveredColor.B + 0.12f, 1.0f),
|
|
HoveredColor.A));
|
|
return ButtonStyle;
|
|
}
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::NativeConstruct()
|
|
{
|
|
Super::NativeConstruct();
|
|
SetIsFocusable(true);
|
|
RebuildFrontendTree();
|
|
FocusPrimaryButton();
|
|
}
|
|
|
|
FReply UAgrarianMvpFrontendWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
|
|
{
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
|
|
{
|
|
const FKey Key = InKeyEvent.GetKey();
|
|
if (Key == EKeys::Left || Key == EKeys::A)
|
|
{
|
|
PlayUiSound(UiSelectionSound);
|
|
SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultMale);
|
|
return FReply::Handled();
|
|
}
|
|
|
|
if (Key == EKeys::Right || Key == EKeys::D)
|
|
{
|
|
PlayUiSound(UiSelectionSound);
|
|
SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultFemale);
|
|
return FReply::Handled();
|
|
}
|
|
|
|
if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
|
|
{
|
|
PlayUiSound(UiConfirmSound);
|
|
ConfirmActiveScreen();
|
|
return FReply::Handled();
|
|
}
|
|
}
|
|
else if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
|
|
{
|
|
const FKey Key = InKeyEvent.GetKey();
|
|
if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
|
|
{
|
|
PlayUiSound(UiConfirmSound);
|
|
ConfirmActiveScreen();
|
|
return FReply::Handled();
|
|
}
|
|
|
|
if (Key == EKeys::BackSpace || Key == EKeys::Escape)
|
|
{
|
|
PlayUiSound(UiBackSound);
|
|
BackFromActiveScreen();
|
|
return FReply::Handled();
|
|
}
|
|
}
|
|
else if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
|
|
{
|
|
const FKey Key = InKeyEvent.GetKey();
|
|
if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
|
|
{
|
|
PlayUiSound(UiConfirmSound);
|
|
ConfirmActiveScreen();
|
|
return FReply::Handled();
|
|
}
|
|
}
|
|
else if (ActiveScreen == EAgrarianMvpFrontendScreen::MainMenu)
|
|
{
|
|
const FKey Key = InKeyEvent.GetKey();
|
|
if (Key == EKeys::Enter || Key == EKeys::SpaceBar || Key == EKeys::Escape)
|
|
{
|
|
PlayUiSound(UiConfirmSound);
|
|
ConfirmActiveScreen();
|
|
return FReply::Handled();
|
|
}
|
|
|
|
if (Key == EKeys::Q)
|
|
{
|
|
PlayUiSound(UiSaveQuitSound);
|
|
SaveAndQuit();
|
|
return FReply::Handled();
|
|
}
|
|
}
|
|
else if (ActiveScreen == EAgrarianMvpFrontendScreen::SavingAndQuit)
|
|
{
|
|
return FReply::Handled();
|
|
}
|
|
|
|
return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::SetActiveScreen(EAgrarianMvpFrontendScreen NewScreen)
|
|
{
|
|
ActiveScreen = NewScreen;
|
|
RebuildFrontendTree();
|
|
FocusPrimaryButton();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype NewArchetype)
|
|
{
|
|
SelectedCharacterArchetype = NewArchetype;
|
|
RebuildFrontendTree();
|
|
FocusPrimaryButton();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::SetUiScale(float NewUiScale)
|
|
{
|
|
UiScale = FMath::Clamp(NewUiScale, 0.75f, 1.5f);
|
|
RebuildFrontendTree();
|
|
FocusPrimaryButton();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::SetHighContrastMode(bool bNewUseHighContrast)
|
|
{
|
|
bUseHighContrast = bNewUseHighContrast;
|
|
RebuildFrontendTree();
|
|
FocusPrimaryButton();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::ConfirmActiveScreen()
|
|
{
|
|
ContinueFromActiveScreen();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::BackFromActiveScreen()
|
|
{
|
|
ReturnFromActiveScreen();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::SaveAndQuit()
|
|
{
|
|
SetActiveScreen(EAgrarianMvpFrontendScreen::SavingAndQuit);
|
|
if (UWorld* World = GetWorld())
|
|
{
|
|
FTimerHandle SaveAndQuitTimerHandle;
|
|
World->GetTimerManager().SetTimer(SaveAndQuitTimerHandle, this, &UAgrarianMvpFrontendWidget::ExecuteSaveAndQuit, 0.35f, false);
|
|
return;
|
|
}
|
|
|
|
ExecuteSaveAndQuit();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::ExecuteSaveAndQuit()
|
|
{
|
|
if (APlayerController* PlayerController = GetOwningPlayer())
|
|
{
|
|
PlayerController->ConsoleCommand(TEXT("AgrarianSaveWorld"));
|
|
PlayerController->ConsoleCommand(TEXT("quit"));
|
|
}
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::ContinueFromActiveScreen()
|
|
{
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
|
|
{
|
|
SetActiveScreen(EAgrarianMvpFrontendScreen::JoinServer);
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
|
|
{
|
|
SetActiveScreen(EAgrarianMvpFrontendScreen::Loading);
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
|
|
{
|
|
CompleteFrontendFlow();
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::SavingAndQuit)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::MainMenu)
|
|
{
|
|
CompleteFrontendFlow();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::ReturnFromActiveScreen()
|
|
{
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
|
|
{
|
|
SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::MainMenu)
|
|
{
|
|
CompleteFrontendFlow();
|
|
}
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::CompleteFrontendFlow()
|
|
{
|
|
if (APlayerController* PlayerController = GetOwningPlayer())
|
|
{
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
|
|
{
|
|
PlayerController->ConsoleCommand(SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale
|
|
? TEXT("AgrarianSelectCharacter female")
|
|
: TEXT("AgrarianSelectCharacter male"));
|
|
}
|
|
|
|
PlayerController->SetInputMode(FInputModeGameOnly());
|
|
PlayerController->bShowMouseCursor = false;
|
|
PlayerController->SetIgnoreMoveInput(false);
|
|
PlayerController->SetIgnoreLookInput(false);
|
|
}
|
|
|
|
RemoveFromParent();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::RebuildFrontendTree()
|
|
{
|
|
if (!WidgetTree)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PrimaryFocusButton = nullptr;
|
|
|
|
const float Scale = FMath::Clamp(UiScale, 0.75f, 1.5f);
|
|
const FLinearColor BackdropColor = bUseHighContrast ? FLinearColor::Black : FLinearColor(0.015f, 0.018f, 0.014f, 0.99f);
|
|
const FLinearColor PanelColor = bUseHighContrast ? FLinearColor(0.0f, 0.0f, 0.0f, 0.98f) : FLinearColor(0.035f, 0.045f, 0.034f, 0.96f);
|
|
const FLinearColor AccentColor = bUseHighContrast ? FLinearColor(0.95f, 0.95f, 0.30f, 1.0f) : FLinearColor(0.45f, 0.72f, 0.40f, 1.0f);
|
|
const FLinearColor TextColor = bUseHighContrast ? FLinearColor::White : FLinearColor(0.92f, 0.98f, 0.84f, 1.0f);
|
|
const FLinearColor MutedTextColor = bUseHighContrast ? FLinearColor(0.86f, 0.86f, 0.66f, 1.0f) : FLinearColor(0.72f, 0.80f, 0.68f, 1.0f);
|
|
const FLinearColor ButtonColor = bUseHighContrast ? FLinearColor(0.30f, 0.30f, 0.02f, 1.0f) : FLinearColor(0.22f, 0.40f, 0.18f, 0.98f);
|
|
const FLinearColor ButtonHoverColor = bUseHighContrast ? FLinearColor(0.48f, 0.48f, 0.08f, 1.0f) : FLinearColor(0.35f, 0.58f, 0.30f, 1.0f);
|
|
const FLinearColor SecondaryButtonColor = bUseHighContrast ? FLinearColor(0.12f, 0.12f, 0.12f, 1.0f) : FLinearColor(0.10f, 0.13f, 0.09f, 0.98f);
|
|
const FLinearColor QuitButtonColor = bUseHighContrast ? FLinearColor(0.32f, 0.10f, 0.08f, 1.0f) : FLinearColor(0.42f, 0.22f, 0.18f, 0.98f);
|
|
|
|
UBorder* RootBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("MvpFrontendRoot"));
|
|
RootBorder->SetBrushColor(BackdropColor);
|
|
RootBorder->SetPadding(FMargin(24.0f * Scale));
|
|
RootBorder->SetHorizontalAlignment(HAlign_Center);
|
|
RootBorder->SetVerticalAlignment(VAlign_Center);
|
|
WidgetTree->RootWidget = RootBorder;
|
|
|
|
USizeBox* PanelSizeBox = WidgetTree->ConstructWidget<USizeBox>(USizeBox::StaticClass(), TEXT("MvpFrontendPanelSize"));
|
|
PanelSizeBox->SetWidthOverride(780.0f * Scale);
|
|
PanelSizeBox->SetMinDesiredWidth(420.0f);
|
|
PanelSizeBox->SetMinDesiredHeight(300.0f);
|
|
RootBorder->SetContent(PanelSizeBox);
|
|
|
|
UBorder* PanelBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("MvpFrontendPanel"));
|
|
PanelBorder->SetBrushColor(PanelColor);
|
|
PanelBorder->SetPadding(FMargin(42.0f * Scale, 34.0f * Scale));
|
|
PanelSizeBox->SetContent(PanelBorder);
|
|
|
|
UVerticalBox* Panel = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("MvpFrontendStack"));
|
|
PanelBorder->SetContent(Panel);
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::MainMenu)
|
|
{
|
|
AddText(Panel, FText::FromString(TEXT("Pause Menu")), FMath::RoundToInt(20.0f * Scale), true, AccentColor, 6.0f * Scale);
|
|
AddText(Panel, MainMenuTitle, FMath::RoundToInt(54.0f * Scale), true, TextColor, 6.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Gameplay is paused while this menu is active.")), FMath::RoundToInt(22.0f * Scale), false, MutedTextColor, 72.0f * Scale);
|
|
PrimaryFocusButton = AddButton(Panel, FText::FromString(TEXT("Resume")), ButtonColor, ButtonHoverColor, 16.0f * Scale);
|
|
PrimaryFocusButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandlePrimaryActionClicked);
|
|
PrimaryFocusButton->OnHovered.AddDynamic(this, &UAgrarianMvpFrontendWidget::FocusPrimaryButton);
|
|
|
|
UButton* QuitButton = AddButton(Panel, FText::FromString(TEXT("Save & Quit")), QuitButtonColor, FLinearColor(0.58f, 0.28f, 0.22f, 1.0f), 34.0f * Scale);
|
|
QuitButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleSaveAndQuitClicked);
|
|
AddText(Panel, FText::FromString(TEXT("Audio")), FMath::RoundToInt(18.0f * Scale), true, AccentColor, 8.0f * Scale);
|
|
if (USlider* Slider = AddVolumeSlider(Panel, FText::FromString(TEXT("Master")), MasterVolume, 8.0f * Scale))
|
|
{
|
|
Slider->OnValueChanged.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleMasterVolumeChanged);
|
|
}
|
|
if (USlider* Slider = AddVolumeSlider(Panel, FText::FromString(TEXT("Ambient")), AmbientVolume, 8.0f * Scale))
|
|
{
|
|
Slider->OnValueChanged.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleAmbientVolumeChanged);
|
|
}
|
|
if (USlider* Slider = AddVolumeSlider(Panel, FText::FromString(TEXT("Weather")), WeatherVolume, 8.0f * Scale))
|
|
{
|
|
Slider->OnValueChanged.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleWeatherVolumeChanged);
|
|
}
|
|
if (USlider* Slider = AddVolumeSlider(Panel, FText::FromString(TEXT("Effects")), EffectsVolume, 8.0f * Scale))
|
|
{
|
|
Slider->OnValueChanged.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleEffectsVolumeChanged);
|
|
}
|
|
if (USlider* Slider = AddVolumeSlider(Panel, FText::FromString(TEXT("Wildlife")), WildlifeVolume, 8.0f * Scale))
|
|
{
|
|
Slider->OnValueChanged.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleWildlifeVolumeChanged);
|
|
}
|
|
if (USlider* Slider = AddVolumeSlider(Panel, FText::FromString(TEXT("UI")), UiVolume, 24.0f * Scale))
|
|
{
|
|
Slider->OnValueChanged.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleUiVolumeChanged);
|
|
}
|
|
AddText(Panel, FText::FromString(TEXT("Escape opens this menu. Save & Quit writes the current world save before closing.")), FMath::RoundToInt(16.0f * Scale), false, MutedTextColor, 0.0f);
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
|
|
{
|
|
AddText(Panel, FText::FromString(TEXT("Character Selection")), FMath::RoundToInt(18.0f * Scale), true, AccentColor, 6.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Choose your first pioneer")), FMath::RoundToInt(34.0f * Scale), true, TextColor, 6.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Select the person who will step into Ground Zero.")), FMath::RoundToInt(18.0f * Scale), false, MutedTextColor, 24.0f * Scale);
|
|
|
|
UHorizontalBox* CharacterRow = WidgetTree->ConstructWidget<UHorizontalBox>(UHorizontalBox::StaticClass(), TEXT("CharacterRow"));
|
|
if (UVerticalBoxSlot* RowSlot = Panel->AddChildToVerticalBox(CharacterRow))
|
|
{
|
|
RowSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 22.0f * Scale));
|
|
}
|
|
|
|
const bool bMaleSelected = SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultMale;
|
|
const bool bFemaleSelected = SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale;
|
|
UButton* MaleButton = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass(), TEXT("MalePioneerButton"));
|
|
MaleButton->SetStyle(MakeAgrarianButtonStyle(bMaleSelected ? ButtonHoverColor : SecondaryButtonColor, ButtonHoverColor));
|
|
MaleButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleMaleCharacterClicked);
|
|
UVerticalBox* MaleStack = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("MalePioneerStack"));
|
|
MaleButton->SetContent(MaleStack);
|
|
AddText(MaleStack, FText::FromString(TEXT("Young adult male")), FMath::RoundToInt(21.0f * Scale), true, TextColor, 8.0f * Scale);
|
|
AddText(MaleStack, FText::FromString(TEXT("Average build, practical workwear proxy, survival baseline.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 18.0f * Scale);
|
|
AddText(MaleStack, bMaleSelected ? FText::FromString(TEXT("Selected")) : FText::FromString(TEXT("Available")), FMath::RoundToInt(15.0f * Scale), true, bMaleSelected ? AccentColor : MutedTextColor, 0.0f);
|
|
if (UHorizontalBoxSlot* MaleSlot = CharacterRow->AddChildToHorizontalBox(MaleButton))
|
|
{
|
|
MaleSlot->SetPadding(FMargin(0.0f, 0.0f, 12.0f * Scale, 0.0f));
|
|
MaleSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
|
|
}
|
|
|
|
UButton* FemaleButton = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass(), TEXT("FemalePioneerButton"));
|
|
FemaleButton->SetStyle(MakeAgrarianButtonStyle(bFemaleSelected ? ButtonHoverColor : SecondaryButtonColor, ButtonHoverColor));
|
|
FemaleButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleFemaleCharacterClicked);
|
|
UVerticalBox* FemaleStack = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("FemalePioneerStack"));
|
|
FemaleButton->SetContent(FemaleStack);
|
|
AddText(FemaleStack, FText::FromString(TEXT("Young adult female")), FMath::RoundToInt(21.0f * Scale), true, TextColor, 8.0f * Scale);
|
|
AddText(FemaleStack, FText::FromString(TEXT("Average build, practical workwear proxy, survival baseline.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 18.0f * Scale);
|
|
AddText(FemaleStack, bFemaleSelected ? FText::FromString(TEXT("Selected")) : FText::FromString(TEXT("Available")), FMath::RoundToInt(15.0f * Scale), true, bFemaleSelected ? AccentColor : MutedTextColor, 0.0f);
|
|
if (UHorizontalBoxSlot* FemaleSlot = CharacterRow->AddChildToHorizontalBox(FemaleButton))
|
|
{
|
|
FemaleSlot->SetPadding(FMargin(12.0f * Scale, 0.0f, 0.0f, 0.0f));
|
|
FemaleSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
|
|
}
|
|
|
|
PrimaryFocusButton = AddButton(Panel, FText::FromString(TEXT("Continue")), ButtonColor, ButtonHoverColor, 10.0f * Scale);
|
|
PrimaryFocusButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandlePrimaryActionClicked);
|
|
PrimaryFocusButton->OnHovered.AddDynamic(this, &UAgrarianMvpFrontendWidget::FocusPrimaryButton);
|
|
AddText(Panel, FText::Format(FText::FromString(TEXT("Selected {0}: {1}. Click a card or use Left/Right, then continue.")), GetSelectedRoleLabel(), GetSelectedCharacterLabel()), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 0.0f);
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
|
|
{
|
|
AddText(Panel, FText::FromString(TEXT("Server Join")), FMath::RoundToInt(18.0f * Scale), true, AccentColor, 6.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Join MVP server")), FMath::RoundToInt(34.0f * Scale), true, TextColor, 8.0f * Scale);
|
|
AddText(Panel, FText::Format(FText::FromString(TEXT("{0}: {1}")), GetSelectedRoleLabel(), GetSelectedCharacterLabel()), FMath::RoundToInt(18.0f * Scale), false, MutedTextColor, 36.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Server address")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 4.0f * Scale);
|
|
AddText(Panel, JoinServerAddress, FMath::RoundToInt(24.0f * Scale), true, TextColor, 42.0f * Scale);
|
|
|
|
UHorizontalBox* ButtonRow = WidgetTree->ConstructWidget<UHorizontalBox>(UHorizontalBox::StaticClass(), TEXT("JoinButtonRow"));
|
|
if (UVerticalBoxSlot* RowSlot = Panel->AddChildToVerticalBox(ButtonRow))
|
|
{
|
|
RowSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 18.0f * Scale));
|
|
}
|
|
|
|
PrimaryFocusButton = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass(), TEXT("ContinueToLoadingButton"));
|
|
PrimaryFocusButton->SetStyle(MakeAgrarianButtonStyle(ButtonColor, ButtonHoverColor));
|
|
PrimaryFocusButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandlePrimaryActionClicked);
|
|
PrimaryFocusButton->OnHovered.AddDynamic(this, &UAgrarianMvpFrontendWidget::FocusPrimaryButton);
|
|
UTextBlock* ContinueLabel = AddText(nullptr, FText::FromString(TEXT("Continue to loading")), FMath::RoundToInt(20.0f * Scale), true, TextColor, 0.0f);
|
|
PrimaryFocusButton->SetContent(ContinueLabel);
|
|
if (UButtonSlot* ContinueLabelSlot = Cast<UButtonSlot>(ContinueLabel->Slot))
|
|
{
|
|
ContinueLabelSlot->SetPadding(FMargin(22.0f, 12.0f));
|
|
ContinueLabelSlot->SetHorizontalAlignment(HAlign_Center);
|
|
}
|
|
if (UHorizontalBoxSlot* ContinueSlot = ButtonRow->AddChildToHorizontalBox(PrimaryFocusButton))
|
|
{
|
|
ContinueSlot->SetPadding(FMargin(0.0f, 0.0f, 12.0f * Scale, 0.0f));
|
|
ContinueSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
|
|
}
|
|
|
|
UButton* BackButton = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass(), TEXT("BackButton"));
|
|
BackButton->SetStyle(MakeAgrarianButtonStyle(SecondaryButtonColor, ButtonHoverColor));
|
|
BackButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandleBackClicked);
|
|
UTextBlock* BackLabel = AddText(nullptr, FText::FromString(TEXT("Back")), FMath::RoundToInt(20.0f * Scale), true, TextColor, 0.0f);
|
|
BackButton->SetContent(BackLabel);
|
|
if (UButtonSlot* BackLabelSlot = Cast<UButtonSlot>(BackLabel->Slot))
|
|
{
|
|
BackLabelSlot->SetPadding(FMargin(22.0f, 12.0f));
|
|
BackLabelSlot->SetHorizontalAlignment(HAlign_Center);
|
|
}
|
|
if (UHorizontalBoxSlot* BackSlot = ButtonRow->AddChildToHorizontalBox(BackButton))
|
|
{
|
|
BackSlot->SetPadding(FMargin(12.0f * Scale, 0.0f, 0.0f, 0.0f));
|
|
BackSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
|
|
}
|
|
|
|
AddText(Panel, FText::FromString(TEXT("Click continue, press Enter, or press Backspace/Escape to revise your pioneer.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 0.0f);
|
|
return;
|
|
}
|
|
|
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::SavingAndQuit)
|
|
{
|
|
AddText(Panel, FText::FromString(TEXT("Saving World")), FMath::RoundToInt(20.0f * Scale), true, AccentColor, 6.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Writing the current world state")), FMath::RoundToInt(34.0f * Scale), true, TextColor, 8.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("The demo will close after the save command is issued.")), FMath::RoundToInt(18.0f * Scale), false, MutedTextColor, 0.0f);
|
|
return;
|
|
}
|
|
|
|
AddText(Panel, FText::FromString(TEXT("Loading Segment")), FMath::RoundToInt(18.0f * Scale), true, AccentColor, 6.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Preparing Ground Zero")), FMath::RoundToInt(34.0f * Scale), true, TextColor, 8.0f * Scale);
|
|
AddText(Panel, FText::FromString(TEXT("Loading terrain, weather, survival state, and server session data.")), FMath::RoundToInt(18.0f * Scale), false, MutedTextColor, 70.0f * Scale);
|
|
AddText(Panel, FText::Format(FText::FromString(TEXT("{0}: {1} | Server: {2}")), GetSelectedRoleLabel(), GetSelectedCharacterLabel(), JoinServerAddress), FMath::RoundToInt(18.0f * Scale), false, TextColor, 34.0f * Scale);
|
|
PrimaryFocusButton = AddButton(Panel, FText::FromString(TEXT("Enter Ground Zero")), ButtonColor, ButtonHoverColor, 14.0f * Scale);
|
|
PrimaryFocusButton->OnClicked.AddDynamic(this, &UAgrarianMvpFrontendWidget::HandlePrimaryActionClicked);
|
|
PrimaryFocusButton->OnHovered.AddDynamic(this, &UAgrarianMvpFrontendWidget::FocusPrimaryButton);
|
|
AddText(Panel, FText::FromString(TEXT("Click or press Enter to close the MVP menu and begin testing.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 0.0f);
|
|
}
|
|
|
|
UTextBlock* UAgrarianMvpFrontendWidget::AddText(UVerticalBox* Parent, const FText& Text, int32 FontSize, bool bBold, const FLinearColor& Color, float BottomPadding)
|
|
{
|
|
UTextBlock* TextBlock = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass());
|
|
TextBlock->SetText(Text);
|
|
TextBlock->SetFont(FCoreStyle::GetDefaultFontStyle(bBold ? "Bold" : "Regular", FontSize));
|
|
TextBlock->SetColorAndOpacity(FSlateColor(Color));
|
|
TextBlock->SetAutoWrapText(true);
|
|
TextBlock->SetJustification(ETextJustify::Left);
|
|
|
|
if (Parent)
|
|
{
|
|
if (UVerticalBoxSlot* TextSlot = Parent->AddChildToVerticalBox(TextBlock))
|
|
{
|
|
TextSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, BottomPadding));
|
|
}
|
|
}
|
|
|
|
return TextBlock;
|
|
}
|
|
|
|
UButton* UAgrarianMvpFrontendWidget::AddButton(UVerticalBox* Parent, const FText& Text, const FLinearColor& NormalColor, const FLinearColor& HoveredColor, float BottomPadding)
|
|
{
|
|
UButton* Button = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass());
|
|
Button->SetStyle(MakeAgrarianButtonStyle(NormalColor, HoveredColor));
|
|
Button->SetClickMethod(EButtonClickMethod::MouseDown);
|
|
Button->SetTouchMethod(EButtonTouchMethod::Down);
|
|
|
|
if (!Text.IsEmpty())
|
|
{
|
|
UTextBlock* Label = AddText(nullptr, Text, FMath::RoundToInt(20.0f * FMath::Clamp(UiScale, 0.75f, 1.5f)), true, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f), 0.0f);
|
|
Button->SetContent(Label);
|
|
if (UButtonSlot* LabelSlot = Cast<UButtonSlot>(Label->Slot))
|
|
{
|
|
LabelSlot->SetPadding(FMargin(22.0f, 12.0f));
|
|
LabelSlot->SetHorizontalAlignment(HAlign_Center);
|
|
}
|
|
}
|
|
|
|
if (Parent)
|
|
{
|
|
if (UVerticalBoxSlot* ButtonSlot = Parent->AddChildToVerticalBox(Button))
|
|
{
|
|
ButtonSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, BottomPadding));
|
|
ButtonSlot->SetHorizontalAlignment(HAlign_Left);
|
|
}
|
|
}
|
|
|
|
return Button;
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::PlayUiSound(USoundBase* Sound) const
|
|
{
|
|
if (Sound)
|
|
{
|
|
UGameplayStatics::PlaySound2D(this, Sound, FMath::Clamp(MasterVolume * UiVolume, 0.0f, 1.0f));
|
|
}
|
|
}
|
|
|
|
USlider* UAgrarianMvpFrontendWidget::AddVolumeSlider(UVerticalBox* Parent, const FText& Label, float Value, float BottomPadding)
|
|
{
|
|
if (!Parent || !WidgetTree)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
UHorizontalBox* Row = WidgetTree->ConstructWidget<UHorizontalBox>(UHorizontalBox::StaticClass());
|
|
if (UVerticalBoxSlot* RowSlot = Parent->AddChildToVerticalBox(Row))
|
|
{
|
|
RowSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, BottomPadding));
|
|
RowSlot->SetHorizontalAlignment(HAlign_Fill);
|
|
}
|
|
|
|
UTextBlock* LabelText = AddText(nullptr, Label, 15, false, FLinearColor(0.82f, 0.90f, 0.76f, 1.0f), 0.0f);
|
|
if (UHorizontalBoxSlot* LabelSlot = Row->AddChildToHorizontalBox(LabelText))
|
|
{
|
|
LabelSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
|
|
LabelSlot->SetHorizontalAlignment(HAlign_Left);
|
|
LabelSlot->SetVerticalAlignment(VAlign_Center);
|
|
}
|
|
|
|
USlider* Slider = WidgetTree->ConstructWidget<USlider>(USlider::StaticClass());
|
|
Slider->SetValue(FMath::Clamp(Value, 0.0f, 1.0f));
|
|
if (UHorizontalBoxSlot* SliderSlot = Row->AddChildToHorizontalBox(Slider))
|
|
{
|
|
SliderSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
|
|
SliderSlot->SetHorizontalAlignment(HAlign_Fill);
|
|
SliderSlot->SetVerticalAlignment(VAlign_Center);
|
|
}
|
|
|
|
return Slider;
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleMasterVolumeChanged(float Value)
|
|
{
|
|
MasterVolume = FMath::Clamp(Value, 0.0f, 1.0f);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleAmbientVolumeChanged(float Value)
|
|
{
|
|
AmbientVolume = FMath::Clamp(Value, 0.0f, 1.0f);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleWeatherVolumeChanged(float Value)
|
|
{
|
|
WeatherVolume = FMath::Clamp(Value, 0.0f, 1.0f);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleEffectsVolumeChanged(float Value)
|
|
{
|
|
EffectsVolume = FMath::Clamp(Value, 0.0f, 1.0f);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleWildlifeVolumeChanged(float Value)
|
|
{
|
|
WildlifeVolume = FMath::Clamp(Value, 0.0f, 1.0f);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleUiVolumeChanged(float Value)
|
|
{
|
|
UiVolume = FMath::Clamp(Value, 0.0f, 1.0f);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::FocusPrimaryButton()
|
|
{
|
|
if (PrimaryFocusButton)
|
|
{
|
|
PrimaryFocusButton->SetKeyboardFocus();
|
|
}
|
|
else
|
|
{
|
|
SetKeyboardFocus();
|
|
}
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandlePrimaryActionClicked()
|
|
{
|
|
PlayUiSound(UiConfirmSound);
|
|
ConfirmActiveScreen();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleBackClicked()
|
|
{
|
|
PlayUiSound(UiBackSound);
|
|
BackFromActiveScreen();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleSaveAndQuitClicked()
|
|
{
|
|
PlayUiSound(UiSaveQuitSound);
|
|
SaveAndQuit();
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleMaleCharacterClicked()
|
|
{
|
|
PlayUiSound(UiSelectionSound);
|
|
SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultMale);
|
|
}
|
|
|
|
void UAgrarianMvpFrontendWidget::HandleFemaleCharacterClicked()
|
|
{
|
|
PlayUiSound(UiSelectionSound);
|
|
SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultFemale);
|
|
}
|
|
|
|
FText UAgrarianMvpFrontendWidget::GetSelectedCharacterLabel() const
|
|
{
|
|
return SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale
|
|
? FText::FromString(TEXT("young adult female"))
|
|
: FText::FromString(TEXT("young adult male"));
|
|
}
|
|
|
|
FText UAgrarianMvpFrontendWidget::GetSelectedRoleLabel() const
|
|
{
|
|
return FText::FromString(TEXT("Pioneer"));
|
|
}
|