diff --git a/Source/ComboInput/Private/Components/ComboManagerComponent.cpp b/Source/ComboInput/Private/Components/ComboManagerComponent.cpp index 32b19b3..7d39d3f 100644 --- a/Source/ComboInput/Private/Components/ComboManagerComponent.cpp +++ b/Source/ComboInput/Private/Components/ComboManagerComponent.cpp @@ -34,6 +34,10 @@ void UComboManagerComponent::InitializeComponent() void UComboManagerComponent::SetComboGraph(const UComboActionGraph *Graph) { this->ComboGraph = Graph; + + this->FoundInputsCache.Empty(); + this->FindAllUsedInputs(); + this->ActiveNode = this->ComboGraph->StartNode; this->PreviousNode = nullptr; } @@ -149,6 +153,43 @@ void UComboManagerComponent::ResetCombo() } +TSet &UComboManagerComponent::FindAllUsedInputs() +{ + if (this->FoundInputsCache.IsEmpty()) + { + // First check the graph for inputs to respond to. + this->FindAllUsedInputs_RecurseGraph(this->ComboGraph->StartNode, this->FoundInputsCache); + + // Next check the fallback actions for supplementary inputs to respond to. + TArray> FallbackInputs; + this->FallbackActions.GetKeys(FallbackInputs); + for (const TObjectPtr &FallbackInput : FallbackInputs) + { + this->FoundInputsCache.Add(FallbackInput); + } + + // Finally check the offset action for the final input to respond to. + if (this->OffsetMap.ComboInput) + { + this->FoundInputsCache.Add(this->OffsetMap.ComboInput); + } + } + + return this->FoundInputsCache; +} +void UComboManagerComponent::FindAllUsedInputs_RecurseGraph(const UComboActionGraphNode *CurrentNode, TSet &FoundInputs) +{ + for (const UComboActionGraphNode *NextNode : CurrentNode->ChildrenNodes) + { + // It should be safe to assume all of our nodes are action nodes. If at some point + // this becomes less reliable, this should be changed. But just for the sake of + // saving a bit of performance on start-up, we're doing this right now. + checkf(NextNode->GetClass() == UComboActionGraphNode_ActionNode::StaticClass(), TEXT("This graph contains non-action nodes. The cast in this function will fail.")); + FoundInputs.Add(static_cast(NextNode)->GetComboInput()); + this->FindAllUsedInputs_RecurseGraph(NextNode, FoundInputs); + } +} + const UComboActionGraphNode *UComboManagerComponent::FindActiveNodeData(const UComboActionGraphNode *CurrentNode, const UComboInputAsset *Input, const EComboActionTriggerEvent TriggerEvent, const UComboAction *&ComboAction) { checkf(CurrentNode, TEXT("Attempting to find an active node from a null node.")); diff --git a/Source/ComboInput/Private/Components/InputBufferComponent.cpp b/Source/ComboInput/Private/Components/InputBufferComponent.cpp index 57f41fb..9f5b738 100644 --- a/Source/ComboInput/Private/Components/InputBufferComponent.cpp +++ b/Source/ComboInput/Private/Components/InputBufferComponent.cpp @@ -28,14 +28,15 @@ void UInputBufferComponent::InitializeComponent() // Get the player character and try to connect to its combo manager. this->OnNewComboInput.BindUObject(ComboManager, &UComboManagerComponent::HandleComboInput); + const TSet &ComboInputs = ComboManager->FindAllUsedInputs(); + // Get all unique EnhancedInput actions bound to combo input actions. - const UInputBufferGlobalSettings *Settings = GetDefault(); TSet InputActionsToBind; - for (TSoftObjectPtr ComboInput : Settings->ComboInputs) + for (const UComboInputAsset *ComboInput : ComboInputs) { - if (ComboInput.IsValid()) + if (ComboInput) { - this->ComboInputList.Emplace(ComboInput.Get()); + this->ComboInputList.Emplace(ComboInput); for (const UInputAction *InputAction : ComboInput->ActionGroup) { InputActionsToBind.Add(InputAction); @@ -43,7 +44,7 @@ void UInputBufferComponent::InitializeComponent() } else { - UE_LOG(LogInputBufferComponent, Verbose, TEXT("Invalid combo action found in Combo Actions list in %s"), *Settings->GetClass()->GetName()); + UE_LOG(LogInputBufferComponent, Verbose, TEXT("Invalid combo input found")); } } for (const UInputAction *InputAction : InputActionsToBind) diff --git a/Source/ComboInput/Public/Components/ComboManagerComponent.h b/Source/ComboInput/Public/Components/ComboManagerComponent.h index ab29e9b..a927474 100644 --- a/Source/ComboInput/Public/Components/ComboManagerComponent.h +++ b/Source/ComboInput/Public/Components/ComboManagerComponent.h @@ -58,6 +58,9 @@ public: this->ComboActionEventBindings.Emplace(Key.Key, MoveTemp(Delegate)); } + // Recursively search the graph for all inputs used by the graph. + TSet &FindAllUsedInputs(); + protected: UPROPERTY(BlueprintReadOnly, EditDefaultsOnly) TObjectPtr ComboGraph; @@ -89,6 +92,7 @@ private: void ResetCombo(); const UComboActionGraphNode *FindActiveNodeData(const UComboActionGraphNode *CurrentNode, const UComboInputAsset *Input, const EComboActionTriggerEvent TriggerEvent, const UComboAction *&ComboAction); + void FindAllUsedInputs_RecurseGraph(const UComboActionGraphNode *CurrentNode, TSet &FoundInputs); void BroadcastDelegates(const class UComboAction *ComboAction, const EComboActionTriggerEvent &TriggerEvent); @@ -102,6 +106,9 @@ private: TMap ComboActionEventBindings; TObjectPtr AttachedInputBuffer; + + // Cache of combo inputs found in the current graph. + TSet FoundInputsCache; FTimerHandle FinishTransitionTimer; FTimerHandle DEBUG__ResetComboTimer; diff --git a/Source/ComboInput/Public/GlobalSettings/InputBufferGlobalSettings.h b/Source/ComboInput/Public/GlobalSettings/InputBufferGlobalSettings.h index 28a1923..1275b08 100644 --- a/Source/ComboInput/Public/GlobalSettings/InputBufferGlobalSettings.h +++ b/Source/ComboInput/Public/GlobalSettings/InputBufferGlobalSettings.h @@ -16,12 +16,6 @@ class COMBOINPUT_API UInputBufferGlobalSettings : public UDeveloperSettingsBacke GENERATED_BODY() public: - // List of possible combo inputs that can be taken. A combo input is selected from this list - // either if an action is made while the current combo is inactive, or when the previous - // action expires. - UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly) - TSet> ComboInputs; - // Length of time after releasing an input to keep the associated combo action buffered before clearing it. UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, meta=(UIMin="0.0", UIMax="0.5", ClampMin="0.0", ClampMax="0.5")) float InputReleaseExpirationTimerLength = 0.15f;