Expose dashboard execution-control hint timer and result surfaces
This commit is contained in:
parent
4b53d20926
commit
ea0739b680
5 changed files with 448 additions and 23 deletions
|
|
@ -10997,6 +10997,162 @@ UHyperTwistCoachDashboardWidget::GetDisplayedCurrentCaseDeckStatusInspectSurface
|
|||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardAttemptTimeInputHintInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedAttemptTimeInputHintInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardAttemptTimeInputHintInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Attempt-time input hint");
|
||||
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
&& CachedRunState.ActiveDeck.IsStructurallyValid();
|
||||
const bool bHasRunnableCurrentCase =
|
||||
bHasActiveRun && CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
|
||||
const FHyperTwistTrainingCase& CurrentTrainingCase = CachedRunState.CurrentSelection.TrainingCase;
|
||||
|
||||
Surface.HintLabel = !DisplayedAttemptTimeHintLabel.IsEmpty()
|
||||
? DisplayedAttemptTimeHintLabel
|
||||
: (CurrentTrainingCase.TimeTargetMs > 0
|
||||
? FString::Printf(TEXT("Enter attempt ms (target %d)"), CurrentTrainingCase.TimeTargetMs)
|
||||
: TEXT("Enter attempt ms"));
|
||||
Surface.UseTargetLabel = !DisplayedUseTargetTimeLabel.IsEmpty()
|
||||
? DisplayedUseTargetTimeLabel
|
||||
: TEXT("Use Target");
|
||||
Surface.UseAverageLabel = !DisplayedUseAverageTimeLabel.IsEmpty()
|
||||
? DisplayedUseAverageTimeLabel
|
||||
: TEXT("Use Avg");
|
||||
Surface.TargetTimeMs = CurrentTrainingCase.TimeTargetMs;
|
||||
Surface.AverageTotalTimeMs = CachedRunSummary.AverageTotalTimeMs;
|
||||
Surface.bHasActiveRun = bHasActiveRun;
|
||||
Surface.bHasRunnableCurrentCase = bHasRunnableCurrentCase;
|
||||
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
|
||||
Surface.bAttemptInputEnabled = !bHasLiveAttemptTimer && bHasRunnableCurrentCase;
|
||||
Surface.bCanUseTargetTime =
|
||||
!bHasLiveAttemptTimer && bHasRunnableCurrentCase && CurrentTrainingCase.TimeTargetMs > 0;
|
||||
Surface.bCanUseAverageTime =
|
||||
!bHasLiveAttemptTimer && bHasActiveRun && CachedRunSummary.AverageTotalTimeMs > 0;
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("Hint: %s | input enabled: %s | %s: %s | %s: %s"),
|
||||
*Surface.HintLabel,
|
||||
Surface.bAttemptInputEnabled ? TEXT("yes") : TEXT("no"),
|
||||
*Surface.UseTargetLabel,
|
||||
Surface.bCanUseTargetTime ? TEXT("yes") : TEXT("no"),
|
||||
*Surface.UseAverageLabel,
|
||||
Surface.bCanUseAverageTime ? TEXT("yes") : TEXT("no"));
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardLiveTimerSplitControlLabelInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedLiveTimerSplitControlLabelInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardLiveTimerSplitControlLabelInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Live timer / split control labels");
|
||||
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
&& CachedRunState.ActiveDeck.IsStructurallyValid();
|
||||
const bool bHasRunnableCurrentCase =
|
||||
bHasActiveRun && CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
|
||||
const bool bLiveInspectionPhase = IsLiveAttemptInspectionPhase();
|
||||
const bool bLiveSolvePhase = bHasLiveAttemptTimer
|
||||
&& LiveAttemptPhase == EHyperTwistCoachDashboardAttemptPhase::Solving;
|
||||
const FHyperTwistTrainingSplitPhaseDefinition* NextSplitPhaseDefinition = FindNextSplitPhaseToCapture();
|
||||
const FString NextSplitLabel = NextSplitPhaseDefinition == nullptr
|
||||
? TEXT("none")
|
||||
: (NextSplitPhaseDefinition->Label.IsEmpty()
|
||||
? NextSplitPhaseDefinition->PhaseId
|
||||
: NextSplitPhaseDefinition->Label);
|
||||
|
||||
Surface.StartTimerLabel = !DisplayedStartTimerControlLabel.IsEmpty()
|
||||
? DisplayedStartTimerControlLabel
|
||||
: (bLiveInspectionPhase
|
||||
? TEXT("Start Solve")
|
||||
: (bHasLiveAttemptTimer ? TEXT("Timer Active") : TEXT("Start Attempt")));
|
||||
Surface.CancelTimerLabel = !DisplayedCancelTimerControlLabel.IsEmpty()
|
||||
? DisplayedCancelTimerControlLabel
|
||||
: TEXT("Cancel Timer");
|
||||
Surface.CaptureSplitLabel = !DisplayedCaptureSplitControlLabel.IsEmpty()
|
||||
? DisplayedCaptureSplitControlLabel
|
||||
: (NextSplitPhaseDefinition == nullptr
|
||||
? TEXT("All Splits Captured")
|
||||
: FString::Printf(TEXT("Capture %s"), *NextSplitLabel));
|
||||
Surface.UndoSplitLabel = !DisplayedUndoSplitControlLabel.IsEmpty()
|
||||
? DisplayedUndoSplitControlLabel
|
||||
: TEXT("Undo Split");
|
||||
Surface.NextSplitLabel = NextSplitLabel;
|
||||
Surface.CapturedSplitCount = LiveAttemptSplitCaptures.Num();
|
||||
Surface.bHasRunnableCurrentCase = bHasRunnableCurrentCase;
|
||||
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
|
||||
Surface.bLiveInspectionPhase = bLiveInspectionPhase;
|
||||
Surface.bLiveSolvePhase = bLiveSolvePhase;
|
||||
Surface.bCanStartOrAdvanceTimer =
|
||||
bHasRunnableCurrentCase && (!bHasLiveAttemptTimer || bLiveInspectionPhase);
|
||||
Surface.bCanCancelTimer = bHasLiveAttemptTimer;
|
||||
Surface.bCanCaptureSplit = bLiveSolvePhase && NextSplitPhaseDefinition != nullptr;
|
||||
Surface.bCanUndoSplit = bLiveSolvePhase && LiveAttemptSplitCaptures.Num() > 0;
|
||||
Surface.TimerControlLine = FString::Printf(
|
||||
TEXT("%s: %s | %s: %s"),
|
||||
*Surface.StartTimerLabel,
|
||||
Surface.bCanStartOrAdvanceTimer ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.CancelTimerLabel,
|
||||
Surface.bCanCancelTimer ? TEXT("enabled") : TEXT("disabled"));
|
||||
Surface.SplitControlLine = FString::Printf(
|
||||
TEXT("%s: %s | %s: %s | next split: %s | captured: %d"),
|
||||
*Surface.CaptureSplitLabel,
|
||||
Surface.bCanCaptureSplit ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.UndoSplitLabel,
|
||||
Surface.bCanUndoSplit ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.NextSplitLabel,
|
||||
Surface.CapturedSplitCount);
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedAttemptResultActionEnablementInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Attempt result-action enablement");
|
||||
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
&& CachedRunState.ActiveDeck.IsStructurallyValid();
|
||||
const bool bHasRunnableCurrentCase =
|
||||
bHasActiveRun && CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
|
||||
const bool bLiveSolvePhase = bHasLiveAttemptTimer
|
||||
&& LiveAttemptPhase == EHyperTwistCoachDashboardAttemptPhase::Solving;
|
||||
|
||||
Surface.SuccessLabel = !DisplayedRecordSuccessActionLabel.IsEmpty()
|
||||
? DisplayedRecordSuccessActionLabel
|
||||
: (bLiveSolvePhase ? TEXT("Stop Success") : TEXT("Record Success"));
|
||||
Surface.FailureLabel = !DisplayedRecordFailureActionLabel.IsEmpty()
|
||||
? DisplayedRecordFailureActionLabel
|
||||
: (bLiveSolvePhase ? TEXT("Stop Failure") : TEXT("Record Failure"));
|
||||
Surface.TimeoutLabel = !DisplayedRecordTimeoutActionLabel.IsEmpty()
|
||||
? DisplayedRecordTimeoutActionLabel
|
||||
: (bLiveSolvePhase ? TEXT("Stop Timeout") : TEXT("Record Timeout"));
|
||||
Surface.DnfLabel = !DisplayedRecordDnfActionLabel.IsEmpty()
|
||||
? DisplayedRecordDnfActionLabel
|
||||
: (bLiveSolvePhase ? TEXT("Stop DNF") : TEXT("Record DNF"));
|
||||
Surface.bHasRunnableCurrentCase = bHasRunnableCurrentCase;
|
||||
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
|
||||
Surface.bLiveSolvePhase = bLiveSolvePhase;
|
||||
Surface.bCanRecordSyntheticAttempt = !bHasLiveAttemptTimer && bHasRunnableCurrentCase;
|
||||
Surface.bCanStopLiveTimedAttempt = bLiveSolvePhase;
|
||||
Surface.bSuccessEnabled = bLiveSolvePhase || (!bHasLiveAttemptTimer && bHasRunnableCurrentCase);
|
||||
Surface.bFailureEnabled = Surface.bSuccessEnabled;
|
||||
Surface.bTimeoutEnabled = Surface.bSuccessEnabled;
|
||||
Surface.bDnfEnabled = Surface.bSuccessEnabled;
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("%s | %s | %s | %s"),
|
||||
*Surface.SuccessLabel,
|
||||
*Surface.FailureLabel,
|
||||
*Surface.TimeoutLabel,
|
||||
*Surface.DnfLabel);
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Result-action detail: live solve %s | synthetic attempt entry %s | stop-live-attempt %s"),
|
||||
Surface.bLiveSolvePhase ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bCanRecordSyntheticAttempt ? TEXT("enabled") : TEXT("disabled"),
|
||||
Surface.bCanStopLiveTimedAttempt ? TEXT("enabled") : TEXT("disabled"));
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedLastAttemptReviewSummaryInspectSurface() const
|
||||
{
|
||||
|
|
@ -23288,7 +23444,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
const FString HintLabel = CurrentTrainingCase.TimeTargetMs > 0
|
||||
? FString::Printf(TEXT("Enter attempt ms (target %d)"), CurrentTrainingCase.TimeTargetMs)
|
||||
: TEXT("Enter attempt ms");
|
||||
AttemptTimeTextBox->SetHintText(FText::FromString(HintLabel));
|
||||
DisplayedAttemptTimeHintLabel = HintLabel;
|
||||
AttemptTimeTextBox->SetHintText(FText::FromString(DisplayedAttemptTimeHintLabel));
|
||||
AttemptTimeTextBox->SetIsEnabled(!bHasLiveAttemptTimer && bHasRunnableCurrentCase);
|
||||
}
|
||||
if (FollowUpTextBlock != nullptr)
|
||||
|
|
@ -23891,9 +24048,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (RecordSuccessButtonLabel != nullptr)
|
||||
{
|
||||
RecordSuccessButtonLabel->SetText(FText::FromString(
|
||||
bLiveSolvePhase ? TEXT("Stop Success") : TEXT("Record Success")
|
||||
));
|
||||
DisplayedRecordSuccessActionLabel =
|
||||
bLiveSolvePhase ? TEXT("Stop Success") : TEXT("Record Success");
|
||||
RecordSuccessButtonLabel->SetText(FText::FromString(DisplayedRecordSuccessActionLabel));
|
||||
}
|
||||
if (RecordSuccessButton != nullptr)
|
||||
{
|
||||
|
|
@ -23901,9 +24058,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (RecordFailureButtonLabel != nullptr)
|
||||
{
|
||||
RecordFailureButtonLabel->SetText(FText::FromString(
|
||||
bLiveSolvePhase ? TEXT("Stop Failure") : TEXT("Record Failure")
|
||||
));
|
||||
DisplayedRecordFailureActionLabel =
|
||||
bLiveSolvePhase ? TEXT("Stop Failure") : TEXT("Record Failure");
|
||||
RecordFailureButtonLabel->SetText(FText::FromString(DisplayedRecordFailureActionLabel));
|
||||
}
|
||||
if (RecordFailureButton != nullptr)
|
||||
{
|
||||
|
|
@ -23911,9 +24068,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (RecordTimeoutButtonLabel != nullptr)
|
||||
{
|
||||
RecordTimeoutButtonLabel->SetText(FText::FromString(
|
||||
bLiveSolvePhase ? TEXT("Stop Timeout") : TEXT("Record Timeout")
|
||||
));
|
||||
DisplayedRecordTimeoutActionLabel =
|
||||
bLiveSolvePhase ? TEXT("Stop Timeout") : TEXT("Record Timeout");
|
||||
RecordTimeoutButtonLabel->SetText(FText::FromString(DisplayedRecordTimeoutActionLabel));
|
||||
}
|
||||
if (RecordTimeoutButton != nullptr)
|
||||
{
|
||||
|
|
@ -23921,9 +24078,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (RecordDnfButtonLabel != nullptr)
|
||||
{
|
||||
RecordDnfButtonLabel->SetText(FText::FromString(
|
||||
bLiveSolvePhase ? TEXT("Stop DNF") : TEXT("Record DNF")
|
||||
));
|
||||
DisplayedRecordDnfActionLabel =
|
||||
bLiveSolvePhase ? TEXT("Stop DNF") : TEXT("Record DNF");
|
||||
RecordDnfButtonLabel->SetText(FText::FromString(DisplayedRecordDnfActionLabel));
|
||||
}
|
||||
if (RecordDnfButton != nullptr)
|
||||
{
|
||||
|
|
@ -23931,7 +24088,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (UseTargetTimeButtonLabel != nullptr)
|
||||
{
|
||||
UseTargetTimeButtonLabel->SetText(FText::FromString(TEXT("Use Target")));
|
||||
DisplayedUseTargetTimeLabel = TEXT("Use Target");
|
||||
UseTargetTimeButtonLabel->SetText(FText::FromString(DisplayedUseTargetTimeLabel));
|
||||
}
|
||||
if (UseTargetTimeButton != nullptr)
|
||||
{
|
||||
|
|
@ -23941,7 +24099,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (UseAverageTimeButtonLabel != nullptr)
|
||||
{
|
||||
UseAverageTimeButtonLabel->SetText(FText::FromString(TEXT("Use Avg")));
|
||||
DisplayedUseAverageTimeLabel = TEXT("Use Avg");
|
||||
UseAverageTimeButtonLabel->SetText(FText::FromString(DisplayedUseAverageTimeLabel));
|
||||
}
|
||||
if (UseAverageTimeButton != nullptr)
|
||||
{
|
||||
|
|
@ -23951,10 +24110,10 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (StartTimerButtonLabel != nullptr)
|
||||
{
|
||||
StartTimerButtonLabel->SetText(FText::FromString(
|
||||
DisplayedStartTimerControlLabel =
|
||||
bLiveInspectionPhase ? TEXT("Start Solve")
|
||||
: (bHasLiveAttemptTimer ? TEXT("Timer Active") : TEXT("Start Attempt"))
|
||||
));
|
||||
: (bHasLiveAttemptTimer ? TEXT("Timer Active") : TEXT("Start Attempt"));
|
||||
StartTimerButtonLabel->SetText(FText::FromString(DisplayedStartTimerControlLabel));
|
||||
}
|
||||
if (StartTimerButton != nullptr)
|
||||
{
|
||||
|
|
@ -23965,7 +24124,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (CancelTimerButtonLabel != nullptr)
|
||||
{
|
||||
CancelTimerButtonLabel->SetText(FText::FromString(TEXT("Cancel Timer")));
|
||||
DisplayedCancelTimerControlLabel = TEXT("Cancel Timer");
|
||||
CancelTimerButtonLabel->SetText(FText::FromString(DisplayedCancelTimerControlLabel));
|
||||
}
|
||||
if (CancelTimerButton != nullptr)
|
||||
{
|
||||
|
|
@ -23976,7 +24136,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
const FString CaptureSplitLabel = NextSplitPhaseDefinition == nullptr
|
||||
? TEXT("All Splits Captured")
|
||||
: FString::Printf(TEXT("Capture %s"), *NextSplitLabel);
|
||||
CaptureSplitButtonLabel->SetText(FText::FromString(CaptureSplitLabel));
|
||||
DisplayedCaptureSplitControlLabel = CaptureSplitLabel;
|
||||
CaptureSplitButtonLabel->SetText(FText::FromString(DisplayedCaptureSplitControlLabel));
|
||||
}
|
||||
if (CaptureSplitButton != nullptr)
|
||||
{
|
||||
|
|
@ -23984,7 +24145,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (UndoSplitButtonLabel != nullptr)
|
||||
{
|
||||
UndoSplitButtonLabel->SetText(FText::FromString(TEXT("Undo Split")));
|
||||
DisplayedUndoSplitControlLabel = TEXT("Undo Split");
|
||||
UndoSplitButtonLabel->SetText(FText::FromString(DisplayedUndoSplitControlLabel));
|
||||
}
|
||||
if (UndoSplitButton != nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -827,6 +827,18 @@ public:
|
|||
FHyperTwistTrainingCoachDashboardCurrentCaseDeckStatusInspectSurface
|
||||
GetDisplayedCurrentCaseDeckStatusInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardAttemptTimeInputHintInspectSurface
|
||||
GetDisplayedAttemptTimeInputHintInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardLiveTimerSplitControlLabelInspectSurface
|
||||
GetDisplayedLiveTimerSplitControlLabelInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface
|
||||
GetDisplayedAttemptResultActionEnablementInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
|
||||
GetDisplayedLastAttemptReviewSummaryInspectSurface() const;
|
||||
|
|
@ -1884,6 +1896,17 @@ private:
|
|||
FString DisplayedActiveRunSummaryLine;
|
||||
FString DisplayedCurrentCasePromptLine;
|
||||
FString DisplayedCurrentCaseNotationLine;
|
||||
FString DisplayedAttemptTimeHintLabel;
|
||||
FString DisplayedUseTargetTimeLabel;
|
||||
FString DisplayedUseAverageTimeLabel;
|
||||
FString DisplayedStartTimerControlLabel;
|
||||
FString DisplayedCancelTimerControlLabel;
|
||||
FString DisplayedCaptureSplitControlLabel;
|
||||
FString DisplayedUndoSplitControlLabel;
|
||||
FString DisplayedRecordSuccessActionLabel;
|
||||
FString DisplayedRecordFailureActionLabel;
|
||||
FString DisplayedRecordTimeoutActionLabel;
|
||||
FString DisplayedRecordDnfActionLabel;
|
||||
FString DisplayedLastAttemptReviewSummaryLine;
|
||||
FString DisplayedLastAttemptTimingLine;
|
||||
FString DisplayedLastAttemptDerivedPhaseLine;
|
||||
|
|
|
|||
|
|
@ -10821,6 +10821,191 @@ struct FHyperTwistTrainingCoachDashboardHandoffRecommendationInspectSurface
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardAttemptTimeInputHintInspectSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString HintLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString UseTargetLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString UseAverageLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 TargetTimeMs = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 AverageTotalTimeMs = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasActiveRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasRunnableCurrentCase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAttemptInputEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanUseTargetTime = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanUseAverageTime = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !HintLabel.IsEmpty()
|
||||
|| bAttemptInputEnabled
|
||||
|| bCanUseTargetTime
|
||||
|| bCanUseAverageTime;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardLiveTimerSplitControlLabelInspectSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString TimerControlLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SplitControlLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StartTimerLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CancelTimerLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CaptureSplitLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString UndoSplitLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextSplitLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 CapturedSplitCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasRunnableCurrentCase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLiveInspectionPhase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLiveSolvePhase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanStartOrAdvanceTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanCancelTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanCaptureSplit = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanUndoSplit = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !TimerControlLine.IsEmpty()
|
||||
|| !SplitControlLine.IsEmpty()
|
||||
|| bCanStartOrAdvanceTimer
|
||||
|| bCanCancelTimer
|
||||
|| bCanCaptureSplit
|
||||
|| bCanUndoSplit;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SuccessLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FailureLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString TimeoutLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DnfLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasRunnableCurrentCase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLiveSolvePhase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanRecordSyntheticAttempt = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanStopLiveTimedAttempt = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSuccessEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bFailureEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bTimeoutEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bDnfEnabled = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| bSuccessEnabled
|
||||
|| bFailureEnabled
|
||||
|| bTimeoutEnabled
|
||||
|| bDnfEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ Current correction call from the source-exposed audit and current execution refr
|
|||
- the latest landed bounded `Phase 4` packet closes the retained-idle comparison/outcome actionability gap at the end of the recognition-assisted coach-to-review continuity lane, and the final retained-surface confirmation pass now leaves that closure lane functionally complete
|
||||
- the retained idle widget surface now keeps retained comparison and decision history inspectable without continuing to advertise live launch or guidance-outcome actions once the coach-to-review loop has already collapsed to truthful closed-loop idle
|
||||
- the now-complete deliberate `UHyperTwistTrainingRuntimeLibrary` world-context consumer lane reaches through active generated-mode selector option owned-execution split-phase current-selection merged ordered roster phase-id lookup, normalized-order lookup, and evaluation-order lookup inspect surfaces, so gameplay/Blueprint callers can inspect one retained merged-roster row directly by phase id, normalized order, or evaluation order without scanning the merged roster array or re-running inspect derivation details directly
|
||||
- the latest landed bounded `Phase 4` packet stays on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds displayed last-attempt review summary, displayed last-attempt timing / derived-phase review, and live split-capture status inspect surfaces over already-derived live dashboard review/timing/split presentation state, so gameplay/Blueprint callers can inspect the active reviewed attempt line, reviewed timing and derived-phase lines, and live split-capture posture without scraping dashboard text blocks or reopening attempt-review or split-capture derivation
|
||||
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the attempt-time input hint, live timer / split control label, and attempt result-action enablement inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam
|
||||
- the latest landed bounded `Phase 4` packet stays on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds attempt-time input hint, live timer / split control label, and attempt result-action enablement inspect surfaces over already-derived live dashboard execution-control presentation state, so gameplay/Blueprint callers can inspect the current attempt-time hint, quick-fill affordance posture, timer/split control labels, and result-action enablement without scraping widget controls or reopening execution-control derivation
|
||||
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the attempt-review navigation, primary / continue / clear / complete run-control enablement, and queue defer / promote / recovery action enablement inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam
|
||||
- the current execution-discipline rule that broad refactor / monolith-splitting work should not interrupt the active bounded roadmap packet unless structure is actually blocking it
|
||||
|
||||
## Current execution-reality references
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# HyperTwist Phase 4 dashboard live execution-control hint, timer/split control, and result-action inspect surface packet
|
||||
|
||||
- bounded Phase `4` dashboard-consumer slice
|
||||
- date: `2026-05-09`
|
||||
|
||||
## Intent
|
||||
|
||||
Stay on the deliberate live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and expose the remaining live attempt-input, timer/split control, and result-action execution-control state directly to gameplay and Blueprint callers.
|
||||
|
||||
## Why this packet exists
|
||||
|
||||
The dashboard already derived:
|
||||
|
||||
- the displayed attempt-time input hint
|
||||
- the displayed timer and split-control labels
|
||||
- the displayed result-action labels and their enablement posture
|
||||
|
||||
But that live state still only surfaced through widget controls. Callers still had to scrape editable-text hints, button labels, or button enabled state to inspect what the dashboard was currently showing.
|
||||
|
||||
## What changed
|
||||
|
||||
- added `FHyperTwistTrainingCoachDashboardAttemptTimeInputHintInspectSurface`
|
||||
- added `FHyperTwistTrainingCoachDashboardLiveTimerSplitControlLabelInspectSurface`
|
||||
- added `FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface`
|
||||
- added `GetDisplayedAttemptTimeInputHintInspectSurface()`
|
||||
- added `GetDisplayedLiveTimerSplitControlLabelInspectSurface()`
|
||||
- added `GetDisplayedAttemptResultActionEnablementInspectSurface()`
|
||||
- retained the exact displayed attempt-time hint, timer/split control labels, and result-action labels inside the widget so the new inspect surfaces report the same live strings the dashboard is already presenting
|
||||
- kept the packet bounded to `UHyperTwistCoachDashboardWidget` plus shared surface types, with no dashboard redesign and no backend continuity changes
|
||||
|
||||
## Files
|
||||
|
||||
- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistTrainingTypes.h`
|
||||
- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistCoachDashboardWidget.h`
|
||||
- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Private\HyperTwistTraining\HyperTwistCoachDashboardWidget.cpp`
|
||||
- `C:\HyperTwist\docs\HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md`
|
||||
|
||||
## Outcome
|
||||
|
||||
Gameplay and Blueprint callers can now inspect:
|
||||
|
||||
- the attempt-time input hint and quick-fill affordance posture
|
||||
- the live timer and split-control labels plus their current enablement posture
|
||||
- the success / failure / timeout / DNF action labels plus their current enablement posture
|
||||
|
||||
without scraping widget controls or reopening execution-control derivation.
|
||||
|
||||
## Validation
|
||||
|
||||
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
|
||||
- passed with `0 Warning(s), 0 Error(s)`
|
||||
|
||||
## Next clean slice
|
||||
|
||||
Stay on the same live dashboard guidance-consumer lane and land the attempt-review navigation, primary / continue / clear / complete run-control enablement, and queue defer / promote / recovery action enablement inspect surface group.
|
||||
Loading…
Add table
Reference in a new issue