351 lines
15 KiB
C++
351 lines
15 KiB
C++
// Copyright Pacificao. All Rights Reserved.
|
|
|
|
#include "AgrarianDemoNoticeWidget.h"
|
|
|
|
#include "Engine/World.h"
|
|
#include "Rendering/DrawElements.h"
|
|
#include "Styling/CoreStyle.h"
|
|
|
|
namespace
|
|
{
|
|
struct FAgrarianCreditCard
|
|
{
|
|
const TCHAR* Name;
|
|
const TCHAR* Role;
|
|
FLinearColor AccentColor;
|
|
int32 IllustrationIndex;
|
|
float HoldSeconds;
|
|
};
|
|
|
|
const FAgrarianCreditCard CreditCards[] = {
|
|
{ TEXT("Nathan Slaven"), TEXT("Lead Developer"), FLinearColor(0.70f, 0.90f, 0.46f, 1.0f), 0, 2.05f },
|
|
{ TEXT("Hunter Slaven"), TEXT("Junior Developer"), FLinearColor(0.36f, 0.72f, 0.96f, 1.0f), 1, 2.05f },
|
|
{ TEXT("Lisa Reiley"), TEXT("Quality Control"), FLinearColor(0.95f, 0.72f, 0.42f, 1.0f), 2, 2.05f },
|
|
{ TEXT("River Slaven"), TEXT("Alpha Game Tester"), FLinearColor(0.56f, 0.82f, 0.66f, 1.0f), 3, 2.05f },
|
|
{ TEXT("Fisher Slaven"), TEXT("Beta Game Tester"), FLinearColor(0.56f, 0.62f, 0.98f, 1.0f), 4, 2.05f },
|
|
{ TEXT("Funding"), TEXT("Cherished individuals, Pacificao seed funding, and Lina Family Investment Funds"), FLinearColor(0.92f, 0.84f, 0.54f, 1.0f), 5, 3.0f },
|
|
};
|
|
|
|
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()
|
|
{
|
|
Super::NativeConstruct();
|
|
CreditsStartTimeSeconds = GetWorld() ? GetWorld()->GetTimeSeconds() : 0.0f;
|
|
}
|
|
|
|
int32 UAgrarianDemoNoticeWidget::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 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);
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(PanelWidth, PanelHeight), FSlateLayoutTransform(FVector2f(PanelPosition))),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
FLinearColor(0.02f, 0.03f, 0.025f, 0.82f));
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(PanelWidth, 3.0f), FSlateLayoutTransform(FVector2f(PanelPosition))),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
FLinearColor(0.45f, 0.72f, 0.40f, 1.0f));
|
|
|
|
const FSlateFontInfo MottoFont = FCoreStyle::GetDefaultFontStyle("Bold", 30);
|
|
const FSlateFontInfo VersionFont = FCoreStyle::GetDefaultFontStyle("Regular", 18);
|
|
const FSlateFontInfo NoticeFont = FCoreStyle::GetDefaultFontStyle("Regular", 16);
|
|
|
|
DrawCenteredText(OutDrawElements, LayerId, AllottedGeometry, Motto, PanelPosition.Y + 34.0f, MottoFont, FLinearColor(0.86f, 0.94f, 0.78f, 1.0f));
|
|
DrawCenteredText(OutDrawElements, LayerId, AllottedGeometry, VersionLabel, PanelPosition.Y + 94.0f, VersionFont, FLinearColor(0.82f, 0.86f, 0.78f, 1.0f));
|
|
DrawCenteredText(OutDrawElements, LayerId, AllottedGeometry, DemoNotice, PanelPosition.Y + 126.0f, NoticeFont, FLinearColor(0.78f, 0.82f, 0.75f, 1.0f));
|
|
DrawCenteredText(OutDrawElements, LayerId, AllottedGeometry, CopyrightNotice, PanelPosition.Y + 158.0f, NoticeFont, FLinearColor(0.66f, 0.70f, 0.64f, 1.0f));
|
|
|
|
DrawCinematicCredits(OutDrawElements, LayerId, AllottedGeometry);
|
|
|
|
return LayerId;
|
|
}
|
|
|
|
void UAgrarianDemoNoticeWidget::DrawCenteredText(
|
|
FSlateWindowElementList& OutDrawElements,
|
|
int32& LayerId,
|
|
const FGeometry& AllottedGeometry,
|
|
const FText& Text,
|
|
float Y,
|
|
const FSlateFontInfo& Font,
|
|
const FLinearColor& Color) const
|
|
{
|
|
const FVector2D Size = AllottedGeometry.GetLocalSize();
|
|
const FString TextString = Text.ToString();
|
|
const float EstimatedWidth = FMath::Min(Size.X - 96.0f, static_cast<float>(TextString.Len()) * Font.Size * 0.52f);
|
|
const FVector2D TextPosition((Size.X - EstimatedWidth) * 0.5f, Y);
|
|
|
|
FSlateDrawElement::MakeText(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(EstimatedWidth, Font.Size + 12.0f), FSlateLayoutTransform(FVector2f(TextPosition))),
|
|
Text,
|
|
Font,
|
|
ESlateDrawEffect::None,
|
|
Color);
|
|
}
|
|
|
|
void UAgrarianDemoNoticeWidget::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);
|
|
}
|
|
|
|
void UAgrarianDemoNoticeWidget::DrawCinematicCredits(
|
|
FSlateWindowElementList& OutDrawElements,
|
|
int32& LayerId,
|
|
const FGeometry& AllottedGeometry) const
|
|
{
|
|
const UWorld* World = GetWorld();
|
|
if (!World)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FVector2D Size = AllottedGeometry.GetLocalSize();
|
|
const float Elapsed = World->GetTimeSeconds() - CreditsStartTimeSeconds;
|
|
const float IntroDelay = 0.55f;
|
|
const float SlamSeconds = 0.28f;
|
|
const float ExitSeconds = 0.48f;
|
|
const float GapSeconds = 0.16f;
|
|
|
|
float TimelineCursor = IntroDelay;
|
|
int32 ActiveIndex = INDEX_NONE;
|
|
float LocalTime = 0.0f;
|
|
for (int32 Index = 0; Index < UE_ARRAY_COUNT(CreditCards); ++Index)
|
|
{
|
|
const float CardDuration = SlamSeconds + CreditCards[Index].HoldSeconds + ExitSeconds + GapSeconds;
|
|
if (Elapsed >= TimelineCursor && Elapsed < TimelineCursor + CardDuration)
|
|
{
|
|
ActiveIndex = Index;
|
|
LocalTime = Elapsed - TimelineCursor;
|
|
break;
|
|
}
|
|
TimelineCursor += CardDuration;
|
|
}
|
|
|
|
if (ActiveIndex == INDEX_NONE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FAgrarianCreditCard& Card = CreditCards[ActiveIndex];
|
|
const bool bEntering = LocalTime < SlamSeconds;
|
|
const bool bExiting = LocalTime > SlamSeconds + Card.HoldSeconds;
|
|
const float EnterAlpha = bEntering ? SmoothStep(LocalTime / SlamSeconds) : 1.0f;
|
|
const float ExitAlpha = bExiting ? 1.0f - SmoothStep((LocalTime - SlamSeconds - Card.HoldSeconds) / ExitSeconds) : 1.0f;
|
|
const float Alpha = FMath::Clamp(EnterAlpha * ExitAlpha, 0.0f, 1.0f);
|
|
const float ImpactOvershoot = bEntering ? FMath::Sin((LocalTime / SlamSeconds) * PI) * 28.0f : 0.0f;
|
|
|
|
const float PanelWidth = FMath::Min(1120.0f, FMath::Max(420.0f, Size.X - 112.0f));
|
|
const float PanelHeight = FMath::Min(330.0f, FMath::Max(220.0f, Size.Y - 340.0f));
|
|
const FVector2D TargetPosition((Size.X - PanelWidth) * 0.5f, FMath::Max(275.0f, (Size.Y - PanelHeight) * 0.5f + 72.0f));
|
|
const float EnterOffset = bEntering ? FMath::Lerp(-Size.X * 0.85f, ImpactOvershoot, SmoothStep(LocalTime / SlamSeconds)) : 0.0f;
|
|
const float ExitOffset = bExiting ? FMath::Lerp(0.0f, Size.X * 0.9f, SmoothStep((LocalTime - SlamSeconds - Card.HoldSeconds) / ExitSeconds)) : 0.0f;
|
|
const FVector2D PanelPosition(TargetPosition.X + EnterOffset + ExitOffset, TargetPosition.Y);
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(Size), FSlateLayoutTransform(FVector2f::ZeroVector)),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
FLinearColor(0.0f, 0.0f, 0.0f, 0.34f * Alpha));
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(PanelWidth, PanelHeight), FSlateLayoutTransform(FVector2f(PanelPosition))),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
FLinearColor(0.015f, 0.018f, 0.014f, 0.92f * Alpha));
|
|
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(PanelWidth, 5.0f), FSlateLayoutTransform(FVector2f(PanelPosition))),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
FLinearColor(Card.AccentColor.R, Card.AccentColor.G, Card.AccentColor.B, Alpha));
|
|
|
|
const FVector2D ArtSize(FMath::Min(275.0f, PanelWidth * 0.32f), PanelHeight - 64.0f);
|
|
const FVector2D ArtPosition(PanelPosition.X + 32.0f, PanelPosition.Y + 32.0f);
|
|
DrawCreditIllustration(OutDrawElements, LayerId, AllottedGeometry, ArtPosition, ArtSize, Card.IllustrationIndex, Card.AccentColor, Alpha);
|
|
|
|
const float TextX = ArtPosition.X + ArtSize.X + 42.0f;
|
|
const float TextWidth = PanelPosition.X + PanelWidth - TextX - 36.0f;
|
|
const FSlateFontInfo NameFont = FCoreStyle::GetDefaultFontStyle("Bold", ActiveIndex == 5 ? 46 : 56);
|
|
const FSlateFontInfo RoleFont = FCoreStyle::GetDefaultFontStyle("Regular", ActiveIndex == 5 ? 22 : 28);
|
|
const FSlateFontInfo LabelFont = FCoreStyle::GetDefaultFontStyle("Regular", 16);
|
|
const float NameY = PanelPosition.Y + (ActiveIndex == 5 ? 76.0f : 92.0f);
|
|
|
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(Card.Name), FVector2D(TextX, NameY), TextWidth, NameFont, FLinearColor(0.94f, 0.98f, 0.88f, Alpha));
|
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(Card.Role), FVector2D(TextX + 4.0f, NameY + 76.0f), TextWidth, RoleFont, FLinearColor(Card.AccentColor.R, Card.AccentColor.G, Card.AccentColor.B, Alpha));
|
|
DrawTextAt(OutDrawElements, LayerId, AllottedGeometry, FText::FromString(TEXT("Agrarian startup credits")), FVector2D(TextX + 6.0f, PanelPosition.Y + PanelHeight - 58.0f), TextWidth, LabelFont, FLinearColor(0.64f, 0.70f, 0.60f, 0.82f * Alpha));
|
|
}
|
|
|
|
void UAgrarianDemoNoticeWidget::DrawCreditIllustration(
|
|
FSlateWindowElementList& OutDrawElements,
|
|
int32& LayerId,
|
|
const FGeometry& AllottedGeometry,
|
|
const FVector2D& Position,
|
|
const FVector2D& Size,
|
|
int32 IllustrationIndex,
|
|
const FLinearColor& AccentColor,
|
|
float Alpha) const
|
|
{
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(Size), FSlateLayoutTransform(FVector2f(Position))),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
FLinearColor(0.07f, 0.08f, 0.065f, 0.96f * Alpha));
|
|
|
|
const FVector2D Center = Position + (Size * 0.5f);
|
|
const FLinearColor SoftAccent(AccentColor.R, AccentColor.G, AccentColor.B, 0.28f * Alpha);
|
|
const FLinearColor StrongAccent(AccentColor.R, AccentColor.G, AccentColor.B, Alpha);
|
|
|
|
auto DrawBox = [&](const FVector2D& BoxPosition, const FVector2D& BoxSize, const FLinearColor& Color)
|
|
{
|
|
FSlateDrawElement::MakeBox(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(FVector2f(BoxSize), FSlateLayoutTransform(FVector2f(BoxPosition))),
|
|
FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),
|
|
ESlateDrawEffect::None,
|
|
Color);
|
|
};
|
|
|
|
auto DrawLine = [&](const TArray<FVector2f>& Points, const FLinearColor& Color, float Thickness)
|
|
{
|
|
FSlateDrawElement::MakeLines(
|
|
OutDrawElements,
|
|
++LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
Points,
|
|
ESlateDrawEffect::None,
|
|
Color,
|
|
true,
|
|
Thickness);
|
|
};
|
|
|
|
DrawBox(Position + FVector2D(16.0f, 16.0f), FVector2D(Size.X - 32.0f, Size.Y - 32.0f), FLinearColor(0.0f, 0.0f, 0.0f, 0.22f * Alpha));
|
|
|
|
if (IllustrationIndex == 0)
|
|
{
|
|
DrawBox(Center + FVector2D(-72.0f, -46.0f), FVector2D(144.0f, 82.0f), SoftAccent);
|
|
DrawBox(Center + FVector2D(-62.0f, -36.0f), FVector2D(124.0f, 62.0f), FLinearColor(0.02f, 0.03f, 0.025f, Alpha));
|
|
DrawLine({ FVector2f(Center.X - 42.0f, Center.Y - 8.0f), FVector2f(Center.X - 8.0f, Center.Y - 28.0f), FVector2f(Center.X + 42.0f, Center.Y + 18.0f) }, StrongAccent, 4.0f);
|
|
DrawBox(Center + FVector2D(-34.0f, 48.0f), FVector2D(68.0f, 10.0f), StrongAccent);
|
|
}
|
|
else if (IllustrationIndex == 1)
|
|
{
|
|
DrawLine({ FVector2f(Center.X, Center.Y + 58.0f), FVector2f(Center.X, Center.Y - 48.0f) }, StrongAccent, 5.0f);
|
|
DrawLine({ FVector2f(Center.X, Center.Y - 8.0f), FVector2f(Center.X - 48.0f, Center.Y - 42.0f), FVector2f(Center.X - 74.0f, Center.Y - 20.0f) }, StrongAccent, 5.0f);
|
|
DrawLine({ FVector2f(Center.X, Center.Y + 2.0f), FVector2f(Center.X + 52.0f, Center.Y - 34.0f), FVector2f(Center.X + 80.0f, Center.Y - 10.0f) }, StrongAccent, 5.0f);
|
|
DrawBox(Center + FVector2D(-84.0f, 64.0f), FVector2D(168.0f, 8.0f), SoftAccent);
|
|
}
|
|
else if (IllustrationIndex == 2)
|
|
{
|
|
DrawBox(Center + FVector2D(-58.0f, -74.0f), FVector2D(116.0f, 148.0f), FLinearColor(0.93f, 0.88f, 0.72f, 0.22f * Alpha));
|
|
DrawBox(Center + FVector2D(-34.0f, -88.0f), FVector2D(68.0f, 20.0f), StrongAccent);
|
|
DrawLine({ FVector2f(Center.X - 32.0f, Center.Y - 26.0f), FVector2f(Center.X - 12.0f, Center.Y - 6.0f), FVector2f(Center.X + 42.0f, Center.Y - 48.0f) }, StrongAccent, 5.0f);
|
|
DrawBox(Center + FVector2D(-34.0f, 28.0f), FVector2D(68.0f, 5.0f), StrongAccent);
|
|
}
|
|
else if (IllustrationIndex == 3)
|
|
{
|
|
DrawBox(Center + FVector2D(-72.0f, -28.0f), FVector2D(144.0f, 56.0f), SoftAccent);
|
|
DrawLine({ FVector2f(Center.X - 70.0f, Center.Y), FVector2f(Center.X - 18.0f, Center.Y - 58.0f), FVector2f(Center.X + 32.0f, Center.Y + 44.0f), FVector2f(Center.X + 78.0f, Center.Y - 18.0f) }, StrongAccent, 5.0f);
|
|
DrawBox(Center + FVector2D(-16.0f, -16.0f), FVector2D(32.0f, 32.0f), FLinearColor(0.92f, 0.96f, 0.86f, 0.80f * Alpha));
|
|
}
|
|
else if (IllustrationIndex == 4)
|
|
{
|
|
DrawBox(Center + FVector2D(-64.0f, -58.0f), FVector2D(128.0f, 116.0f), SoftAccent);
|
|
DrawLine({ FVector2f(Center.X - 44.0f, Center.Y - 8.0f), FVector2f(Center.X - 8.0f, Center.Y + 28.0f), FVector2f(Center.X + 54.0f, Center.Y - 36.0f) }, StrongAccent, 5.0f);
|
|
DrawBox(Center + FVector2D(-74.0f, 74.0f), FVector2D(148.0f, 8.0f), StrongAccent);
|
|
DrawBox(Center + FVector2D(-74.0f, -82.0f), FVector2D(148.0f, 8.0f), StrongAccent);
|
|
}
|
|
else
|
|
{
|
|
DrawLine({ FVector2f(Center.X, Center.Y + 72.0f), FVector2f(Center.X, Center.Y - 36.0f) }, StrongAccent, 5.0f);
|
|
DrawLine({ FVector2f(Center.X, Center.Y - 12.0f), FVector2f(Center.X - 52.0f, Center.Y - 50.0f), FVector2f(Center.X - 80.0f, Center.Y - 28.0f) }, StrongAccent, 5.0f);
|
|
DrawLine({ FVector2f(Center.X, Center.Y - 6.0f), FVector2f(Center.X + 52.0f, Center.Y - 54.0f), FVector2f(Center.X + 84.0f, Center.Y - 28.0f) }, StrongAccent, 5.0f);
|
|
DrawBox(Center + FVector2D(-92.0f, 78.0f), FVector2D(184.0f, 8.0f), SoftAccent);
|
|
DrawBox(Center + FVector2D(-48.0f, 56.0f), FVector2D(96.0f, 8.0f), StrongAccent);
|
|
}
|
|
}
|