Fix MVP menu startup and mouse flow

This commit is contained in:
2026-05-18 22:14:17 -07:00
parent 5566d846e1
commit 3aac902142
10 changed files with 321 additions and 35 deletions
@@ -25,8 +25,11 @@ EXPECTED = {
"EKeys::A",
"EKeys::D",
"Selected",
"Use Left/Right or A/D to choose",
"Click a card or use Left/Right",
"GetSelectedCharacterLabel",
"NativeOnMouseButtonDown",
"IsPointInside(LocalMousePosition, MaleCardPosition, CardSize)",
"IsPointInside(LocalMousePosition, FemaleCardPosition, CardSize)",
],
"AgrarianGamePlayerController.h": [
"AgrarianSelectCharacter",
@@ -17,13 +17,16 @@ EXPECTED = {
"AgrarianMvpFrontendWidget.cpp": [
"EAgrarianMvpFrontendScreen::CharacterSelection",
"DrawCharacterSelection",
"Choose your first settler",
"Choose your first pioneer",
"Young adult male",
"Young adult female",
"MVP placeholder landing page",
"Select the person who will step into Ground Zero.",
"NativeOnMouseButtonDown",
"Continue",
],
"AgrarianGamePlayerController.cpp": [
"SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection)",
"MvpFrontendStartupDelaySeconds",
],
"AGRARIAN_DEVELOPMENT_ROADMAP.md": [
"[x] After splash/startup screens, land on an MVP character selection landing page.",
+2
View File
@@ -22,6 +22,8 @@ EXPECTED = {
"SetActiveScreen(EAgrarianMvpFrontendScreen::JoinServer)",
"Join MVP server",
"Continue to loading",
"Back",
"NativeOnMouseButtonDown",
],
"AgrarianGamePlayerController.h": [
"AgrarianShowMvpScreen",
+2 -1
View File
@@ -19,7 +19,8 @@ EXPECTED = {
"SetActiveScreen(EAgrarianMvpFrontendScreen::Loading)",
"Preparing Ground Zero",
"Loading terrain, weather, survival state, and server session data.",
"MVP loading placeholder",
"Enter Ground Zero",
"CompleteFrontendFlow",
"BarSize.X * 0.62f",
],
"AgrarianGamePlayerController.cpp": [
@@ -29,6 +29,17 @@ REQUIRED = {
"Cherished individuals, Pacificao seed funding, and Lina Family Investment Funds",
"SlamSeconds",
"DrawCreditIllustration",
"GetCreditsSequenceDurationSeconds",
"Agrarian Startup Credits",
],
ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.h": [
"MvpFrontendStartupDelaySeconds = 24.25f",
"ShowMvpFrontend",
],
ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp": [
"GetWorldTimerManager().SetTimer",
"ShowMvpFrontend",
"FInputModeGameAndUI",
],
ROOT / "Config" / "DefaultGame.ini": [
"ProjectVersion=0.1.N-investor.20260518",
@@ -31,6 +31,21 @@ float SmoothStep(float Value)
const float ClampedValue = FMath::Clamp(Value, 0.0f, 1.0f);
return ClampedValue * ClampedValue * (3.0f - (2.0f * ClampedValue));
}
float GetCreditsSequenceDurationSeconds()
{
constexpr float IntroDelay = 0.55f;
constexpr float SlamSeconds = 0.28f;
constexpr float ExitSeconds = 0.48f;
constexpr float GapSeconds = 0.16f;
float Duration = IntroDelay;
for (const FAgrarianCreditCard& Card : CreditCards)
{
Duration += SlamSeconds + Card.HoldSeconds + ExitSeconds + GapSeconds;
}
return Duration;
}
}
void UAgrarianDemoNoticeWidget::NativeConstruct()
@@ -51,6 +66,26 @@ int32 UAgrarianDemoNoticeWidget::NativePaint(
LayerId = Super::NativePaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
const FVector2D Size = AllottedGeometry.GetLocalSize();
const UWorld* World = GetWorld();
const float Elapsed = World ? World->GetTimeSeconds() - CreditsStartTimeSeconds : 0.0f;
if (Elapsed <= GetCreditsSequenceDurationSeconds() + 1.0f)
{
FSlateDrawElement::MakeBox(
OutDrawElements,
++LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(Size), FSlateLayoutTransform(FVector2f::ZeroVector)),
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
ESlateDrawEffect::None,
FLinearColor(0.006f, 0.008f, 0.007f, 0.98f));
const FSlateFontInfo SegmentFont = FCoreStyle::GetDefaultFontStyle("Bold", 22);
const FSlateFontInfo VersionFont = FCoreStyle::GetDefaultFontStyle("Regular", 15);
DrawCenteredText(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Agrarian Startup Credits")), 38.0f, SegmentFont, FLinearColor(0.72f, 0.84f, 0.60f, 1.0f));
DrawCenteredText(OutDrawElements, LayerId, AllottedGeometry, VersionLabel, 72.0f, VersionFont, FLinearColor(0.58f, 0.64f, 0.54f, 1.0f));
DrawCinematicCredits(OutDrawElements, LayerId, AllottedGeometry);
return LayerId;
}
const float PanelWidth = FMath::Min(860.0f, FMath::Max(320.0f, Size.X - 96.0f));
const float PanelHeight = 210.0f;
const FVector2D PanelPosition((Size.X - PanelWidth) * 0.5f, 42.0f);
@@ -18,6 +18,7 @@
#include "GameFramework/CharacterMovementComponent.h"
#include "InputMappingContext.h"
#include "Blueprint/UserWidget.h"
#include "TimerManager.h"
#include "AgrarianGame.h"
#include "Widgets/Input/SVirtualJoystick.h"
@@ -81,16 +82,18 @@ void AAgrarianGamePlayerController::BeginPlay()
if (IsLocalPlayerController())
{
if (!MvpFrontendWidgetClass)
if (MvpFrontendStartupDelaySeconds > 0.0f)
{
MvpFrontendWidgetClass = UAgrarianMvpFrontendWidget::StaticClass();
GetWorldTimerManager().SetTimer(
MvpFrontendStartupTimerHandle,
this,
&AAgrarianGamePlayerController::ShowMvpFrontend,
MvpFrontendStartupDelaySeconds,
false);
}
MvpFrontendWidget = CreateWidget<UAgrarianMvpFrontendWidget>(this, MvpFrontendWidgetClass);
if (MvpFrontendWidget)
else
{
MvpFrontendWidget->SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
MvpFrontendWidget->AddToPlayerScreen(10);
ShowMvpFrontend();
}
}
@@ -147,6 +150,30 @@ bool AAgrarianGamePlayerController::ShouldUseTouchControls() const
return SVirtualJoystick::ShouldDisplayTouchInterface() || bForceTouchControls;
}
void AAgrarianGamePlayerController::ShowMvpFrontend()
{
if (!IsLocalPlayerController() || MvpFrontendWidget)
{
return;
}
if (!MvpFrontendWidgetClass)
{
MvpFrontendWidgetClass = UAgrarianMvpFrontendWidget::StaticClass();
}
MvpFrontendWidget = CreateWidget<UAgrarianMvpFrontendWidget>(this, MvpFrontendWidgetClass);
if (!MvpFrontendWidget)
{
return;
}
MvpFrontendWidget->SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
MvpFrontendWidget->AddToPlayerScreen(10);
SetInputMode(FInputModeGameAndUI().SetWidgetToFocus(MvpFrontendWidget->TakeWidget()).SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock));
bShowMouseCursor = true;
}
void AAgrarianGamePlayerController::AgrarianGrantItem(FName ItemId, int32 Quantity)
{
if (ItemId == NAME_None || Quantity <= 0)
@@ -44,6 +44,11 @@ protected:
UPROPERTY()
TObjectPtr<UAgrarianMvpFrontendWidget> MvpFrontendWidget;
UPROPERTY(EditAnywhere, Category = "Agrarian|MVP UI", meta = (ClampMin = "0.0"))
float MvpFrontendStartupDelaySeconds = 24.25f;
FTimerHandle MvpFrontendStartupTimerHandle;
/** If true, the player will use UMG touch controls even if not playing on mobile platforms */
UPROPERTY(EditAnywhere, Config, Category = "Input|Touch Controls")
bool bForceTouchControls = false;
@@ -56,6 +61,7 @@ protected:
/** Returns true if the player should use UMG touch controls */
bool ShouldUseTouchControls() const;
void ShowMvpFrontend();
public:
UFUNCTION(Exec)
+214 -24
View File
@@ -2,6 +2,7 @@
#include "AgrarianMvpFrontendWidget.h"
#include "GameFramework/PlayerController.h"
#include "InputCoreTypes.h"
#include "Rendering/DrawElements.h"
#include "Styling/CoreStyle.h"
@@ -32,7 +33,7 @@ FReply UAgrarianMvpFrontendWidget::NativeOnKeyDown(const FGeometry& InGeometry,
if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
{
SetActiveScreen(EAgrarianMvpFrontendScreen::JoinServer);
ContinueFromActiveScreen();
return FReply::Handled();
}
}
@@ -41,13 +42,22 @@ FReply UAgrarianMvpFrontendWidget::NativeOnKeyDown(const FGeometry& InGeometry,
const FKey Key = InKeyEvent.GetKey();
if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
{
SetActiveScreen(EAgrarianMvpFrontendScreen::Loading);
ContinueFromActiveScreen();
return FReply::Handled();
}
if (Key == EKeys::BackSpace || Key == EKeys::Escape)
{
SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
ReturnFromActiveScreen();
return FReply::Handled();
}
}
else if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
{
const FKey Key = InKeyEvent.GetKey();
if (Key == EKeys::Enter || Key == EKeys::SpaceBar)
{
ContinueFromActiveScreen();
return FReply::Handled();
}
}
@@ -55,6 +65,89 @@ FReply UAgrarianMvpFrontendWidget::NativeOnKeyDown(const FGeometry& InGeometry,
return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
}
FReply UAgrarianMvpFrontendWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
if (InMouseEvent.GetEffectingButton() != EKeys::LeftMouseButton)
{
return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
}
const FVector2D LocalMousePosition = InGeometry.AbsoluteToLocal(InMouseEvent.GetScreenSpacePosition());
float Scale = 1.0f;
FVector2D PanelPosition = FVector2D::ZeroVector;
FVector2D PanelSize = FVector2D::ZeroVector;
if (!GetPanelLayout(InGeometry.GetLocalSize(), Scale, PanelPosition, PanelSize))
{
return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
}
const float ContentX = PanelPosition.X + (44.0f * Scale);
const float ContentWidth = PanelSize.X - (88.0f * Scale);
if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
{
const FVector2D CardSize((ContentWidth - (24.0f * Scale)) * 0.5f, 206.0f * Scale);
const FVector2D MaleCardPosition(ContentX, PanelPosition.Y + (142.0f * Scale));
const FVector2D FemaleCardPosition(ContentX + CardSize.X + (24.0f * Scale), MaleCardPosition.Y);
const FVector2D ButtonPosition(ContentX, PanelPosition.Y + PanelSize.Y - (88.0f * Scale));
const FVector2D ButtonSize(FMath::Min(ContentWidth, 280.0f * Scale), 52.0f * Scale);
if (IsPointInside(LocalMousePosition, MaleCardPosition, CardSize))
{
SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultMale);
return FReply::Handled();
}
if (IsPointInside(LocalMousePosition, FemaleCardPosition, CardSize))
{
SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultFemale);
return FReply::Handled();
}
if (IsPointInside(LocalMousePosition, ButtonPosition, ButtonSize))
{
ContinueFromActiveScreen();
return FReply::Handled();
}
}
else if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
{
const float JoinContentX = PanelPosition.X + (48.0f * Scale);
const float JoinContentWidth = PanelSize.X - (96.0f * Scale);
const FVector2D ButtonPosition(JoinContentX, PanelPosition.Y + (300.0f * Scale));
const FVector2D ButtonSize(FMath::Min(JoinContentWidth, 330.0f * Scale), 58.0f * Scale);
const FVector2D BackButtonPosition(ButtonPosition.X + ButtonSize.X + (16.0f * Scale), ButtonPosition.Y);
const FVector2D BackButtonSize(FMath::Min(JoinContentWidth - ButtonSize.X - (16.0f * Scale), 180.0f * Scale), ButtonSize.Y);
if (IsPointInside(LocalMousePosition, ButtonPosition, ButtonSize))
{
ContinueFromActiveScreen();
return FReply::Handled();
}
if (BackButtonSize.X > 96.0f && IsPointInside(LocalMousePosition, BackButtonPosition, BackButtonSize))
{
ReturnFromActiveScreen();
return FReply::Handled();
}
}
else if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
{
const float LoadingContentX = PanelPosition.X + (48.0f * Scale);
const float LoadingContentWidth = PanelSize.X - (96.0f * Scale);
const FVector2D ButtonPosition(LoadingContentX, PanelPosition.Y + (318.0f * Scale));
const FVector2D ButtonSize(FMath::Min(LoadingContentWidth, 310.0f * Scale), 56.0f * Scale);
if (IsPointInside(LocalMousePosition, ButtonPosition, ButtonSize))
{
ContinueFromActiveScreen();
return FReply::Handled();
}
}
return FReply::Handled();
}
void UAgrarianMvpFrontendWidget::SetActiveScreen(EAgrarianMvpFrontendScreen NewScreen)
{
ActiveScreen = NewScreen;
@@ -91,13 +184,10 @@ int32 UAgrarianMvpFrontendWidget::NativePaint(
LayerId = Super::NativePaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
const FVector2D Size = AllottedGeometry.GetLocalSize();
const float Scale = FMath::Clamp(UiScale, 0.75f, 1.5f);
constexpr float MinimumPanelMargin = 24.0f;
constexpr float PreferredPanelWidth = 780.0f;
constexpr float PreferredPanelHeight = 430.0f;
const FVector2D AvailablePanelSize(
FMath::Max(320.0f, Size.X - (MinimumPanelMargin * 2.0f)),
FMath::Max(240.0f, Size.Y - (MinimumPanelMargin * 2.0f)));
float Scale = 1.0f;
FVector2D PanelPosition = FVector2D::ZeroVector;
FVector2D PanelSize = FVector2D::ZeroVector;
GetPanelLayout(Size, Scale, PanelPosition, PanelSize);
const FLinearColor BackdropColor = bUseHighContrast ? FLinearColor(0.0f, 0.0f, 0.0f, 0.96f) : FLinearColor(0.015f, 0.018f, 0.014f, 0.92f);
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);
@@ -110,13 +200,6 @@ int32 UAgrarianMvpFrontendWidget::NativePaint(
ESlateDrawEffect::None,
BackdropColor);
const FVector2D PanelSize(
FMath::Min(AvailablePanelSize.X, PreferredPanelWidth * Scale),
FMath::Min(AvailablePanelSize.Y, PreferredPanelHeight * Scale));
const FVector2D PanelPosition(
(Size.X - PanelSize.X) * 0.5f,
(Size.Y - PanelSize.Y) * 0.5f);
FSlateDrawElement::MakeBox(
OutDrawElements,
++LayerId,
@@ -153,6 +236,73 @@ int32 UAgrarianMvpFrontendWidget::NativePaint(
return LayerId;
}
bool UAgrarianMvpFrontendWidget::GetPanelLayout(const FVector2D& WidgetSize, float& OutScale, FVector2D& OutPanelPosition, FVector2D& OutPanelSize) const
{
OutScale = FMath::Clamp(UiScale, 0.75f, 1.5f);
constexpr float MinimumPanelMargin = 24.0f;
constexpr float PreferredPanelWidth = 780.0f;
constexpr float PreferredPanelHeight = 430.0f;
const FVector2D AvailablePanelSize(
FMath::Max(320.0f, WidgetSize.X - (MinimumPanelMargin * 2.0f)),
FMath::Max(240.0f, WidgetSize.Y - (MinimumPanelMargin * 2.0f)));
OutPanelSize = FVector2D(
FMath::Min(AvailablePanelSize.X, PreferredPanelWidth * OutScale),
FMath::Min(AvailablePanelSize.Y, PreferredPanelHeight * OutScale));
OutPanelPosition = FVector2D(
(WidgetSize.X - OutPanelSize.X) * 0.5f,
(WidgetSize.Y - OutPanelSize.Y) * 0.5f);
return WidgetSize.X > 0.0f && WidgetSize.Y > 0.0f;
}
bool UAgrarianMvpFrontendWidget::IsPointInside(const FVector2D& Point, const FVector2D& Position, const FVector2D& Size) const
{
return Point.X >= Position.X
&& Point.Y >= Position.Y
&& Point.X <= Position.X + Size.X
&& Point.Y <= Position.Y + Size.Y;
}
void UAgrarianMvpFrontendWidget::ContinueFromActiveScreen()
{
if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
{
SetActiveScreen(EAgrarianMvpFrontendScreen::JoinServer);
return;
}
if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
{
SetActiveScreen(EAgrarianMvpFrontendScreen::Loading);
return;
}
if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
{
CompleteFrontendFlow();
}
}
void UAgrarianMvpFrontendWidget::ReturnFromActiveScreen()
{
if (ActiveScreen == EAgrarianMvpFrontendScreen::JoinServer)
{
SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
}
}
void UAgrarianMvpFrontendWidget::CompleteFrontendFlow()
{
if (APlayerController* PlayerController = GetOwningPlayer())
{
PlayerController->SetInputMode(FInputModeGameOnly());
PlayerController->bShowMouseCursor = false;
}
RemoveFromParent();
}
void UAgrarianMvpFrontendWidget::DrawMainMenu(
FSlateWindowElementList& OutDrawElements,
int32& LayerId,
@@ -200,8 +350,8 @@ void UAgrarianMvpFrontendWidget::DrawCharacterSelection(
const FSlateFontInfo CardTitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(22.0f * Scale));
const FSlateFontInfo LabelFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(15.0f * Scale));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Choose your first settler")), FVector2D(ContentX, PanelPosition.Y + (34.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("MVP placeholder landing page before entering Ground Zero.")), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (82.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Choose your first pioneer")), FVector2D(ContentX, PanelPosition.Y + (34.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Select the person who will step into Ground Zero.")), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (82.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));
const FVector2D CardSize((ContentWidth - (24.0f * Scale)) * 0.5f, 206.0f * Scale);
const FVector2D MaleCardPosition(ContentX, PanelPosition.Y + (142.0f * Scale));
@@ -254,7 +404,18 @@ void UAgrarianMvpFrontendWidget::DrawCharacterSelection(
DrawCharacterCard(MaleCardPosition, FText::FromString(TEXT("Young adult male")), FText::FromString(TEXT("Average proportions, survival baseline, placeholder visual.")), FLinearColor(0.36f, 0.58f, 0.78f, 1.0f), SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultMale);
DrawCharacterCard(FemaleCardPosition, FText::FromString(TEXT("Young adult female")), FText::FromString(TEXT("Average proportions, survival baseline, placeholder visual.")), FLinearColor(0.56f, 0.68f, 0.46f, 1.0f), SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale);
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Selected: {0}. Use Left/Right or A/D to choose; both choices enter the same MVP survival baseline.")), GetSelectedCharacterLabel()), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, LabelFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
const FVector2D ButtonPosition(ContentX, PanelPosition.Y + PanelSize.Y - (88.0f * Scale));
const FVector2D ButtonSize(FMath::Min(ContentWidth, 280.0f * Scale), 52.0f * Scale);
FSlateDrawElement::MakeBox(
OutDrawElements,
++LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(ButtonSize), FSlateLayoutTransform(FVector2f(ButtonPosition))),
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
ESlateDrawEffect::None,
FLinearColor(0.35f, 0.58f, 0.30f, 0.95f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Continue")), ButtonPosition + FVector2D(22.0f * Scale, 10.0f * Scale), ButtonSize.X - (44.0f * Scale), CardTitleFont, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Selected {0}: {1}. Click a card or use Left/Right, then continue.")), GetSelectedRoleLabel(), GetSelectedCharacterLabel()), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (26.0f * Scale)), ContentWidth, LabelFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}
void UAgrarianMvpFrontendWidget::DrawJoinServer(
@@ -273,7 +434,7 @@ void UAgrarianMvpFrontendWidget::DrawJoinServer(
const FSlateFontInfo HintFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(15.0f * Scale));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Join MVP server")), FVector2D(ContentX, PanelPosition.Y + (44.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Character: {0}")), GetSelectedCharacterLabel()), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (94.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("{0}: {1}")), GetSelectedRoleLabel(), GetSelectedCharacterLabel()), FVector2D(ContentX + (2.0f * Scale), PanelPosition.Y + (94.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));
const FVector2D AddressPanelPosition(ContentX, PanelPosition.Y + (164.0f * Scale));
const FVector2D AddressPanelSize(ContentWidth, 96.0f * Scale);
@@ -299,7 +460,20 @@ void UAgrarianMvpFrontendWidget::DrawJoinServer(
FLinearColor(0.35f, 0.58f, 0.30f, 0.95f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Continue to loading")), ButtonPosition + FVector2D(22.0f * Scale, 12.0f * Scale), ButtonSize.X - (44.0f * Scale), AddressFont, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Press Backspace or Escape to return to character selection.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
const FVector2D BackButtonPosition(ButtonPosition.X + ButtonSize.X + (16.0f * Scale), ButtonPosition.Y);
const FVector2D BackButtonSize(FMath::Min(ContentWidth - ButtonSize.X - (16.0f * Scale), 180.0f * Scale), ButtonSize.Y);
if (BackButtonSize.X > 96.0f)
{
FSlateDrawElement::MakeBox(
OutDrawElements,
++LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(BackButtonSize), FSlateLayoutTransform(FVector2f(BackButtonPosition))),
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
ESlateDrawEffect::None,
FLinearColor(0.12f, 0.15f, 0.11f, 0.95f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Back")), BackButtonPosition + FVector2D(22.0f * Scale, 12.0f * Scale), BackButtonSize.X - (44.0f * Scale), AddressFont, FLinearColor(0.82f, 0.88f, 0.76f, 1.0f));
}
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Click continue, press Enter, or press Backspace/Escape to revise your pioneer.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}
void UAgrarianMvpFrontendWidget::DrawLoading(
@@ -337,8 +511,19 @@ void UAgrarianMvpFrontendWidget::DrawLoading(
ESlateDrawEffect::None,
FLinearColor(0.45f, 0.72f, 0.40f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("Character: {0} | Server: {1}")), GetSelectedCharacterLabel(), JoinServerAddress), FVector2D(ContentX, PanelPosition.Y + (270.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.78f, 0.84f, 0.72f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("MVP loading placeholder; final connection and map handoff will attach here.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::Format(FText::FromString(TEXT("{0}: {1} | Server: {2}")), GetSelectedRoleLabel(), GetSelectedCharacterLabel(), JoinServerAddress), FVector2D(ContentX, PanelPosition.Y + (270.0f * Scale)), ContentWidth, BodyFont, FLinearColor(0.78f, 0.84f, 0.72f, 1.0f));
const FVector2D ButtonPosition(ContentX, PanelPosition.Y + (318.0f * Scale));
const FVector2D ButtonSize(FMath::Min(ContentWidth, 310.0f * Scale), 56.0f * Scale);
FSlateDrawElement::MakeBox(
OutDrawElements,
++LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(ButtonSize), FSlateLayoutTransform(FVector2f(ButtonPosition))),
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
ESlateDrawEffect::None,
FLinearColor(0.35f, 0.58f, 0.30f, 0.95f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Enter Ground Zero")), ButtonPosition + FVector2D(22.0f * Scale, 11.0f * Scale), ButtonSize.X - (44.0f * Scale), BodyFont, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f));
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Click or press Enter to close the MVP menu and begin testing.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
}
FText UAgrarianMvpFrontendWidget::GetSelectedCharacterLabel() const
@@ -348,6 +533,11 @@ FText UAgrarianMvpFrontendWidget::GetSelectedCharacterLabel() const
: FText::FromString(TEXT("young adult male"));
}
FText UAgrarianMvpFrontendWidget::GetSelectedRoleLabel() const
{
return FText::FromString(TEXT("Pioneer"));
}
void UAgrarianMvpFrontendWidget::DrawTextAt(
FSlateWindowElementList& OutDrawElements,
int32& LayerId,
@@ -68,6 +68,7 @@ protected:
virtual void NativeConstruct() override;
virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override;
virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
virtual int32 NativePaint(
const FPaintArgs& Args,
@@ -79,6 +80,12 @@ protected:
bool bParentEnabled) const override;
private:
bool GetPanelLayout(const FVector2D& WidgetSize, float& OutScale, FVector2D& OutPanelPosition, FVector2D& OutPanelSize) const;
bool IsPointInside(const FVector2D& Point, const FVector2D& Position, const FVector2D& Size) const;
void ContinueFromActiveScreen();
void ReturnFromActiveScreen();
void CompleteFrontendFlow();
void DrawMainMenu(
FSlateWindowElementList& OutDrawElements,
int32& LayerId,
@@ -112,6 +119,7 @@ private:
float Scale) const;
FText GetSelectedCharacterLabel() const;
FText GetSelectedRoleLabel() const;
void DrawTextAt(
FSlateWindowElementList& OutDrawElements,