GameLiftPlugin/Source/GameLiftPlugin/Private/SMenu/Anywhere/SConnectAnywhereFleetMenu.cpp (608 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "SConnectAnywhereFleetMenu.h"
#include <Widgets/Layout/SWidgetSwitcher.h>
#include <Async/Async.h>
#include "SWidgets/SBootstrapStatus.h"
#include "SWidgets/SErrorBanner.h"
#include "SWidgets/SInputTextBox.h"
#include "SWidgets/STextStatus.h"
#include "SWidgets/SOnlineHyperlink.h"
#include "SWidgets/SNamedRow.h"
#include "SWidgets/SSectionsWithHeaders.h"
#include "SWidgets/SSelectionComboBox.h"
#include "IGameLiftAnywhereHandler.h"
#include "IGameLiftCoreModule.h"
#include "GameLiftPlugin.h"
#include "GameLiftPluginStyle.h"
#include <Developer/Settings/Public/ISettingsModule.h>
#include "Settings/UGameLiftAnywhereStatus.h"
#include "Settings/UGameLiftSettings.h"
#include "Types/EBootstrapMessageState.h"
#include "Utils/StringPaths.h"
#include "Utils/Misc.h"
#define LOCTEXT_NAMESPACE "SConnectAnywhereFleetMenu"
void SConnectAnywhereFleetMenu::Construct(const FArguments& InArgs)
{
OnFleetChangedDelegate = InArgs._OnFleetChangedDelegate;
SSectionStep::Construct(
SSectionStep::FArguments()
.HeaderTitle(Menu::DeployAnywhere::kConnectToFleetHeader)
.HeaderDescription(Menu::DeployAnywhere::kFleetSectionDescription)
.BodyContent()
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Fill)
[
SAssignNew(DeployFleetErrorBanner, SErrorBanner)
.ErrorText(Menu::DeployAnywhere::kLoadingFleetErrorText)
.ErrorButtonText(Menu::DeployAnywhere::kLoadingFleetRetryText)
.OnBannerButtonClicked_Raw(this, &SConnectAnywhereFleetMenu::OnRetryLoadingFleetInfo)
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(SPadding::Bottom)
[
SNew(SOnlineHyperlink)
.Text(Settings::AwsAccount::kAWSFreeTierLinkText)
.Link(Settings::AwsAccount::kAWSFreeTierLinkUrl)
]
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Fill)
.Padding(SPadding::Top)
[
SAssignNew(ConnectToFleetWidgetSwitcher, SWidgetSwitcher)
+ SWidgetSwitcher::Slot()
[
// input box that has "Create new fleet" and cancel button (depending on whether it has existing fleets or not)
CreateAddNewFleetUI()
]
+ SWidgetSwitcher::Slot()
[
// it has create new anywhere fleet and selection box (with an inprogress state) when fleet selected, it is marked as done
CreateChooseExistingFleetUI()
]
]
]);
// Listen to profile changes
SGameLiftSettingsAwsAccountMenu::OnProfileSelectionChangedMultiDelegate.AddSP(this, &SConnectAnywhereFleetMenu::OnBootstrapStatusChanged);
// Initialize section UI based on state
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
// If section not done and previous section not done
if (!AnywhereStatus->IsFleetDeployed && AnywhereStatus->PathToServerBuild.IsEmpty())
{
ResetAndCollapseSection();
}
// If section not done, but previous is done
else if (!AnywhereStatus->IsFleetDeployed)
{
StartSection();
}
// If section is done, and previous done
else {
DeployFleetErrorBanner->SetVisibility(EVisibility::Collapsed);
ExistingFleetsComboBox->SetUnselectedText(FText::FromString(AnywhereStatus->FleetName));
ConnectToFleetWidgetSwitcher->SetActiveWidgetIndex((int)EFleetSelectionUIState::ChooseExistingFleet);
FleetIDRow->SetVisibility(EVisibility::Visible);
FleetIDTextView->SetText(FText::FromString(AnywhereStatus->FleetId));
SetProgressBarState(SProgressBar::EProgressBarUIState::ProgressComplete);
ModifyCreateButtonSwitcher->SetActiveWidgetIndex(1);
ExistingFleetsComboBox->SetEnabled(false);
}
}
void SConnectAnywhereFleetMenu::StartSection()
{
// Default UI to show existing fleet selection until fleet data is loaded
ClearSelectedFleet();
ExistingFleetList.Reset();
ExistingFleetsComboBox->SetEnabled(true);
ExistingFleetsComboBox->SetUnselectedText(Menu::DeployAnywhere::kUnselectedFleetDropDownText);
ChangeFleetSelectionUIState(EFleetSelectionUIState::ChooseExistingFleet);
// Start loading fleet data
if (CanEnableUI())
{
// Refresh the available fleets for the newly bootstrapped profile
LoadFleetInfoAsync();
}
}
void SConnectAnywhereFleetMenu::OnBootstrapStatusChanged(const SGameLiftSettingsAwsAccountMenu* /* Sender */)
{
UGameLiftSettings* Settings = GetMutableDefault<UGameLiftSettings>();
EBootstrapMessageState BootstrapState = EBootstrapMessageStateFromInt(Settings->BootstrapStatus);
if (BootstrapState == EBootstrapMessageState::NoBootstrappedMessage
|| BootstrapState == EBootstrapMessageState::ActiveMessage)
{
ClearSelectedFleet();
// Set UI to show existing fleet selection
ExistingFleetList.Reset();
ExistingFleetsComboBox->RequestToRebuildList();
ExistingFleetsComboBox->ClearSelection();
ExistingFleetsComboBox->SetUnselectedText(Menu::DeployAnywhere::kUnselectedFleetDropDownText);
ChangeFleetSelectionUIState(EFleetSelectionUIState::ChooseExistingFleet);
if (CanEnableUI())
{
// Refresh the available fleets for the newly bootstrapped profile
LoadFleetInfoAsync();
}
}
}
void SConnectAnywhereFleetMenu::LoadFleetInfoAsync()
{
IsLoadingFleetInfo = true;
ExistingFleetsComboBox->SetUnselectedText(Menu::DeployAnywhere::kLoadingFleetDropDownText);
// Hide error banner
DeployFleetErrorBanner->SetVisibility(EVisibility::Collapsed);
Async(EAsyncExecution::Thread,
[this]()
{
// Get list of available Anywhere fleets
IGameLiftAnywhereHandler& Handler = IGameLiftCoreModule::Get().GetGameLiftAnywhereHandler();
GameLiftAnywhereDescribeFleetsResult ListFleetResult = Handler.DescribeAnywhereFleets();
// Update UI on the main thread to avoid Slate errors such as SLATE_CROSS_THREAD_CHECK failure.
Async(EAsyncExecution::TaskGraphMainThread,
[this, ListFleetResult = MoveTemp(ListFleetResult)]
{
OnLoadFleetInfoComplete(ListFleetResult);
});
});
}
void SConnectAnywhereFleetMenu::OnLoadFleetInfoComplete(const GameLiftAnywhereDescribeFleetsResult& ListFleetResult)
{
IsLoadingFleetInfo = false;
ExistingFleetsComboBox->SetUnselectedText(Menu::DeployAnywhere::kUnselectedFleetDropDownText);
if (ListFleetResult.bIsSuccessful)
{
// Update available fleet list
OnAvailableFleetsChanged(ListFleetResult.Fleets);
}
else
{
// Show error banner
DeployFleetErrorBanner->SetVisibility(EVisibility::Visible);
}
}
void SConnectAnywhereFleetMenu::OnRetryLoadingFleetInfo()
{
if (CanEnableUI())
{
// Refresh the available fleets for the current bootstrapped profile
LoadFleetInfoAsync();
}
}
void SConnectAnywhereFleetMenu::OnAvailableFleetsChanged(const TArray<GameLiftAnywhereDescribeFleetsResult::FleetAttributes>& Fleets)
{
ExistingFleetList.Reset();
for (const auto& Fleet : Fleets)
{
ExistingFleetList.Add(FTextIntPair(FText::FromString(Fleet.FleetName), ExistingFleetList.Num(), FText::FromString(Fleet.FleetId)));
}
ValidateCurrentlySelectedFleet();
if (ExistingFleetList.Num() > 0)
{
ChangeFleetSelectionUIState(EFleetSelectionUIState::ChooseExistingFleet);
}
else
{
ChangeFleetSelectionUIState(EFleetSelectionUIState::CreateNewFleet);
}
}
TSharedRef<SWidget> SConnectAnywhereFleetMenu::CreateAddNewFleetUI()
{
TSharedRef<SVerticalBox> VerticalBox = SNew(SVerticalBox)
// Anywhere fleet name text input
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Fill)
.Padding(SPadding::Top + SPadding::Right2x)
[
SNew(SNamedRow)
.NameText(Menu::DeployAnywhere::kNewFleetNameTitle)
.RowWidget(
SAssignNew(FleetNameTextInput, SEditableTextBox)
.Text(GetDefaultFleetName())
.HintText(Menu::DeployAnywhere::kNewFleetNameTextBoxHint)
)
]
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Fill)
.Padding(SPadding::Bottom + SPadding::Right2x)
[
SNew(SNamedRow)
.SecondaryColumnLeftPadding(true)
.RowWidget(
SNew(STextBlock)
.Text(Menu::DeployAnywhere::kFleetNameInstructionText)
.AutoWrapText(true)
.TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kNote)
)
]
+ SVerticalBox::Slot()
.AutoHeight()
.VAlign(VAlign_Center)
.Padding(SPadding::Top + SPadding::Right2x)
[
SAssignNew(DeployFleetErrorRow, SNamedRow)
.SecondaryColumnLeftPadding(true)
.RowWidget(
SAssignNew(DeployFleetErrorTextBlock, STextBlock)
.TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kNote)
.AutoWrapText(true)
)
.Visibility(EVisibility::Collapsed)
]
+ SVerticalBox::Slot()
.AutoHeight()
.VAlign(VAlign_Center)
.Padding(SPadding::Top3x + SPadding::Right2x)
[
SNew(SHorizontalBox)
// Button to cancel adding new anywhere fleet
+ SHorizontalBox::Slot()
.AutoWidth()
.HAlign(HAlign_Left)
.Padding(SPadding::Right2x)
[
SAssignNew(CancelButton, SButton)
.Text(Menu::DeployAnywhere::kCancelButtonText)
.OnClicked_Raw(this, &SConnectAnywhereFleetMenu::OnCancelFleetButtonClicked)
.ButtonStyle(FGameLiftPluginStyle::Get(), Style::Button::kNormalButtonStyleName)
.TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kButtonNormal)
]
// Button to add a new anywhere fleet
+ SHorizontalBox::Slot()
.AutoWidth()
.HAlign(HAlign_Left)
.Padding(SPadding::Right2x)
[
SNew(SButton)
.Text(Menu::DeployAnywhere::kCreateFleetButtonText)
.OnClicked_Raw(this, &SConnectAnywhereFleetMenu::OnCreateFleetButtonClicked)
.IsEnabled_Raw(this, &SConnectAnywhereFleetMenu::CanCreateFleet)
.ButtonStyle(FGameLiftPluginStyle::Get(), Style::Button::kSuccessButtonStyleName)
.TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kButtonLight)
]
// Loading indicator during fleet creation
+ SHorizontalBox::Slot()
.AutoWidth()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
SNew(STextStatus)
.IconState(STextStatus::EIconState::Loading)
.Visibility_Lambda([&]
{
return IsLoading ? EVisibility::Visible : EVisibility::Hidden;
})
]
// Hyperlink to see/manage available fleets in console
+ SHorizontalBox::Slot()
.FillWidth(1)
.HAlign(HAlign_Right)
.Padding(SPadding::Right) // move the link left a bit
[
CreateFleetsInConsoleHyperLink()
]
];
DeployFleetErrorTextBlock->SetColorAndOpacity(FGameLiftPluginStyle::Get().GetColor(Style::Color::kError));
return VerticalBox;
}
TSharedRef<SWidget> SConnectAnywhereFleetMenu::CreateChooseExistingFleetUI()
{
return SNew(SVerticalBox)
// Anywhere fleet dropdown
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Fill)
.Padding(SPadding::Top_Bottom + SPadding::Right2x)
[
SNew(SNamedRow)
.NameText(Menu::DeployAnywhere::kSelectedFleetTitle)
.RowWidget(
SAssignNew(ExistingFleetsComboBox, SSelectionComboBox)
.UnselectedText(Menu::DeployAnywhere::kUnselectedFleetDropDownText)
.OnListBuilding_Raw(this, &SConnectAnywhereFleetMenu::OnBuildExistingFleetValues)
.OnItemSelected_Raw(this, &SConnectAnywhereFleetMenu::OnExistingFleetSelected)
.IsEnabled_Raw(this, &SConnectAnywhereFleetMenu::CanEnableFleetSelectionUI)
)
]
// Anywhere fleet ID
+ SVerticalBox::Slot()
.AutoHeight()
.HAlign(HAlign_Fill)
.Padding(SPadding::Top_Bottom + SPadding::Right2x)
[
SAssignNew(FleetIDRow, SNamedRow)
.NameText(Menu::DeployAnywhere::kSelectedFleetIDTitle)
.RowWidget(
SAssignNew(FleetIDTextView, SEditableText)
.Style(FGameLiftPluginStyle::Get(), Style::EditableText::kFieldMedium)
.IsReadOnly(true)
)
.SecondaryColumnLeftPadding(true)
]
// Button to add a new Anywhere fleet
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(SPadding::Top_Bottom + SPadding::Right2x)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.HAlign(HAlign_Left)
.Padding(SPadding::Right)
[
SAssignNew(ModifyCreateButtonSwitcher, SWidgetSwitcher)
+ SWidgetSwitcher::Slot()
[
SAssignNew(AddFleetButton, SButton)
.Text(Menu::DeployAnywhere::kGoToCreateFleetButtonText)
.OnClicked_Raw(this, &SConnectAnywhereFleetMenu::OnGoToCreateFleetButtonClicked)
.IsEnabled_Raw(this, &SConnectAnywhereFleetMenu::CanEnableUI)
.ButtonStyle(FGameLiftPluginStyle::Get(), Style::Button::kNormalButtonStyleName)
.TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kButtonNormal)
]
+ SWidgetSwitcher::Slot()
[
// modify button
SAssignNew(ModifyButton, SButton)
.Text(Menu::DeployAnywhere::kModifyAnywhereFleet)
.OnClicked_Raw(this, &SConnectAnywhereFleetMenu::OnModifyButtonClicked)
.ButtonStyle(FGameLiftPluginStyle::Get(), Style::Button::kNormalButtonStyleName)
.TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kButtonNormal)
]
]
// Hyperlink to fleet list in console for current region
+ SHorizontalBox::Slot()
.FillWidth(1)
.HAlign(HAlign_Right)
.Padding(SPadding::Right) // move the link left a bit
[
CreateFleetsInConsoleHyperLink()
]
];
}
FReply SConnectAnywhereFleetMenu::OnModifyButtonClicked()
{
ResetAndCollapseNextSections();
return FReply::Handled();
}
TSharedRef<SWidget> SConnectAnywhereFleetMenu::CreateFleetsInConsoleHyperLink()
{
return SNew(SOnlineHyperlink)
.Text(Menu::DeployAnywhere::kViewInGameLiftConsoleHyperLinkText)
.Link_Lambda([&]
{
// Update link with the region associated with the currently selected profile
FString CurrentAwsRegion(TEXT("us-west-2"));
UGameLiftSettings* Settings = GetMutableDefault<UGameLiftSettings>();
if (Settings && !Settings->AwsRegion.IsEmpty())
{
CurrentAwsRegion = Settings->AwsRegion.ToString();
}
return (FString::Format(Menu::DeployAnywhere::kViewInGameLiftConsoleHyperLinkUrlFormat, { CurrentAwsRegion }));
});
}
FReply SConnectAnywhereFleetMenu::OnCreateFleetButtonClicked()
{
FString FleetName = FleetNameTextInput->GetText().ToString().TrimStartAndEnd();
// Validate input
if (FleetName.IsEmpty())
{
return FReply::Handled();
}
IsLoading = true;
SetProgressBarState(SProgressBar::EProgressBarUIState::InProgress);
FleetNameTextInput->SetIsReadOnly(true);
if (CancelButton->GetVisibility() == EVisibility::Visible)
{
CancelButton->SetVisibility(EVisibility::Collapsed);
}
Async(EAsyncExecution::Thread,
// Move or copy is needed here so the new thread can always access the variable.
[this, FleetName = MoveTemp(FleetName)]()
{
TTuple<FString, FString> FleetIdResult = CreateCustomLocationAndFleet(FleetName);
IsLoading = false;
// Have to update UI in this new thread otherwise SLATE_CROSS_THREAD_CHECK will fail.
// This is because updates in switcher widget can only happen in the game thread or Slate thread.
// Note: There could be a better solution here.
Async(EAsyncExecution::TaskGraphMainThread,
[this, FleetNameCopy = FleetName, FleetIdResult = MoveTemp(FleetIdResult)]
{
if (!FleetIdResult.Get<0>().IsEmpty())
{
AddNewAnywhereFleet(FleetNameCopy, FleetIdResult.Get<0>());
UpdateErrorMessage(FText::GetEmpty()); // added this to mimic other section
ChangeFleetSelectionUIState(EFleetSelectionUIState::ChooseExistingFleet);
}
else
{
UpdateErrorMessage(FText::FromString(FleetIdResult.Get<1>()));
SetProgressBarState(SProgressBar::EProgressBarUIState::ProgressError);
}
FleetNameTextInput->SetIsReadOnly(false);
CancelButton->SetVisibility(EVisibility::Visible);
});
});
return FReply::Handled();
}
FReply SConnectAnywhereFleetMenu::OnGoToCreateFleetButtonClicked()
{
ChangeFleetSelectionUIState(EFleetSelectionUIState::CreateNewFleet);
return FReply::Handled();
}
FReply SConnectAnywhereFleetMenu::OnCancelFleetButtonClicked()
{
ChangeFleetSelectionUIState(EFleetSelectionUIState::ChooseExistingFleet);
return FReply::Handled();
}
TTuple<FString, FString> SConnectAnywhereFleetMenu::CreateCustomLocation()
{
UGameLiftSettings* Settings = GetMutableDefault<UGameLiftSettings>();
FString AwsRegion = Settings->AwsRegion.ToString();
IGameLiftAnywhereHandler& Handler = IGameLiftCoreModule::Get().GetGameLiftAnywhereHandler();
GameLiftAnywhereCreateLocationResult CreateLocationResult = Handler.CreateCustomLocation(AwsRegion);
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
if (CreateLocationResult.bIsSuccessful)
{
AnywhereStatus->CustomLocation = CreateLocationResult.LocationName;
AnywhereStatus->DeployedRegion = AwsRegion;
AnywhereStatus->SaveConfig();
return MakeTuple(CreateLocationResult.LocationName, TEXT(""));
}
else
{
return MakeTuple(TEXT(""), CreateLocationResult.ErrorMessage);
}
}
TTuple<FString, FString> SConnectAnywhereFleetMenu::CreateCustomLocationAndFleet(const FString& InFleetName)
{
// Create a custom location for the current AWS region used in the profile.
TTuple<FString, FString> CreateLocationResult = CreateCustomLocation();
const FString LocationName = CreateLocationResult.Get<0>();
if (LocationName.IsEmpty())
{
// Failed to create custom location.
return CreateLocationResult;
}
// Create an Anywhere fleet.
IGameLiftAnywhereHandler& Handler = IGameLiftCoreModule::Get().GetGameLiftAnywhereHandler();
GameLiftAnywhereCreateFleetResult CreateFleetResult = Handler.CreateFleet(InFleetName, LocationName);
if (CreateFleetResult.bIsSuccessful)
{
return MakeTuple(CreateFleetResult.FleetId, TEXT(""));
}
else
{
return MakeTuple(TEXT(""), CreateFleetResult.ErrorMessage);
}
}
void SConnectAnywhereFleetMenu::AddNewAnywhereFleet(const FString& InFleetName, const FString& InFleetId)
{
// Add new Anywhere fleet
ExistingFleetList.Add(FTextIntPair(FText::FromString(InFleetName), ExistingFleetList.Num(), FText::FromString(InFleetId)));
// Set selected Anywhere fleet
SaveSelectedFleet(InFleetName, InFleetId);
}
bool SConnectAnywhereFleetMenu::CanCreateFleet() const
{
return CanEnableUI() && !FleetNameTextInput->GetText().IsEmpty();
}
bool SConnectAnywhereFleetMenu::CanEnableFleetSelectionUI() const
{
UGameLiftSettings* Settings = GetMutableDefault<UGameLiftSettings>();
return EBootstrapMessageStateFromInt(Settings->BootstrapStatus) == EBootstrapMessageState::ActiveMessage
&& !IsLoading;
}
bool SConnectAnywhereFleetMenu::CanEnableUI() const
{
UGameLiftSettings* Settings = GetMutableDefault<UGameLiftSettings>();
return EBootstrapMessageStateFromInt(Settings->BootstrapStatus) == EBootstrapMessageState::ActiveMessage
&& !IsLoading && !IsLoadingFleetInfo;
}
void SConnectAnywhereFleetMenu::ChangeFleetSelectionUIState(EFleetSelectionUIState InState)
{
ConnectToFleetWidgetSwitcher->SetActiveWidgetIndex(FleetSelectionUIStateToInt(InState));
UpdateContentForCurrentUIState();
}
void SConnectAnywhereFleetMenu::UpdateContentForCurrentUIState()
{
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
// Hide error banner
DeployFleetErrorBanner->SetVisibility(EVisibility::Collapsed);
if (ConnectToFleetWidgetSwitcher->GetActiveWidgetIndex() == FleetSelectionUIStateToInt(EFleetSelectionUIState::CreateNewFleet))
{
// Update UI for creating a new fleet
bool HasExistingFleets = HaveExistingFleets();
CancelButton->SetVisibility(HasExistingFleets ? EVisibility::Visible : EVisibility::Collapsed);
if (HasExistingFleets)
{
SetProgressBarState(SProgressBar::EProgressBarUIState::NotStart);
}
}
else
{
// Update UI for selecting an existing fleet
ExistingFleetsComboBox->RequestToRebuildList();
ExistingFleetsComboBox->SetSelectedByName(FText::FromString(AnywhereStatus->FleetName));
if (ExistingFleetsComboBox->IsCurrentSelectionValid())
{
FleetIDRow->SetVisibility(EVisibility::Visible);
FleetIDTextView->SetText(FText::FromString(AnywhereStatus->FleetId));
SetProgressBarState(SProgressBar::EProgressBarUIState::ProgressComplete);
ModifyCreateButtonSwitcher->SetActiveWidgetIndex(1);
ExistingFleetsComboBox->SetEnabled(false);
StartNextSection();
}
else
{
if (ExistingFleetList.Num() > 0) // We use Num instead of IsEmpty to maintain UE4 compatibility.
{
// Can't find previously selected fleet, so clear it.
ClearSelectedFleet();
}
FleetIDRow->SetVisibility(EVisibility::Collapsed);
ModifyCreateButtonSwitcher->SetActiveWidgetIndex(0);
SetProgressBarState(SProgressBar::EProgressBarUIState::NotStart);
}
}
}
void SConnectAnywhereFleetMenu::OnSelectedFleetChanged()
{
// Called when a user creates a new fleet or changes to another existing fleet
OnFleetChangedDelegate.ExecuteIfBound();
}
bool SConnectAnywhereFleetMenu::HaveExistingFleets() const
{
return ExistingFleetList.Num() > 0;
}
bool SConnectAnywhereFleetMenu::IsFleetSelected() const
{
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
return !AnywhereStatus->FleetName.IsEmpty();
}
void SConnectAnywhereFleetMenu::SaveSelectedFleet(const FString& InFleetName, const FString& InFleetId)
{
if (InFleetName.IsEmpty() || InFleetId.IsEmpty())
{
ClearSelectedFleet();
}
else
{
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
if (AnywhereStatus->FleetName != InFleetName
|| AnywhereStatus->FleetId != InFleetId
|| !AnywhereStatus->IsFleetDeployed)
{
AnywhereStatus->FleetName = InFleetName;
AnywhereStatus->FleetId = InFleetId;
AnywhereStatus->IsFleetDeployed = true;
AnywhereStatus->SaveConfig();
OnSelectedFleetChanged();
}
}
}
void SConnectAnywhereFleetMenu::ClearSelectedFleet()
{
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
if (AnywhereStatus->IsFleetDeployed)
{
AnywhereStatus->FleetName.Empty();
AnywhereStatus->FleetId.Empty();
AnywhereStatus->IsFleetDeployed = false;
AnywhereStatus->SaveConfig();
ExistingFleetsComboBox->ClearSelection();
OnSelectedFleetChanged();
}
}
void SConnectAnywhereFleetMenu::ValidateCurrentlySelectedFleet()
{
// Check if the currently selected fleet is still available
UGameLiftAnywhereStatus* AnywhereStatus = GetMutableDefault<UGameLiftAnywhereStatus>();
if (AnywhereStatus->IsFleetDeployed)
{
bool SelectedFleetExists = false;
for (const FTextIntPair& ExistingFleet : ExistingFleetList)
{
if ((ExistingFleet.Text.ToString() == AnywhereStatus->FleetName)
&& (ExistingFleet.Description.ToString() == AnywhereStatus->FleetId))
{
SelectedFleetExists = true;
break;
}
}
if (!SelectedFleetExists)
{
ClearSelectedFleet();
}
}
}
void SConnectAnywhereFleetMenu::OnBuildExistingFleetValues(TArray<FTextIntPair>& Items)
{
Items.Reset();
for (const FTextIntPair& ExistingFleet : ExistingFleetList)
{
Items.Add(ExistingFleet);
}
}
void SConnectAnywhereFleetMenu::OnExistingFleetSelected(int SelectionId, const FTextIntPair& Items)
{
// Change which fleet is selected
SaveSelectedFleet(Items.Text.ToString(), Items.Description.ToString());
UpdateContentForCurrentUIState();
}
void SConnectAnywhereFleetMenu::UpdateErrorMessage(const FText& ErrorMessage)
{
if (ErrorMessage.IsEmpty())
{
DeployFleetErrorRow->SetVisibility(EVisibility::Collapsed);
DeployFleetErrorTextBlock->SetText(FText::GetEmpty());
}
else
{
DeployFleetErrorRow->SetVisibility(EVisibility::Visible);
DeployFleetErrorTextBlock->SetText(ErrorMessage);
}
}
FText SConnectAnywhereFleetMenu::GetDefaultFleetName() const
{
FString DefaultFleetName = FString::Format(TEXT("{0}-AnywhereFleet"), { FApp::GetProjectName() });
return FText::FromString(DefaultFleetName);
}
#undef LOCTEXT_NAMESPACE