From bec22af2a038cfe439b1db82e1afa209fb74d96a Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Fri, 1 May 2026 22:59:51 +0200 Subject: [PATCH] Apply imported selector options to active runs --- .../HyperTwistTrainingCatalogLibrary.cpp | 41 +++++++++++++++++++ .../HyperTwistTrainingRuntimeLibrary.cpp | 14 +++++++ .../HyperTwistTrainingSubsystem.cpp | 36 ++++++++++++++++ .../HyperTwistTrainingCatalogLibrary.h | 8 ++++ .../HyperTwistTrainingRuntimeLibrary.h | 7 ++++ .../HyperTwistTrainingSubsystem.h | 6 +++ 6 files changed, 112 insertions(+) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.cpp index 2175bc1..d0af91e 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.cpp @@ -2760,6 +2760,47 @@ bool UHyperTwistTrainingCatalogLibrary::TryGetImportedRuntimeSelectorOptionCases return OutCases.Num() > 0; } +bool UHyperTwistTrainingCatalogLibrary::TryGetImportedRuntimeSelectorOptionCaseFromDeck( + const FHyperTwistTrainingDeck& Deck, + const FString& SelectorId, + const FString& OptionId, + FHyperTwistTrainingCase& OutCase +) +{ + OutCase = FHyperTwistTrainingCase(); + + FHyperTwistTrainingImportedRuntimeSelector Selector; + if (!TryGetImportedRuntimeSelectorFromDeck(Deck, SelectorId, Selector) || OptionId.IsEmpty()) + { + return false; + } + + const FHyperTwistTrainingImportedRuntimeSelectorOption* MatchingOption = Selector.Options.FindByPredicate( + [&OptionId](const FHyperTwistTrainingImportedRuntimeSelectorOption& Candidate) + { + return Candidate.OptionId == OptionId || Candidate.OptionValue == OptionId; + } + ); + if (MatchingOption == nullptr) + { + return false; + } + + const FHyperTwistTrainingCase* MatchingCase = Deck.Cases.FindByPredicate( + [&MatchingOption](const FHyperTwistTrainingCase& Candidate) + { + return HyperTwistTrainingCatalogLibraryInternal::DoesSelectorOptionMatchCase(*MatchingOption, Candidate); + } + ); + if (MatchingCase == nullptr) + { + return false; + } + + OutCase = *MatchingCase; + return OutCase.IsStructurallyValid(); +} + FHyperTwistTrainingMethodDescriptor UHyperTwistTrainingCatalogLibrary::DescribeTrainingDeckMethod( const FHyperTwistTrainingDeck& Deck ) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp index 4596800..f831e1b 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.cpp @@ -102,6 +102,20 @@ bool UHyperTwistTrainingRuntimeLibrary::TryGetActiveImportedRuntimeSelectorOptio return false; } +FHyperTwistTrainingRunState UHyperTwistTrainingRuntimeLibrary::ApplyActiveImportedRuntimeSelectorOption( + UObject* WorldContextObject, + const FString& SelectorId, + const FString& OptionId +) +{ + if (UHyperTwistTrainingSubsystem* TrainingSubsystem = GetTrainingSubsystem(WorldContextObject)) + { + return TrainingSubsystem->ApplyActiveImportedRuntimeSelectorOption(SelectorId, OptionId); + } + + return FHyperTwistTrainingRunState(); +} + FHyperTwistTrainingMethodDrillRunState UHyperTwistTrainingRuntimeLibrary::GetActiveMethodDrillRunState( UObject* WorldContextObject ) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp index 36bb8d9..e54431c 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp @@ -745,6 +745,42 @@ bool UHyperTwistTrainingSubsystem::TryGetActiveImportedRuntimeSelectorOptionCase ); } +FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::ApplyActiveImportedRuntimeSelectorOption( + const FString& SelectorId, + const FString& OptionId +) +{ + if (!HasActiveRun()) + { + return FHyperTwistTrainingRunState(); + } + + FHyperTwistTrainingCase SelectedCase; + if (!UHyperTwistTrainingCatalogLibrary::TryGetImportedRuntimeSelectorOptionCaseFromDeck( + ActiveRunState.ActiveDeck, + SelectorId, + OptionId, + SelectedCase)) + { + return FHyperTwistTrainingRunState(); + } + + FHyperTwistTrainingDeck SelectedDeck = ActiveRunState.ActiveDeck; + SelectedDeck.SelectionPolicy = EHyperTwistTrainingSelectionPolicy::Scripted; + SelectedDeck.Cases.Reset(); + SelectedDeck.Cases.Add(SelectedCase); + SelectedDeck.Tags.AddUnique(TEXT("runtime-surface:selector-option-applied")); + SelectedDeck.Tags.AddUnique(FString::Printf(TEXT("selector:%s"), *SelectorId.ToLower())); + SelectedDeck.Tags.AddUnique(FString::Printf(TEXT("selector-option:%s"), *OptionId.ToLower())); + + return StartTrainingRunFromDeck( + SelectedDeck, + ActiveRunState.Session.UserId, + ActiveRunState.Session.TrainingSessionId, + ActiveRunState.Session.Mode + ); +} + FHyperTwistTrainingMethodDrillRunState UHyperTwistTrainingSubsystem::GetActiveMethodDrillRunState() const { return ActiveMethodDrillRunState; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.h index ae5ae36..683b3db 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCatalogLibrary.h @@ -154,6 +154,14 @@ public: TArray& OutCases ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Catalog") + static bool TryGetImportedRuntimeSelectorOptionCaseFromDeck( + const FHyperTwistTrainingDeck& Deck, + const FString& SelectorId, + const FString& OptionId, + FHyperTwistTrainingCase& OutCase + ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Catalog") static FHyperTwistTrainingMethodDescriptor DescribeTrainingDeckMethod( const FHyperTwistTrainingDeck& Deck diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h index 96afd0c..d3e9d23 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h @@ -48,6 +48,13 @@ public: TArray& OutCases ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training", meta = (WorldContext = "WorldContextObject")) + static FHyperTwistTrainingRunState ApplyActiveImportedRuntimeSelectorOption( + UObject* WorldContextObject, + const FString& SelectorId, + const FString& OptionId + ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Drill", meta = (WorldContext = "WorldContextObject")) static FHyperTwistTrainingMethodDrillRunState GetActiveMethodDrillRunState(UObject* WorldContextObject); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h index 4caf483..c6bbfba 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSubsystem.h @@ -38,6 +38,12 @@ public: TArray& OutCases ) const; + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training") + FHyperTwistTrainingRunState ApplyActiveImportedRuntimeSelectorOption( + const FString& SelectorId, + const FString& OptionId + ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Drill") FHyperTwistTrainingMethodDrillRunState GetActiveMethodDrillRunState() const;