- Renomeia ~50 classes UCLASS/USTRUCT/UENUM/UINTERFACE pra Zeus* (AZeusGameMode, AZeusCharacter, UZeusGameInstance, IZeusEntityInterface, UZeusWorldSubsystem, FZeusEntitySnapshot, etc.) - Encurta AZMMOPlayerCharacter -> AZeusCharacter - Renomeia módulos satélite ZMMOAttributes -> ZeusAttributes e ZMMOJobs -> ZeusJobs (pasta + .Build.cs + .uproject) - Mantém módulo principal ZMMO (renomeia depois quando jogo ganhar nome) - DefaultEngine.ini: ActiveClassRedirects ZMMOX -> ZeusX (preserva BPs/assets) - DefaultGame.ini: sections atualizadas pra ZeusThemeSubsystem/ZeusPlayerState - Category="ZMMO|..." -> "Zeus|..." em UPROPERTYs - Preserva LogZMMO, ZMMO_API, /Script/ZMMO., /Game/ZMMO/, classes Target Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
236 lines
5.5 KiB
C++
236 lines
5.5 KiB
C++
#include "UILoadingScreen_Base.h"
|
|
|
|
#include "Components/ProgressBar.h"
|
|
#include "CommonTextBlock.h"
|
|
#include "Engine/DataTable.h"
|
|
#include "Engine/World.h"
|
|
#include "TimerManager.h"
|
|
#include "UILoadingProfilesDataAsset.h"
|
|
#include "UILoadingTipRow.h"
|
|
|
|
void UUILoadingScreen_Base::Configure(EZeusLoadingContext InContext,
|
|
UZeusLoadingProfilesDataAsset* Profiles,
|
|
UDataTable* TipsTable)
|
|
{
|
|
Context_ = InContext;
|
|
bCompleteFired_ = false;
|
|
|
|
// Perfil (etapas + título).
|
|
Profile_ = (Profiles != nullptr)
|
|
? Profiles->GetProfile(InContext)
|
|
: FZeusLoadingProfile();
|
|
|
|
StepStatus_.Reset();
|
|
for (const FZeusLoadingStepDef& Step : Profile_.Steps)
|
|
{
|
|
StepStatus_.Add(Step.StepId, EZeusLoadingStepStatus::Pending);
|
|
}
|
|
|
|
// Pool de dicas filtrada por contexto (None = qualquer).
|
|
TipPool_.Reset();
|
|
if (TipsTable != nullptr)
|
|
{
|
|
TipsTable->ForeachRow<FZeusLoadingTipRow>(TEXT("UUILoadingScreen_Base::Configure"),
|
|
[this](const FName& /*Key*/, const FZeusLoadingTipRow& Row)
|
|
{
|
|
if (Row.Context == EZeusLoadingContext::None || Row.Context == Context_)
|
|
{
|
|
if (!Row.Tip.IsEmpty())
|
|
{
|
|
TipPool_.Add(Row.Tip);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
NextTipIndex_ = 0;
|
|
|
|
RefreshUI();
|
|
|
|
if (IsActivated())
|
|
{
|
|
StartTipTimer();
|
|
}
|
|
}
|
|
|
|
void UUILoadingScreen_Base::NativeOnActivated()
|
|
{
|
|
Super::NativeOnActivated();
|
|
RefreshUI();
|
|
StartTipTimer();
|
|
}
|
|
|
|
void UUILoadingScreen_Base::NativeOnDeactivated()
|
|
{
|
|
StopTipTimer();
|
|
Super::NativeOnDeactivated();
|
|
}
|
|
|
|
void UUILoadingScreen_Base::MarkStepRunning(FName StepId)
|
|
{
|
|
if (EZeusLoadingStepStatus* Status = StepStatus_.Find(StepId))
|
|
{
|
|
// Já Done não regride.
|
|
if (*Status != EZeusLoadingStepStatus::Done && *Status != EZeusLoadingStepStatus::Failed)
|
|
{
|
|
*Status = EZeusLoadingStepStatus::Running;
|
|
RefreshUI();
|
|
}
|
|
}
|
|
}
|
|
|
|
void UUILoadingScreen_Base::MarkStepDone(FName StepId)
|
|
{
|
|
if (EZeusLoadingStepStatus* Status = StepStatus_.Find(StepId))
|
|
{
|
|
*Status = EZeusLoadingStepStatus::Done;
|
|
RefreshUI();
|
|
|
|
if (!bCompleteFired_ && AreAllStepsDone())
|
|
{
|
|
bCompleteFired_ = true;
|
|
OnLoadingComplete.Broadcast();
|
|
}
|
|
}
|
|
}
|
|
|
|
void UUILoadingScreen_Base::MarkStepFailed(FName StepId, const FText& Reason)
|
|
{
|
|
if (EZeusLoadingStepStatus* Status = StepStatus_.Find(StepId))
|
|
{
|
|
*Status = EZeusLoadingStepStatus::Failed;
|
|
if (Text_Status && !Reason.IsEmpty())
|
|
{
|
|
Text_Status->SetText(Reason);
|
|
}
|
|
RefreshUI();
|
|
}
|
|
}
|
|
|
|
bool UUILoadingScreen_Base::AreAllStepsDone() const
|
|
{
|
|
if (Profile_.Steps.Num() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
for (const FZeusLoadingStepDef& Step : Profile_.Steps)
|
|
{
|
|
const EZeusLoadingStepStatus* Status = StepStatus_.Find(Step.StepId);
|
|
if (Status == nullptr || *Status != EZeusLoadingStepStatus::Done)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int32 UUILoadingScreen_Base::FindStepIndex(FName StepId) const
|
|
{
|
|
for (int32 i = 0; i < Profile_.Steps.Num(); ++i)
|
|
{
|
|
if (Profile_.Steps[i].StepId == StepId)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return INDEX_NONE;
|
|
}
|
|
|
|
EZeusLoadingStepStatus UUILoadingScreen_Base::GetStepStatus(int32 Index) const
|
|
{
|
|
if (!Profile_.Steps.IsValidIndex(Index)) return EZeusLoadingStepStatus::Pending;
|
|
const EZeusLoadingStepStatus* Status = StepStatus_.Find(Profile_.Steps[Index].StepId);
|
|
return Status ? *Status : EZeusLoadingStepStatus::Pending;
|
|
}
|
|
|
|
FText UUILoadingScreen_Base::ComputeCurrentStatusText() const
|
|
{
|
|
// Prioridade: Running > último Done > primeiro Pending > Status default.
|
|
int32 LastDone = INDEX_NONE;
|
|
for (int32 i = 0; i < Profile_.Steps.Num(); ++i)
|
|
{
|
|
const EZeusLoadingStepStatus St = GetStepStatus(i);
|
|
if (St == EZeusLoadingStepStatus::Running)
|
|
{
|
|
return Profile_.Steps[i].Label;
|
|
}
|
|
if (St == EZeusLoadingStepStatus::Done)
|
|
{
|
|
LastDone = i;
|
|
}
|
|
}
|
|
if (LastDone != INDEX_NONE)
|
|
{
|
|
return Profile_.Steps[LastDone].Label;
|
|
}
|
|
if (Profile_.Steps.Num() > 0)
|
|
{
|
|
return Profile_.Steps[0].Label;
|
|
}
|
|
return StatusDefault;
|
|
}
|
|
|
|
float UUILoadingScreen_Base::ComputeProgress01() const
|
|
{
|
|
const int32 N = Profile_.Steps.Num();
|
|
if (N == 0) return 0.f;
|
|
float Acc = 0.f;
|
|
for (int32 i = 0; i < N; ++i)
|
|
{
|
|
const EZeusLoadingStepStatus St = GetStepStatus(i);
|
|
if (St == EZeusLoadingStepStatus::Done) Acc += 1.f;
|
|
else if (St == EZeusLoadingStepStatus::Running) Acc += 0.5f;
|
|
}
|
|
return FMath::Clamp(Acc / static_cast<float>(N), 0.f, 1.f);
|
|
}
|
|
|
|
void UUILoadingScreen_Base::RefreshUI()
|
|
{
|
|
if (Text_Title)
|
|
{
|
|
const FText& Title = Profile_.TitleOverride.IsEmpty() ? TitleDefault : Profile_.TitleOverride;
|
|
Text_Title->SetText(Title);
|
|
}
|
|
if (Text_Status)
|
|
{
|
|
Text_Status->SetText(ComputeCurrentStatusText());
|
|
}
|
|
if (ProgressBar_Progress)
|
|
{
|
|
ProgressBar_Progress->SetPercent(ComputeProgress01());
|
|
}
|
|
if (Text_Tip && TipPool_.Num() > 0 && Text_Tip->GetText().IsEmpty())
|
|
{
|
|
// Primeira dica na inicialização (timer cuida das próximas).
|
|
Text_Tip->SetText(TipPool_[0]);
|
|
NextTipIndex_ = TipPool_.Num() > 1 ? 1 : 0;
|
|
}
|
|
}
|
|
|
|
void UUILoadingScreen_Base::RotateTip()
|
|
{
|
|
if (!Text_Tip || TipPool_.Num() == 0) return;
|
|
Text_Tip->SetText(TipPool_[NextTipIndex_]);
|
|
NextTipIndex_ = (NextTipIndex_ + 1) % TipPool_.Num();
|
|
}
|
|
|
|
void UUILoadingScreen_Base::StartTipTimer()
|
|
{
|
|
StopTipTimer();
|
|
if (TipRotationIntervalSeconds <= 0.f || TipPool_.Num() <= 1) return;
|
|
if (UWorld* W = GetWorld())
|
|
{
|
|
W->GetTimerManager().SetTimer(TipTimerHandle_, this,
|
|
&UUILoadingScreen_Base::RotateTip,
|
|
TipRotationIntervalSeconds, /*bLoop=*/true);
|
|
}
|
|
}
|
|
|
|
void UUILoadingScreen_Base::StopTipTimer()
|
|
{
|
|
if (UWorld* W = GetWorld())
|
|
{
|
|
W->GetTimerManager().ClearTimer(TipTimerHandle_);
|
|
}
|
|
TipTimerHandle_.Invalidate();
|
|
}
|