Add MVP character selection landing
This commit is contained in:
@@ -794,7 +794,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
|
||||||
|
|
||||||
- [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.
|
- [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.
|
- [x] After splash/startup screens, land on an MVP character selection landing page. The local player controller now opens the MVP frontend on `CharacterSelection`, and the native frontend widget paints a scalable character-selection landing page before gameplay.
|
||||||
- [ ] 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.
|
||||||
- [ ] Add loading screen.
|
- [ ] Add loading screen.
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
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.cpp": ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp",
|
||||||
|
"AGRARIAN_DEVELOPMENT_ROADMAP.md": ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md",
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECTED = {
|
||||||
|
"AgrarianMvpFrontendWidget.h": [
|
||||||
|
"CharacterSelection",
|
||||||
|
"DrawCharacterSelection",
|
||||||
|
],
|
||||||
|
"AgrarianMvpFrontendWidget.cpp": [
|
||||||
|
"EAgrarianMvpFrontendScreen::CharacterSelection",
|
||||||
|
"DrawCharacterSelection",
|
||||||
|
"Choose your first settler",
|
||||||
|
"Young adult male",
|
||||||
|
"Young adult female",
|
||||||
|
"MVP placeholder landing page",
|
||||||
|
],
|
||||||
|
"AgrarianGamePlayerController.cpp": [
|
||||||
|
"SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection)",
|
||||||
|
],
|
||||||
|
"AGRARIAN_DEVELOPMENT_ROADMAP.md": [
|
||||||
|
"[x] After splash/startup screens, land on an MVP character selection landing page.",
|
||||||
|
"`CharacterSelection`",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 character selection landing verification failed: " + "; ".join(missing))
|
||||||
|
|
||||||
|
print("Agrarian MVP character selection landing verification complete.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -88,7 +88,7 @@ void AAgrarianGamePlayerController::BeginPlay()
|
|||||||
MvpFrontendWidget = CreateWidget<UAgrarianMvpFrontendWidget>(this, MvpFrontendWidgetClass);
|
MvpFrontendWidget = CreateWidget<UAgrarianMvpFrontendWidget>(this, MvpFrontendWidgetClass);
|
||||||
if (MvpFrontendWidget)
|
if (MvpFrontendWidget)
|
||||||
{
|
{
|
||||||
MvpFrontendWidget->SetActiveScreen(EAgrarianMvpFrontendScreen::MainMenu);
|
MvpFrontendWidget->SetActiveScreen(EAgrarianMvpFrontendScreen::CharacterSelection);
|
||||||
MvpFrontendWidget->AddToPlayerScreen(10);
|
MvpFrontendWidget->AddToPlayerScreen(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ int32 UAgrarianMvpFrontendWidget::NativePaint(
|
|||||||
{
|
{
|
||||||
DrawMainMenu(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
|
DrawMainMenu(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
|
||||||
}
|
}
|
||||||
|
else if (ActiveScreen == EAgrarianMvpFrontendScreen::CharacterSelection)
|
||||||
|
{
|
||||||
|
DrawCharacterSelection(OutDrawElements, LayerId, AllottedGeometry, PanelPosition, PanelSize, Scale);
|
||||||
|
}
|
||||||
|
|
||||||
return LayerId;
|
return LayerId;
|
||||||
}
|
}
|
||||||
@@ -96,6 +100,66 @@ void UAgrarianMvpFrontendWidget::DrawMainMenu(
|
|||||||
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));
|
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::DrawCharacterSelection(
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32& LayerId,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FVector2D& PanelPosition,
|
||||||
|
const FVector2D& PanelSize,
|
||||||
|
float Scale) const
|
||||||
|
{
|
||||||
|
const float ContentX = PanelPosition.X + (44.0f * Scale);
|
||||||
|
const float ContentWidth = PanelSize.X - (88.0f * Scale);
|
||||||
|
const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", FMath::RoundToInt(34.0f * Scale));
|
||||||
|
const FSlateFontInfo BodyFont = FCoreStyle::GetDefaultFontStyle("Regular", FMath::RoundToInt(18.0f * Scale));
|
||||||
|
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));
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
auto DrawCharacterCard = [&](const FVector2D& CardPosition, const FText& Title, const FText& Summary, const FLinearColor& AccentColor)
|
||||||
|
{
|
||||||
|
FSlateDrawElement::MakeBox(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(CardSize), FSlateLayoutTransform(FVector2f(CardPosition))),
|
||||||
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
FLinearColor(0.055f, 0.065f, 0.05f, 0.95f));
|
||||||
|
|
||||||
|
FSlateDrawElement::MakeBox(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(CardSize.X, 3.0f * Scale), FSlateLayoutTransform(FVector2f(CardPosition))),
|
||||||
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
AccentColor);
|
||||||
|
|
||||||
|
const FVector2D PortraitPosition = CardPosition + FVector2D(24.0f * Scale, 42.0f * Scale);
|
||||||
|
const FVector2D PortraitSize(72.0f * Scale, 112.0f * Scale);
|
||||||
|
FSlateDrawElement::MakeBox(
|
||||||
|
OutDrawElements,
|
||||||
|
++LayerId,
|
||||||
|
AllottedGeometry.ToPaintGeometry(FVector2f(PortraitSize), FSlateLayoutTransform(FVector2f(PortraitPosition))),
|
||||||
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
||||||
|
ESlateDrawEffect::None,
|
||||||
|
FLinearColor(0.14f, 0.16f, 0.13f, 1.0f));
|
||||||
|
|
||||||
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, Title, CardPosition + FVector2D(116.0f * Scale, 42.0f * Scale), CardSize.X - (140.0f * Scale), CardTitleFont, FLinearColor(0.92f, 0.98f, 0.84f, 1.0f));
|
||||||
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, Summary, CardPosition + FVector2D(116.0f * Scale, 82.0f * Scale), CardSize.X - (140.0f * Scale), LabelFont, FLinearColor(0.72f, 0.78f, 0.68f, 1.0f));
|
||||||
|
};
|
||||||
|
|
||||||
|
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));
|
||||||
|
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));
|
||||||
|
|
||||||
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Selection is visual-only for this milestone; both choices enter the same MVP survival baseline.")), FVector2D(ContentX, PanelPosition.Y + PanelSize.Y - (46.0f * Scale)), ContentWidth, LabelFont, FLinearColor(0.62f, 0.68f, 0.58f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
void UAgrarianMvpFrontendWidget::DrawTextAt(
|
void UAgrarianMvpFrontendWidget::DrawTextAt(
|
||||||
FSlateWindowElementList& OutDrawElements,
|
FSlateWindowElementList& OutDrawElements,
|
||||||
int32& LayerId,
|
int32& LayerId,
|
||||||
|
|||||||
@@ -61,6 +61,14 @@ private:
|
|||||||
const FVector2D& PanelSize,
|
const FVector2D& PanelSize,
|
||||||
float Scale) const;
|
float Scale) const;
|
||||||
|
|
||||||
|
void DrawCharacterSelection(
|
||||||
|
FSlateWindowElementList& OutDrawElements,
|
||||||
|
int32& LayerId,
|
||||||
|
const FGeometry& AllottedGeometry,
|
||||||
|
const FVector2D& PanelPosition,
|
||||||
|
const FVector2D& PanelSize,
|
||||||
|
float Scale) const;
|
||||||
|
|
||||||
void DrawTextAt(
|
void DrawTextAt(
|
||||||
FSlateWindowElementList& OutDrawElements,
|
FSlateWindowElementList& OutDrawElements,
|
||||||
int32& LayerId,
|
int32& LayerId,
|
||||||
|
|||||||
Reference in New Issue
Block a user