Expose dashboard guidance preview case navigation surface
This commit is contained in:
parent
9fafb7d5c7
commit
47cf3bb7fd
5 changed files with 233 additions and 4 deletions
|
|
@ -10551,6 +10551,105 @@ UHyperTwistCoachDashboardWidget::GetDisplayedGuidancePreviewCaseDetailInspectSur
|
|||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardGuidancePreviewCaseNavigationInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedGuidancePreviewCaseNavigationInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardGuidancePreviewCaseNavigationInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Preview case navigation");
|
||||
|
||||
const auto BuildPreviewLaneLabel = [](const EHyperTwistCoachDashboardGuidancePreviewLane Lane) -> FString
|
||||
{
|
||||
return Lane == EHyperTwistCoachDashboardGuidancePreviewLane::Recommended
|
||||
? TEXT("recommended")
|
||||
: (Lane == EHyperTwistCoachDashboardGuidancePreviewLane::FollowUp
|
||||
? TEXT("follow-up")
|
||||
: TEXT("none"));
|
||||
};
|
||||
|
||||
const FHyperTwistTrainingDeck* ActivePreviewDeck = GetActiveGuidancePreviewDeck();
|
||||
const FHyperTwistTrainingCase* SelectedGuidancePreviewCase =
|
||||
ActivePreviewDeck != nullptr
|
||||
&& SelectedGuidancePreviewCaseIndex >= 0
|
||||
&& SelectedGuidancePreviewCaseIndex < ActivePreviewDeck->Cases.Num()
|
||||
? &ActivePreviewDeck->Cases[SelectedGuidancePreviewCaseIndex]
|
||||
: nullptr;
|
||||
const bool bNavigationEnabled = ActivePreviewDeck != nullptr && ActivePreviewDeck->Cases.Num() > 1;
|
||||
|
||||
Surface.PreviousLabel = !DisplayedPreviousGuidanceCaseNavigationLabel.IsEmpty()
|
||||
? DisplayedPreviousGuidanceCaseNavigationLabel
|
||||
: TEXT("Prev Guidance Case");
|
||||
Surface.NextLabel = !DisplayedNextGuidanceCaseNavigationLabel.IsEmpty()
|
||||
? DisplayedNextGuidanceCaseNavigationLabel
|
||||
: TEXT("Next Guidance Case");
|
||||
Surface.ActivePreviewLaneLabel = BuildPreviewLaneLabel(ActiveGuidancePreviewLane);
|
||||
Surface.DeckLabel =
|
||||
ActivePreviewDeck != nullptr
|
||||
? (ActivePreviewDeck->Title.IsEmpty() ? ActivePreviewDeck->DeckId : ActivePreviewDeck->Title)
|
||||
: TEXT("n/a");
|
||||
Surface.SelectedCaseId =
|
||||
SelectedGuidancePreviewCase != nullptr && !SelectedGuidancePreviewCase->CaseId.IsEmpty()
|
||||
? SelectedGuidancePreviewCase->CaseId
|
||||
: TEXT("n/a");
|
||||
Surface.SelectedCasePromptLabel =
|
||||
SelectedGuidancePreviewCase != nullptr
|
||||
&& !SelectedGuidancePreviewCase->PromptLabel.IsEmpty()
|
||||
? SelectedGuidancePreviewCase->PromptLabel
|
||||
: TEXT("n/a");
|
||||
Surface.SelectedCaseOrdinal =
|
||||
SelectedGuidancePreviewCase != nullptr && ActivePreviewDeck != nullptr
|
||||
? FString::Printf(TEXT("%d/%d"), SelectedGuidancePreviewCaseIndex + 1, ActivePreviewDeck->Cases.Num())
|
||||
: TEXT("none");
|
||||
Surface.SelectedCaseIndex = SelectedGuidancePreviewCaseIndex;
|
||||
Surface.TotalCaseCount = ActivePreviewDeck != nullptr ? ActivePreviewDeck->Cases.Num() : 0;
|
||||
Surface.bHasActivePreviewDeck = ActivePreviewDeck != nullptr;
|
||||
Surface.bHasSelectedCase = SelectedGuidancePreviewCase != nullptr;
|
||||
Surface.bPreviousEnabled = bNavigationEnabled;
|
||||
Surface.bNextEnabled = bNavigationEnabled;
|
||||
|
||||
const bool bQueueRecoveryMemorySource =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsQueueRecoveryMemorySource(
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel);
|
||||
Surface.bClosedLoopIdleDashboard =
|
||||
IsCoachLoopActionabilityClosed()
|
||||
&& (
|
||||
bQueueRecoveryMemorySource
|
||||
|| !CachedCoachPanelState.PreferredGuidanceSourceLabel.IsEmpty()
|
||||
|| DisplayedCoachHandoffRecommendationKind != EHyperTwistTrainingCoachHandoffKind::None);
|
||||
|
||||
Surface.StatusLine =
|
||||
SelectedGuidancePreviewCase != nullptr
|
||||
? FString::Printf(
|
||||
TEXT("Preview navigation: lane %s | selected %s | case %s | deck %s"),
|
||||
*Surface.ActivePreviewLaneLabel,
|
||||
*Surface.SelectedCaseOrdinal,
|
||||
*Surface.SelectedCaseId,
|
||||
*Surface.DeckLabel)
|
||||
: FString::Printf(
|
||||
TEXT("Preview navigation: lane %s | no active preview case is currently selected"),
|
||||
*Surface.ActivePreviewLaneLabel);
|
||||
Surface.DetailLine =
|
||||
ActivePreviewDeck != nullptr
|
||||
? FString::Printf(
|
||||
TEXT("%s: %s | %s: %s | selected prompt %s"),
|
||||
*Surface.PreviousLabel,
|
||||
Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.NextLabel,
|
||||
Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled"),
|
||||
*Surface.SelectedCasePromptLabel)
|
||||
: FString::Printf(
|
||||
TEXT("%s: disabled | %s: disabled | build a preview deck before navigating guidance cases"),
|
||||
*Surface.PreviousLabel,
|
||||
*Surface.NextLabel);
|
||||
if (Surface.bClosedLoopIdleDashboard)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Preview navigation: no active guidance preview remains in the closed-loop idle state.");
|
||||
Surface.DetailLine =
|
||||
TEXT("Preview navigation detail: retained coach memory remains inspectable, but live preview-case navigation is inactive.");
|
||||
}
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardMethodDrillDiagnosticsInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedMethodDrillDiagnosticsInspectSurface() const
|
||||
{
|
||||
|
|
@ -26354,7 +26453,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (PreviousGuidanceCaseButtonLabel != nullptr)
|
||||
{
|
||||
PreviousGuidanceCaseButtonLabel->SetText(FText::FromString(TEXT("Prev Guidance Case")));
|
||||
DisplayedPreviousGuidanceCaseNavigationLabel = TEXT("Prev Guidance Case");
|
||||
PreviousGuidanceCaseButtonLabel->SetText(FText::FromString(
|
||||
DisplayedPreviousGuidanceCaseNavigationLabel));
|
||||
}
|
||||
if (PreviousGuidanceCaseButton != nullptr)
|
||||
{
|
||||
|
|
@ -26364,7 +26465,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
}
|
||||
if (NextGuidanceCaseButtonLabel != nullptr)
|
||||
{
|
||||
NextGuidanceCaseButtonLabel->SetText(FText::FromString(TEXT("Next Guidance Case")));
|
||||
DisplayedNextGuidanceCaseNavigationLabel = TEXT("Next Guidance Case");
|
||||
NextGuidanceCaseButtonLabel->SetText(FText::FromString(
|
||||
DisplayedNextGuidanceCaseNavigationLabel));
|
||||
}
|
||||
if (NextGuidanceCaseButton != nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -831,6 +831,10 @@ public:
|
|||
FHyperTwistTrainingCoachDashboardGuidancePreviewCaseDetailInspectSurface
|
||||
GetDisplayedGuidancePreviewCaseDetailInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardGuidancePreviewCaseNavigationInspectSurface
|
||||
GetDisplayedGuidancePreviewCaseNavigationInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardMethodDrillDiagnosticsInspectSurface
|
||||
GetDisplayedMethodDrillDiagnosticsInspectSurface() const;
|
||||
|
|
@ -2121,6 +2125,8 @@ private:
|
|||
FString DisplayedNextTemplateLaunchNavigationLabel;
|
||||
FString DisplayedPreviousAttemptNavigationLabel;
|
||||
FString DisplayedNextAttemptNavigationLabel;
|
||||
FString DisplayedPreviousGuidanceCaseNavigationLabel;
|
||||
FString DisplayedNextGuidanceCaseNavigationLabel;
|
||||
EHyperTwistCoachDashboardGuidancePreviewLane ActiveGuidancePreviewLane =
|
||||
EHyperTwistCoachDashboardGuidancePreviewLane::None;
|
||||
int32 SelectedGuidancePreviewCaseIndex = INDEX_NONE;
|
||||
|
|
|
|||
|
|
@ -11303,6 +11303,73 @@ struct FHyperTwistTrainingCoachDashboardGuidancePreviewCaseDetailInspectSurface
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardGuidancePreviewCaseNavigationInspectSurface
|
||||
{
|
||||
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 PreviousLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString NextLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ActivePreviewLaneLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DeckLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedCaseId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedCasePromptLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedCaseOrdinal;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 SelectedCaseIndex = INDEX_NONE;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 TotalCaseCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasActivePreviewDeck = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasSelectedCase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClosedLoopIdleDashboard = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bPreviousEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bNextEnabled = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| bHasActivePreviewDeck
|
||||
|| bHasSelectedCase
|
||||
|| bPreviousEnabled
|
||||
|| bNextEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardGuidanceRationaleInspectSurface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 adjacent in that same live dashboard consumer lane and adds the preferred template-launch plus recommended/follow-up preview action control surface trio over the already-derived launch/preview button labels and enablement posture, so gameplay/Blueprint callers can inspect the exact surfaced template/preview action labels and their gating state without scraping widget button text
|
||||
- the next best clean move is to stay adjacent in that same live dashboard consumer lane and expose the guidance preview case navigation control surface pair over the already-derived `Prev Guidance Case` / `Next Guidance Case` labels and enablement posture
|
||||
- the latest landed bounded `Phase 4` packet stays adjacent in that same live dashboard consumer lane and adds the guidance preview case navigation control surface over the already-derived `Prev Guidance Case` / `Next Guidance Case` labels and enablement posture, so gameplay/Blueprint callers can inspect the exact surfaced preview-case navigation labels and their gating state without scraping widget button text
|
||||
- the next best clean move is to stay adjacent in that same live dashboard consumer lane and expose the preview-deck plus start-selected-preview-case action control pair over the already-derived launch button labels and enablement posture
|
||||
- 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
|
||||
|
||||
## Donor portfolio phase taxonomy
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# HyperTwist Phase 4 dashboard live guidance preview case navigation control inspect surface packet
|
||||
|
||||
- bounded Phase `4` dashboard-consumer slice
|
||||
- date: `2026-05-10`
|
||||
|
||||
## Intent
|
||||
|
||||
Stay adjacent in the live dashboard consumer lane and expose the guidance preview case navigation controls directly to gameplay and Blueprint callers.
|
||||
|
||||
## Why this packet exists
|
||||
|
||||
`UHyperTwistCoachDashboardWidget` already displayed:
|
||||
|
||||
- the `Prev Guidance Case` action label
|
||||
- the `Next Guidance Case` action label
|
||||
- the enablement posture behind those two preview-case navigation controls
|
||||
|
||||
But that control band still only surfaced through button labels and `SetIsEnabled` state. Callers still had to scrape widget controls to understand whether the dashboard currently has a navigable preview deck, which preview case is selected, and whether the previous/next navigation pair is actually actionable.
|
||||
|
||||
## What changed
|
||||
|
||||
- added `FHyperTwistTrainingCoachDashboardGuidancePreviewCaseNavigationInspectSurface`
|
||||
- added `GetDisplayedGuidancePreviewCaseNavigationInspectSurface()`
|
||||
- retained the exact displayed `Prev Guidance Case` and `Next Guidance Case` labels inside the widget so the new surface reports the same live strings the dashboard is already presenting
|
||||
- kept the packet bounded to `UHyperTwistCoachDashboardWidget` plus shared surface types, with no preview-deck derivation refactor 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 exact displayed `Prev Guidance Case` label
|
||||
- the exact displayed `Next Guidance Case` label
|
||||
- whether previous navigation is currently enabled
|
||||
- whether next navigation is currently enabled
|
||||
- the active preview lane, selected case ordinal, selected case id, and surfaced prompt behind those controls
|
||||
|
||||
without scraping widget button text or reopening preview-case navigation gating logic.
|
||||
|
||||
## 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 consumer lane and expose the preview-deck plus start-selected-preview-case action control pair over the already-derived launch button labels and enablement posture.
|
||||
Loading…
Add table
Reference in a new issue