Expose gameplay generated-mode selector context surface
This commit is contained in:
parent
6b418f78b1
commit
a8be3a2106
9 changed files with 433 additions and 2 deletions
|
|
@ -6809,3 +6809,200 @@ UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeLaunchExecutionContextS
|
|||
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorApplicationContextSurface(
|
||||
const FHyperTwistTrainingDeck& ActiveDeck,
|
||||
const FHyperTwistTrainingImportedRuntimeSelectionState& ImportedRuntimeSelectionState,
|
||||
const FHyperTwistTrainingImportedGeneratedModeLaunchConfig& LaunchConfig,
|
||||
const FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface& LaunchExecutionContextSurface
|
||||
)
|
||||
{
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface Surface;
|
||||
Surface.Headline = TEXT("Generated Mode Selectors");
|
||||
|
||||
const FHyperTwistTrainingImportedRuntimeSurface& RuntimeSurface = ActiveDeck.ImportedRuntimeSurface;
|
||||
Surface.bHasGeneratedModeSurface = RuntimeSurface.IsStructurallyValid()
|
||||
&& RuntimeSurface.SurfaceKind.Equals(TEXT("generated-mode"), ESearchCase::IgnoreCase);
|
||||
Surface.bHasSelectionState = ImportedRuntimeSelectionState.IsStructurallyValid();
|
||||
Surface.bHasLaunchConfig = LaunchConfig.IsStructurallyValid();
|
||||
Surface.bWillRefreshLaunchRequestOnExecute =
|
||||
LaunchExecutionContextSurface.bWillRefreshLaunchRequestOnExecute;
|
||||
Surface.bSelectionStateMatchesSurface = !Surface.bHasGeneratedModeSurface
|
||||
|| !Surface.bHasSelectionState
|
||||
|| ImportedRuntimeSelectionState.SurfaceId == RuntimeSurface.SurfaceId;
|
||||
|
||||
Surface.SurfaceId = Surface.bHasLaunchConfig
|
||||
? LaunchConfig.SurfaceId
|
||||
: (Surface.bHasGeneratedModeSurface
|
||||
? RuntimeSurface.SurfaceId
|
||||
: ImportedRuntimeSelectionState.SurfaceId);
|
||||
Surface.SurfaceLabel = Surface.bHasLaunchConfig
|
||||
? LaunchConfig.SurfaceLabel
|
||||
: (Surface.bHasGeneratedModeSurface ? RuntimeSurface.SurfaceLabel : FString());
|
||||
Surface.SurfaceKind = Surface.bHasGeneratedModeSurface
|
||||
? RuntimeSurface.SurfaceKind
|
||||
: ImportedRuntimeSelectionState.SurfaceKind;
|
||||
Surface.RuntimeModeId = Surface.bHasLaunchConfig
|
||||
? LaunchConfig.RuntimeModeId
|
||||
: (Surface.bHasGeneratedModeSurface ? RuntimeSurface.RuntimeModeId : FString());
|
||||
Surface.GeneratorType = Surface.bHasLaunchConfig
|
||||
? LaunchConfig.GeneratorType
|
||||
: (Surface.bHasGeneratedModeSurface ? RuntimeSurface.GeneratorType : FString());
|
||||
|
||||
TSet<FString> RequiredSelectorIds;
|
||||
if (Surface.bHasGeneratedModeSurface)
|
||||
{
|
||||
for (const FHyperTwistTrainingImportedRuntimeSelector& Selector : RuntimeSurface.Selectors)
|
||||
{
|
||||
if (Selector.IsStructurallyValid())
|
||||
{
|
||||
RequiredSelectorIds.Add(Selector.SelectorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Surface.RequiredSelectorCount = RequiredSelectorIds.Num();
|
||||
|
||||
TSet<FString> SelectedSelectorIds;
|
||||
if (Surface.bHasSelectionState)
|
||||
{
|
||||
for (const FHyperTwistTrainingImportedRuntimeSelectorChoice& Choice :
|
||||
ImportedRuntimeSelectionState.SelectorChoices)
|
||||
{
|
||||
if (!Choice.IsStructurallyValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (RequiredSelectorIds.Num() > 0 && !RequiredSelectorIds.Contains(Choice.SelectorId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SelectedSelectorIds.Add(Choice.SelectorId);
|
||||
}
|
||||
}
|
||||
Surface.SelectedSelectorCount = SelectedSelectorIds.Num();
|
||||
Surface.MissingSelectorCount = FMath::Max(
|
||||
Surface.RequiredSelectorCount - Surface.SelectedSelectorCount,
|
||||
0
|
||||
);
|
||||
Surface.bHasFullSelectorCoverage = Surface.bHasLaunchConfig
|
||||
|| (Surface.bHasSelectionState
|
||||
&& Surface.bSelectionStateMatchesSurface
|
||||
&& Surface.RequiredSelectorCount > 0
|
||||
&& Surface.MissingSelectorCount == 0);
|
||||
|
||||
const FString SurfaceLabelSummary = Surface.SurfaceLabel.IsEmpty()
|
||||
? (Surface.SurfaceId.IsEmpty() ? TEXT("n/a") : Surface.SurfaceId)
|
||||
: Surface.SurfaceLabel;
|
||||
const FString SurfaceIdSummary = Surface.SurfaceId.IsEmpty() ? TEXT("n/a") : Surface.SurfaceId;
|
||||
const FString SurfaceKindSummary = Surface.SurfaceKind.IsEmpty() ? TEXT("n/a") : Surface.SurfaceKind;
|
||||
const FString RuntimeModeSummary = Surface.RuntimeModeId.IsEmpty() ? TEXT("n/a") : Surface.RuntimeModeId;
|
||||
const FString GeneratorSummary = Surface.GeneratorType.IsEmpty() ? TEXT("n/a") : Surface.GeneratorType;
|
||||
const FString CoverageSuffix = Surface.MissingSelectorCount > 0
|
||||
? FString::Printf(TEXT(" | missing: %d"), Surface.MissingSelectorCount)
|
||||
: FString();
|
||||
|
||||
if (Surface.RequiredSelectorCount > 0)
|
||||
{
|
||||
Surface.CoverageLine = FString::Printf(
|
||||
TEXT("Coverage: %d/%d selectors selected%s"),
|
||||
Surface.SelectedSelectorCount,
|
||||
Surface.RequiredSelectorCount,
|
||||
*CoverageSuffix
|
||||
);
|
||||
}
|
||||
else if (Surface.bHasSelectionState)
|
||||
{
|
||||
Surface.CoverageLine = FString::Printf(
|
||||
TEXT("Coverage: %d selector choice%s cached"),
|
||||
Surface.SelectedSelectorCount,
|
||||
Surface.SelectedSelectorCount == 1 ? TEXT("") : TEXT("s")
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.CoverageLine = TEXT("Coverage: no generated-mode selector choices are cached");
|
||||
}
|
||||
if (!Surface.bSelectionStateMatchesSurface && Surface.bHasGeneratedModeSurface && Surface.bHasSelectionState)
|
||||
{
|
||||
Surface.CoverageLine += TEXT(" | selection state is bound to a different surface");
|
||||
}
|
||||
|
||||
Surface.IdentityLine = FString::Printf(
|
||||
TEXT("Identity: %s | kind: %s | mode: %s | generator: %s"),
|
||||
*SurfaceLabelSummary,
|
||||
*SurfaceKindSummary,
|
||||
*RuntimeModeSummary,
|
||||
*GeneratorSummary
|
||||
);
|
||||
|
||||
if (LaunchExecutionContextSurface.bHasExecutionTarget)
|
||||
{
|
||||
Surface.RefreshLine = Surface.bWillRefreshLaunchRequestOnExecute
|
||||
? TEXT("Refresh posture: execute will rebuild the stored request from the current selector set.")
|
||||
: TEXT("Refresh posture: execute can use the current stored request without rebuilding it.");
|
||||
}
|
||||
else if (Surface.bHasLaunchConfig || Surface.bHasGeneratedModeSurface)
|
||||
{
|
||||
Surface.RefreshLine =
|
||||
TEXT("Refresh posture: no generated-mode execution target is currently staged.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.RefreshLine =
|
||||
TEXT("Refresh posture: selector application must stage a generated-mode target first.");
|
||||
}
|
||||
|
||||
if (Surface.bHasLaunchConfig)
|
||||
{
|
||||
Surface.StatusLine = Surface.bWillRefreshLaunchRequestOnExecute
|
||||
? TEXT("Generated-mode selector application is complete; execute will refresh the stored request from the current selector set.")
|
||||
: TEXT("Generated-mode selector application is complete for the active generated-mode surface.");
|
||||
}
|
||||
else if (Surface.bHasGeneratedModeSurface && Surface.bHasSelectionState && !Surface.bSelectionStateMatchesSurface)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector application is cached against a different surface than the active generated-mode deck.");
|
||||
}
|
||||
else if (Surface.bHasGeneratedModeSurface && Surface.RequiredSelectorCount > 0 && Surface.MissingSelectorCount == 0)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector application has full selector coverage, but launch execution is not yet staged.");
|
||||
}
|
||||
else if (Surface.bHasGeneratedModeSurface && Surface.RequiredSelectorCount > 0 && Surface.SelectedSelectorCount > 0)
|
||||
{
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("Generated-mode selector application is in progress; %d selector%s still need selection."),
|
||||
Surface.MissingSelectorCount,
|
||||
Surface.MissingSelectorCount == 1 ? TEXT("") : TEXT("s")
|
||||
);
|
||||
}
|
||||
else if (Surface.bHasGeneratedModeSurface)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector application has not started for the active generated-mode surface.");
|
||||
}
|
||||
else if (Surface.bHasSelectionState)
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector application is cached, but no active generated-mode surface is currently staged.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.StatusLine =
|
||||
TEXT("Generated-mode selector application is not currently cached.");
|
||||
}
|
||||
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Surface: %s (%s) | Runtime: %s | Generator: %s | Launch posture: %s"),
|
||||
*SurfaceLabelSummary,
|
||||
*SurfaceIdSummary,
|
||||
*RuntimeModeSummary,
|
||||
*GeneratorSummary,
|
||||
LaunchExecutionContextSurface.StatusLine.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *LaunchExecutionContextSurface.StatusLine
|
||||
);
|
||||
|
||||
return Surface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -677,6 +677,20 @@ UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeLaunchExecutionCon
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeSelectorApplicationContextSurface() const
|
||||
{
|
||||
const FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
|
||||
LaunchExecutionContextSurface =
|
||||
GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface();
|
||||
return UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorApplicationContextSurface(
|
||||
CachedRunState.ActiveDeck,
|
||||
CachedImportedRuntimeSelectionState,
|
||||
CachedImportedGeneratedModeLaunchConfig,
|
||||
LaunchExecutionContextSurface
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartCoachRecommendedRun(
|
||||
const int32 MaxCases,
|
||||
const FString& StartActionSourceLabel
|
||||
|
|
|
|||
|
|
@ -658,6 +658,20 @@ AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeLaunchExecutionCo
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeSelectorApplicationContextSurface() const
|
||||
{
|
||||
const FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
|
||||
LaunchExecutionContextSurface =
|
||||
GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface();
|
||||
return UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeSelectorApplicationContextSurface(
|
||||
CachedRunState.ActiveDeck,
|
||||
CachedImportedRuntimeSelectionState,
|
||||
CachedImportedGeneratedModeLaunchConfig,
|
||||
LaunchExecutionContextSurface
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartCoachRecommendedTrainingRun(
|
||||
const int32 MaxCases
|
||||
)
|
||||
|
|
|
|||
|
|
@ -668,4 +668,14 @@ public:
|
|||
const FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface&
|
||||
VerificationRecognitionReviewContextSurface
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
static FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
DeriveCoachGeneratedModeSelectorApplicationContextSurface(
|
||||
const FHyperTwistTrainingDeck& ActiveDeck,
|
||||
const FHyperTwistTrainingImportedRuntimeSelectionState& ImportedRuntimeSelectionState,
|
||||
const FHyperTwistTrainingImportedGeneratedModeLaunchConfig& LaunchConfig,
|
||||
const FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface&
|
||||
LaunchExecutionContextSurface
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -248,6 +248,10 @@ public:
|
|||
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
|
||||
GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorApplicationContextSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingRunState StartCoachRecommendedRun(
|
||||
int32 MaxCases,
|
||||
|
|
|
|||
|
|
@ -229,6 +229,10 @@ public:
|
|||
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
|
||||
GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
GetDisplayedCoachGeneratedModeSelectorApplicationContextSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
|
||||
FHyperTwistTrainingRunState StartCoachRecommendedTrainingRun(int32 MaxCases);
|
||||
|
||||
|
|
|
|||
|
|
@ -8387,3 +8387,79 @@ struct FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
|
|||
|| bHasBlockedExecution;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Headline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString CoverageLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString IdentityLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RefreshLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SurfaceId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SurfaceLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SurfaceKind;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RuntimeModeId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString GeneratorType;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 SelectedSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 RequiredSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 MissingSelectorCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasGeneratedModeSurface = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasSelectionState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLaunchConfig = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSelectionStateMatchesSurface = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasFullSelectorCoverage = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bWillRefreshLaunchRequestOnExecute = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !CoverageLine.IsEmpty()
|
||||
|| !IdentityLine.IsEmpty()
|
||||
|| bHasGeneratedModeSurface
|
||||
|| bHasSelectionState
|
||||
|| bHasLaunchConfig;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ Current correction call from the source-exposed audit and current execution refr
|
|||
- the imported generated-mode gap is closed; request/config/selection plumbing and the bounded clean-room executor are already landed in first-party code
|
||||
- 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 latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin generated-mode launch-request / execution context surface over the already-cached generated-mode request / execution panel state, so gameplay/Blueprint callers can render latest generated-mode request, runtime mode, selector summary, execution readiness, and blocked-reason context without reading raw request/execution fields directly
|
||||
- the current next bounded packet is to expose one thin generated-mode selector/application context surface on those same two consumer surfaces so gameplay/Blueprint callers can render active selector-state coverage, generator/runtime identity, and request-refresh implications without reading raw imported selection/config payloads directly
|
||||
- the latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin generated-mode selector/application context surface over the already-cached imported selection and launch-config state, so gameplay/Blueprint callers can render active selector-state coverage, generator/runtime identity, and request-refresh implications without reading raw imported selection/config payloads directly
|
||||
- the current next bounded packet is to expose one thin generated-mode selector roster / option-availability surface on those same two consumer surfaces so gameplay/Blueprint callers can render active selector labels, bindings, and unresolved option availability without reading raw imported runtime selector arrays or option payloads directly
|
||||
- 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,112 @@
|
|||
# HyperTwist Phase 4 gameplay generated-mode selector / application context surface packet
|
||||
|
||||
Created on `2026-05-08`
|
||||
|
||||
Status:
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- bounded Phase `4` gameplay-facing consumer slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet closes the next thin gameplay-facing consumer seam above the panel-widget and session-actor generated-mode helpers by exposing one pure selector / application context surface over the already-cached imported selection state and generated-mode launch-config state.
|
||||
|
||||
The open tasks were:
|
||||
|
||||
- stop forcing gameplay / Blueprint callers to read raw imported selection-state payloads and launch-config payloads just to render selector coverage, generator/runtime identity, and request-refresh implications
|
||||
- expose one thin first-party context surface that summarizes active selector coverage, generated-mode surface identity, runtime mode, generator type, and refresh-on-execute posture
|
||||
- keep that surface derived from already-cached gameplay consumer state instead of widening into backend selector application or execution logic
|
||||
|
||||
It is not:
|
||||
|
||||
- a new selector-application behavior packet
|
||||
- a generated-mode execution packet
|
||||
- a selector-catalog UI composition pass
|
||||
- a broader gameplay HUD packet
|
||||
|
||||
## Scope
|
||||
|
||||
Bounded lane:
|
||||
|
||||
- add a first-party generated-mode selector / application context surface in shared training types
|
||||
- add a coach-library helper that derives the surface from the active deck imported runtime surface, cached imported selection state, cached generated-mode launch config, and the already-landed launch / execution context surface
|
||||
- expose that derived context surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`
|
||||
- keep the derivation presentation-only and rooted in already-cached gameplay consumer state
|
||||
|
||||
Out of scope:
|
||||
|
||||
- changing selector-application persistence behavior
|
||||
- changing generated-mode launch-config derivation rules
|
||||
- changing generated-mode execution behavior
|
||||
- importing dashboard-only generated-mode inspection into gameplay consumers
|
||||
|
||||
## Why this was the right next packet
|
||||
|
||||
Before this slice:
|
||||
|
||||
- gameplay-facing panel/session consumers already exposed a truthful generated-mode launch / execution context surface
|
||||
|
||||
But one thin consumer seam was still open:
|
||||
|
||||
- callers could explain current generated-mode request and execution posture
|
||||
- but they still had to read raw imported selection/config payloads to explain whether selector application was complete, what runtime/generator identity those selections targeted, and whether execute would rebuild the stored request
|
||||
|
||||
That meant:
|
||||
|
||||
- execution posture was thin and reusable
|
||||
- but selector-application context still leaked raw imported payloads into callers
|
||||
|
||||
So the next bounded move was:
|
||||
|
||||
- keep the already-landed launch / execution context surface unchanged
|
||||
- and expose one narrow selector / application context surface above the cached imported selection/config state
|
||||
|
||||
## What landed
|
||||
|
||||
Primary code changes:
|
||||
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
|
||||
- added `FHyperTwistTrainingCoachGeneratedModeSelectorApplicationContextSurface`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp`
|
||||
- added `DeriveCoachGeneratedModeSelectorApplicationContextSurface(...)`
|
||||
- context is derived from the active imported runtime surface, cached imported selection state, cached generated-mode launch config, and the already-landed launch / execution context surface
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
|
||||
- added `GetDisplayedCoachGeneratedModeSelectorApplicationContextSurface()`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp`
|
||||
- added `GetDisplayedCoachGeneratedModeSelectorApplicationContextSurface()`
|
||||
|
||||
## Product effect
|
||||
|
||||
The gameplay-facing generated-mode consumer layer is now more complete:
|
||||
|
||||
- gameplay / Blueprint callers can read one pure surface to render selector coverage, missing-selector count, generated-mode surface identity, runtime mode, generator type, and request-refresh implications
|
||||
- callers no longer need to inspect raw imported selection-state or generated-mode launch-config payloads directly
|
||||
- the surface stays aligned with the already-landed generated-mode launch / execution context surface without widening backend behavior
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- shared training types expose a narrow generated-mode selector / application context surface
|
||||
- coach-library derivation consumes already-cached gameplay consumer state rather than adding new runtime fetches
|
||||
- panel-widget callers can fetch the displayed selector / application context surface directly
|
||||
- session-actor callers can fetch the displayed selector / application context surface directly
|
||||
- full product build succeeds
|
||||
|
||||
## Validation checklist
|
||||
|
||||
1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor`
|
||||
2. confirm the new selector / application context surface compiles in shared types and coach library
|
||||
3. confirm panel-widget getters compile and return the derived context surface
|
||||
4. confirm session-actor getters compile and return the derived context surface
|
||||
5. confirm no backend selector-application or generated-mode execution behavior was pulled into the packet
|
||||
|
||||
## Validation result
|
||||
|
||||
- full `Development Editor|Win64` build succeeded on `2026-05-08`
|
||||
- build completed with `0` warnings and `0` errors
|
||||
|
||||
## Next bounded follow-on slice
|
||||
|
||||
- stay on the same gameplay-facing consumer lane and expose one thin generated-mode selector roster / option-availability surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`, so gameplay callers can render active selector labels, bindings, and unresolved option availability without reading raw imported runtime selector arrays or option payloads directly
|
||||
Loading…
Add table
Reference in a new issue