Add MVP main menu placeholder
This commit is contained in:
@@ -793,7 +793,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
|||||||
|
|
||||||
## 0.1.N MVP UI And UX
|
## 0.1.N MVP UI And UX
|
||||||
|
|
||||||
- [ ] Add main menu placeholder.
|
- [x] Add main menu placeholder. Added native `UAgrarianMvpFrontendWidget` with a scalable painted main menu panel and local player-controller spawning so the MVP frontend has an owned placeholder instead of relying on template UI.
|
||||||
- [ ] After splash/startup screens, land on an MVP character selection landing page.
|
- [ ] After splash/startup screens, land on an MVP character selection landing page.
|
||||||
- [ ] Let players choose a realistic young adult male or female character with average proportions for the MVP.
|
- [ ] Let players choose a realistic young adult male or female character with average proportions for the MVP.
|
||||||
- [ ] Add join server screen.
|
- [ ] Add join server screen.
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
FILES = {
|
||||||
|
"AgrarianMvpFrontendWidget.h": ROOT / "Source" / "AgrarianGame" / "AgrarianMvpFrontendWidget.h",
|
||||||
|
"AgrarianMvpFrontendWidget.cpp": ROOT / "Source" / "AgrarianGame" / "AgrarianMvpFrontendWidget.cpp",
|
||||||
|
"AgrarianGamePlayerController.h": ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.h",
|
||||||
|
"AgrarianGamePlayerController.cpp": ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp",
|
||||||
|
"AGRARIAN_DEVELOPMENT_ROADMAP.md": ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md",
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECTED = {
|
||||||
|
"AgrarianMvpFrontendWidget.h": [
|
||||||
|
"UAgrarianMvpFrontendWidget",
|
||||||
|
"EAgrarianMvpFrontendScreen",
|
||||||
|
"MainMenu",
|
||||||
|
"MainMenuTitle",
|
||||||
|
"MVP investor build",
|
||||||
|
"PrimaryActionLabel",
|
||||||
|
"UiScale",
|
||||||
|
],
|
||||||
|
"AgrarianMvpFrontendWidget.cpp": [
|
||||||
|
"DrawMainMenu",
|
||||||
|
"Placeholder flow",
|
||||||
|
"FMath::Clamp(UiScale",
|
||||||
|
],
|
||||||
|
"AgrarianGamePlayerController.h": [
|
||||||
|
"MvpFrontendWidgetClass",
|
||||||
|
"MvpFrontendWidget",
|
||||||
|
],
|
||||||
|
"AgrarianGamePlayerController.cpp": [
|
||||||
|
"UAgrarianMvpFrontendWidget::StaticClass()",
|
||||||
|
"EAgrarianMvpFrontendScreen::MainMenu",
|
||||||
|
"AddToPlayerScreen(10)",
|
||||||
|
],
|
||||||
|
"AGRARIAN_DEVELOPMENT_ROADMAP.md": [
|
||||||
|
"[x] Add main menu placeholder.",
|
||||||
|
"UAgrarianMvpFrontendWidget",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
missing = []
|
||||||
|
for label, path in FILES.items():
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
for snippet in EXPECTED[label]:
|
||||||
|
if snippet not in text:
|
||||||
|
missing.append(f"{label}: {snippet}")
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
raise RuntimeError("MVP main menu placeholder verification failed: " + "; ".join(missing))
|
||||||
|
|
||||||
|
print("Agrarian MVP main menu placeholder verification complete.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "AgrarianGameCharacter.h"
|
#include "AgrarianGameCharacter.h"
|
||||||
#include "AgrarianInventoryComponent.h"
|
#include "AgrarianInventoryComponent.h"
|
||||||
#include "AgrarianItemPickup.h"
|
#include "AgrarianItemPickup.h"
|
||||||
|
#include "AgrarianMvpFrontendWidget.h"
|
||||||
#include "AgrarianPersistenceSubsystem.h"
|
#include "AgrarianPersistenceSubsystem.h"
|
||||||
#include "AgrarianShelterActor.h"
|
#include "AgrarianShelterActor.h"
|
||||||
#include "AgrarianSurvivalComponent.h"
|
#include "AgrarianSurvivalComponent.h"
|
||||||
@@ -77,6 +78,21 @@ void AAgrarianGamePlayerController::BeginPlay()
|
|||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
if (IsLocalPlayerController())
|
||||||
|
{
|
||||||
|
if (!MvpFrontendWidgetClass)
|
||||||
|
{
|
||||||
|
MvpFrontendWidgetClass = UAgrarianMvpFrontendWidget::StaticClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
MvpFrontendWidget = CreateWidget<UAgrarianMvpFrontendWidget>(this, MvpFrontendWidgetClass);
|
||||||
|
if (MvpFrontendWidget)
|
||||||
|
{
|
||||||
|
MvpFrontendWidget->SetActiveScreen(EAgrarianMvpFrontendScreen::MainMenu);
|
||||||
|
MvpFrontendWidget->AddToPlayerScreen(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// only spawn touch controls on local player controllers
|
// only spawn touch controls on local player controllers
|
||||||
if (ShouldUseTouchControls() && IsLocalPlayerController())
|
if (ShouldUseTouchControls() && IsLocalPlayerController())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
class UInputMappingContext;
|
class UInputMappingContext;
|
||||||
class UUserWidget;
|
class UUserWidget;
|
||||||
|
class UAgrarianMvpFrontendWidget;
|
||||||
class AAgrarianShelterActor;
|
class AAgrarianShelterActor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +38,12 @@ protected:
|
|||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TObjectPtr<UUserWidget> MobileControlsWidget;
|
TObjectPtr<UUserWidget> MobileControlsWidget;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, Category = "Agrarian|MVP UI")
|
||||||
|
TSubclassOf<UAgrarianMvpFrontendWidget> MvpFrontendWidgetClass;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UAgrarianMvpFrontendWidget> MvpFrontendWidget;
|
||||||
|
|
||||||
/** If true, the player will use UMG touch controls even if not playing on mobile platforms */
|
/** If true, the player will use UMG touch controls even if not playing on mobile platforms */
|
||||||
UPROPERTY(EditAnywhere, Config, Category = "Input|Touch Controls")
|
UPROPERTY(EditAnywhere, Config, Category = "Input|Touch Controls")
|
||||||
bool bForceTouchControls = false;
|
bool bForceTouchControls = false;
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright Pacificao. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "AgrarianMvpFrontendWidget.h"
|
||||||
|
|
||||||
|
#include "Rendering/DrawElements.h"
|
||||||
|
#include "Styling/CoreStyle.h"
|
||||||
|
|
||||||
|
void UAgrarianMvpFrontendWidget::SetActiveScreen(EAgrarianMvpFrontendScreen NewScreen)
|
||||||
|
{
|
||||||
|
ActiveScreen = NewScreen;
|
||||||
|
InvalidateLayoutAndVolatility();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 UAgrarianMvpFrontendWidget::NativePaint(
|
||||||
|
const FPaintArgs& Args,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FSlateRect& MyCullingRect,
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32 LayerId,
|
||||||
|
const FWidgetStyle& InWidgetStyle,
|
||||||
|
bool bParentEnabled) const
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
FSlateDrawElement::MakeBox(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(Size), FSlateLayoutTransform(FVector2f::ZeroVector)),
|
||||||
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
FLinearColor(0.015f, 0.018f, 0.014f, 0.92f));
|
||||||
|
|
||||||
|
const FVector2D PanelSize(
|
||||||
|
FMath::Min(Size.X - 48.0f, 780.0f * Scale),
|
||||||
|
FMath::Min(Size.Y - 48.0f, 430.0f * Scale));
|
||||||
|
const FVector2D PanelPosition(
|
||||||
|
(Size.X - PanelSize.X) * 0.5f,
|
||||||
|
(Size.Y - PanelSize.Y) * 0.5f);
|
||||||
|
|
||||||
|
FSlateDrawElement::MakeBox(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(PanelSize), FSlateLayoutTransform(FVector2f(PanelPosition))),
|
||||||
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
FLinearColor(0.035f, 0.045f, 0.034f, 0.96f));
|
||||||
|
|
||||||
|
FSlateDrawElement::MakeBox(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(PanelSize.X, 4.0f * Scale), FSlateLayoutTransform(FVector2f(PanelPosition))),
|
||||||
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
FLinearColor(0.45f, 0.72f, 0.40f, 1.0f));
|
||||||
|
|
||||||
|
if (ActiveScreen == EAgrarianMvpFrontendScreen::MainMenu)
|
||||||
|
{
|
||||||
|
DrawMainMenu(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LayerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UAgrarianMvpFrontendWidget::DrawMainMenu(
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32& LayerId,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FVector2D& PanelPosition,
|
||||||
|
const FVector2D& PanelSize,
|
||||||
|
float Scale) const
|
||||||
|
{
|
||||||
|
const float ContentX = PanelPosition.X + (48.0f * Scale);
|
||||||
|
const float ContentWidth = PanelSize.X - (96.0f * Scale);
|
||||||
|
const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(54.0f * Scale));
|
||||||
|
const FSlateFontInfo SubtitleFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(22.0f * Scale));
|
||||||
|
const FSlateFontInfo ButtonFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(24.0f * Scale));
|
||||||
|
const FSlateFontInfo HintFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(16.0f * Scale));
|
||||||
|
|
||||||
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, MainMenuTitle, FVector2D(ContentX, PanelPosition.Y + (58.0f * Scale)), ContentWidth, TitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
|
||||||
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, MainMenuSubtitle, FVector2D(ContentX + (4.0f * Scale), PanelPosition.Y + (128.0f * Scale)), ContentWidth, SubtitleFont, FLinearColor(0.72f, 0.80f, 0.68f, 1.0f));
|
||||||
|
|
||||||
|
const FVector2D ButtonPosition(ContentX, PanelPosition.Y + (230.0f * Scale));
|
||||||
|
const FVector2D ButtonSize(FMath::Min(ContentWidth, 280.0f * Scale), 58.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, PrimaryActionLabel, ButtonPosition + FVector2D(22.0f * Scale, 12.0f * Scale), ButtonSize.X - (44.0f * Scale), ButtonFont, FLinearColor(0.96f, 1.0f, 0.90f, 1.0f));
|
||||||
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Placeholder flow: splash, startup credits, character selection, join, loading, then Ground Zero.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (66.0f * Scale)), ContentWidth, HintFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UAgrarianMvpFrontendWidget::DrawTextAt(
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32& LayerId,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FText& Text,
|
||||||
|
const FVector2D& Position,
|
||||||
|
float Width,
|
||||||
|
const FSlateFontInfo& Font,
|
||||||
|
const FLinearColor& Color) const
|
||||||
|
{
|
||||||
|
FSlateDrawElement::MakeText(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(FMath::Max(96.0f, Width), Font.Size + 18.0f), FSlateLayoutTransform(FVector2f(Position))),
|
||||||
|
Text,
|
||||||
|
Font,
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
Color);
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright Pacificao. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Blueprint/UserWidget.h"
|
||||||
|
#include "AgrarianMvpFrontendWidget.generated.h"
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EAgrarianMvpFrontendScreen : uint8
|
||||||
|
{
|
||||||
|
MainMenu,
|
||||||
|
CharacterSelection,
|
||||||
|
JoinServer,
|
||||||
|
Loading
|
||||||
|
};
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class AGRARIANGAME_API UAgrarianMvpFrontendWidget : public UUserWidget
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|MVP UI")
|
||||||
|
EAgrarianMvpFrontendScreen ActiveScreen = EAgrarianMvpFrontendScreen::MainMenu;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|MVP UI")
|
||||||
|
FText MainMenuTitle = FText::FromString(TEXT("Agrarian"));
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|MVP UI")
|
||||||
|
FText MainMenuSubtitle = FText::FromString(TEXT("MVP investor build"));
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|MVP UI")
|
||||||
|
FText PrimaryActionLabel = FText::FromString(TEXT("Begin"));
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|MVP UI")
|
||||||
|
FText JoinServerAddress = FText::FromString(TEXT("play.agrariangame.com:7777"));
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|MVP UI", meta = (ClampMin = "0.75", ClampMax = "1.5"))
|
||||||
|
float UiScale = 1.0f;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Agrarian|MVP UI")
|
||||||
|
void SetActiveScreen(EAgrarianMvpFrontendScreen NewScreen);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int32 NativePaint(
|
||||||
|
const FPaintArgs& Args,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FSlateRect& MyCullingRect,
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32 LayerId,
|
||||||
|
const FWidgetStyle& InWidgetStyle,
|
||||||
|
bool bParentEnabled) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DrawMainMenu(
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32& LayerId,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FVector2D& PanelPosition,
|
||||||
|
const FVector2D& PanelSize,
|
||||||
|
float Scale) const;
|
||||||
|
|
||||||
|
void DrawTextAt(
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32& LayerId,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FText& Text,
|
||||||
|
const FVector2D& Position,
|
||||||
|
float Width,
|
||||||
|
const FSlateFontInfo& Font,
|
||||||
|
const FLinearColor& Color) const;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user