diff --git a/Content/Docs/UINavControllerDocs.uasset b/Content/Docs/UINavControllerDocs.uasset index 2a5526fe..6b7b45aa 100644 Binary files a/Content/Docs/UINavControllerDocs.uasset and b/Content/Docs/UINavControllerDocs.uasset differ diff --git a/Content/Docs/UINavDocs.uasset b/Content/Docs/UINavDocs.uasset index dde98c53..13d1c55e 100644 Binary files a/Content/Docs/UINavDocs.uasset and b/Content/Docs/UINavDocs.uasset differ diff --git a/Content/Docs/Updates.uasset b/Content/Docs/Updates.uasset index e5ab89a9..bc22d905 100644 Binary files a/Content/Docs/Updates.uasset and b/Content/Docs/Updates.uasset differ diff --git a/Content/UINavPC.uasset b/Content/UINavPC.uasset index b87108b4..4337393f 100644 Binary files a/Content/UINavPC.uasset and b/Content/UINavPC.uasset differ diff --git a/Source/UINavigation/Private/UINavComponentBox.cpp b/Source/UINavigation/Private/UINavComponentBox.cpp index 75a939d9..7ed31671 100644 --- a/Source/UINavigation/Private/UINavComponentBox.cpp +++ b/Source/UINavigation/Private/UINavComponentBox.cpp @@ -41,13 +41,13 @@ void UUINavComponentBox::BaseConstruct() void UUINavComponentBox::CheckLeftLimit() { if (bLoopOptions) return; - if (OptionIndex == 0) LeftButton->SetIsEnabled(false); + if (OptionIndex <= 0) LeftButton->SetIsEnabled(false); } void UUINavComponentBox::CheckRightLimit() { if (bLoopOptions) return; - if (OptionIndex == GetMaxOptionIndex()) RightButton->SetIsEnabled(false); + if (OptionIndex >= GetMaxOptionIndex()) RightButton->SetIsEnabled(false); } void UUINavComponentBox::UpdateTextToIndex(const int NewIndex) @@ -102,7 +102,7 @@ void UUINavComponentBox::FinishNavigateLeft(const bool bOptionChanged) CheckLeftLimit(); //Enable button if previously disabled - if (!RightButton->bIsEnabled) RightButton->SetIsEnabled(true); + if (!RightButton->bIsEnabled && GetMaxOptionIndex() > 0) RightButton->SetIsEnabled(true); if (bOptionChanged) { @@ -130,7 +130,7 @@ void UUINavComponentBox::FinishNavigateRight(const bool bOptionChanged) CheckRightLimit(); //Enable button if previously disabled - if (!LeftButton->bIsEnabled) LeftButton->SetIsEnabled(true); + if (!LeftButton->bIsEnabled && GetMaxOptionIndex() > 0) LeftButton->SetIsEnabled(true); if (bOptionChanged) { diff --git a/Source/UINavigation/Private/UINavHorizontalComponent.cpp b/Source/UINavigation/Private/UINavHorizontalComponent.cpp index 60949646..22b7d188 100644 --- a/Source/UINavigation/Private/UINavHorizontalComponent.cpp +++ b/Source/UINavigation/Private/UINavHorizontalComponent.cpp @@ -23,7 +23,9 @@ void UUINavHorizontalComponent::NavigateRight() void UUINavHorizontalComponent::Update() { - int MaxOptionIndex = GetMaxOptionIndex(); + const int MaxOptionIndex = GetMaxOptionIndex(); + if (MaxOptionIndex < 1) return; + if (OptionIndex > MaxOptionIndex) OptionIndex = MaxOptionIndex; else if (OptionIndex < 0) OptionIndex = 0; @@ -36,9 +38,9 @@ void UUINavHorizontalComponent::UpdateTextToIndex(int NewIndex) Update(); } -void UUINavHorizontalComponent::ChangeText(FText NewText) +void UUINavHorizontalComponent::ChangeText(const FText NewText) { - NavText->SetText(NewText); + if (NavText != nullptr) NavText->SetText(NewText); } void UUINavHorizontalComponent::OnNavigateLeft_Implementation() diff --git a/Source/UINavigation/Private/UINavOptionBox.cpp b/Source/UINavigation/Private/UINavOptionBox.cpp index ea931f3b..283afada 100644 --- a/Source/UINavigation/Private/UINavOptionBox.cpp +++ b/Source/UINavigation/Private/UINavOptionBox.cpp @@ -24,12 +24,7 @@ int UUINavOptionBox::GetMaxOptionIndex() const } else { - if (StringOptions.Num() > 0) return StringOptions.Num() - 1; - else - { - DISPLAYERROR(TEXT("StringOptions needs to have at least 2 options")); - return 0; - } + return StringOptions.Num() - 1; } } @@ -39,6 +34,6 @@ void UUINavOptionBox::Update() NavText->SetText(bUseNumberRange ? FText::FromString(FString::FromInt(MinRange + OptionIndex*Interval)) : - StringOptions.Num() > OptionIndex ? StringOptions[OptionIndex] : FText()); + StringOptions.IsValidIndex(OptionIndex) ? StringOptions[OptionIndex] : FText()); } diff --git a/Source/UINavigation/Private/UINavPCComponent.cpp b/Source/UINavigation/Private/UINavPCComponent.cpp index f78cb5d2..3d67c221 100644 --- a/Source/UINavigation/Private/UINavPCComponent.cpp +++ b/Source/UINavigation/Private/UINavPCComponent.cpp @@ -49,6 +49,10 @@ void UUINavPCComponent::BeginPlay() VerifyDefaultInputs(); FetchUINavActionKeys(); + if (!FCoreDelegates::OnControllerConnectionChange.IsBoundToObject(this)) + { + FCoreDelegates::OnControllerConnectionChange.AddUObject(this, &UUINavPCComponent::OnControllerConnectionChanged); + } } } @@ -58,6 +62,8 @@ void UUINavPCComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) { FSlateApplication::Get().UnregisterInputPreProcessor(SharedInputProcessor); } + + FCoreDelegates::OnControllerConnectionChange.RemoveAll(this); Super::EndPlay(EndPlayReason); } @@ -203,6 +209,11 @@ void UUINavPCComponent::CallCustomInput(const FName ActionName, const bool bPres } } +void UUINavPCComponent::OnControllerConnectionChanged(bool bConnected, int32 UserId, int32 UserIndex) +{ + IUINavPCReceiver::Execute_OnControllerConnectionChanged(GetOwner(), bConnected, UserId, UserIndex); +} + void UUINavPCComponent::VerifyDefaultInputs() { UUINavSettings *MySettings = GetMutableDefault(); diff --git a/Source/UINavigation/Private/UINavPCReceiver.cpp b/Source/UINavigation/Private/UINavPCReceiver.cpp index 33ca788e..cb2b3cf9 100644 --- a/Source/UINavigation/Private/UINavPCReceiver.cpp +++ b/Source/UINavigation/Private/UINavPCReceiver.cpp @@ -11,8 +11,11 @@ void IUINavPCReceiver::OnInputChanged_Implementation(EInputType From, EInputType { } -void IUINavPCReceiver::OnActiveWidgetChanged_Implementation(UUINavWidget* OldActiveWidget, - UUINavWidget* NewActiveWidget) +void IUINavPCReceiver::OnControllerConnectionChanged_Implementation(bool bConnected, int32 UserId, int32 UserIndex) +{ +} + +void IUINavPCReceiver::OnActiveWidgetChanged_Implementation(UUINavWidget* OldActiveWidget, UUINavWidget* NewActiveWidget) { } diff --git a/Source/UINavigation/Private/UINavSlider.cpp b/Source/UINavigation/Private/UINavSlider.cpp index 48c3cf1c..57a0ac3f 100644 --- a/Source/UINavigation/Private/UINavSlider.cpp +++ b/Source/UINavigation/Private/UINavSlider.cpp @@ -67,7 +67,6 @@ void UUINavSlider::Update() if (NavText != nullptr) NavText->SetText(ValueText); if (NavSpinBox != nullptr) { - bIgnoreSpinBoxCommit = true; NavSpinBox->SetValue(Value); } } @@ -144,11 +143,6 @@ void UUINavSlider::HandleOnMouseCaptureEnd() void UUINavSlider::HandleOnSpinBoxValueChanged(float InValue, ETextCommit::Type CommitMethod) { - if (bIgnoreSpinBoxCommit) - { - bIgnoreSpinBoxCommit = false; - return; - } OptionIndex = IndexFromValue(InValue); Update(); } diff --git a/Source/UINavigation/Private/UINavWidget.cpp b/Source/UINavigation/Private/UINavWidget.cpp index 2d2660ce..51a27e8b 100644 --- a/Source/UINavigation/Private/UINavWidget.cpp +++ b/Source/UINavigation/Private/UINavWidget.cpp @@ -11,6 +11,7 @@ #include "UINavPCComponent.h" #include "UINavPCReceiver.h" #include "UINavPromptWidget.h" +#include "UINavSettings.h" #include "UINavWidgetComponent.h" #include "UINavBlueprintFunctionLibrary.h" #include "UINavMacros.h" @@ -134,8 +135,6 @@ void UUINavWidget::InitialSetup(const bool bRebuilding) if (!IsSelectorValid()) { UINavSetup(); - bShouldTick = false; - return; } else { @@ -153,16 +152,12 @@ void UUINavWidget::ReconfigureSetup() if (!IsSelectorValid()) { UINavSetup(); - return; } else { SetupSelector(); } - bShouldTick = true; - WaitForTick = 0; - for (UUINavWidget* ChildUINavWidget : ChildUINavWidgets) { ChildUINavWidget->ReconfigureSetup(); @@ -514,9 +509,7 @@ void UUINavWidget::RebuildNavigation(const int NewButtonIndex) bMovingSelector = false; bIgnoreMouseEvent = false; bReturning = false; - bShouldTick = true; ReceiveInputType = EReceiveInputType::None; - WaitForTick = 0; HaltedIndex = -1; SelectedButtonIndex = -1; SelectCount = 0; @@ -552,6 +545,9 @@ void UUINavWidget::SetupSelector() SelectorSlot->SetAlignment(FVector2D(0.5f, 0.5f)); SelectorSlot->SetPosition(FVector2D(0.f, 0.f)); + + UINavSetupWaitForTick=0; + bShouldTickUINavSetup = true; } void UUINavWidget::UINavSetup() @@ -574,7 +570,7 @@ void UUINavWidget::UINavSetup() { SetEnableUINavButtons(true, true); } - + bCompletedSetup = true; if (OuterUINavWidget == nullptr) @@ -720,24 +716,41 @@ void UUINavWidget::NativeTick(const FGeometry & MyGeometry, float DeltaTime) { Super::NativeTick(MyGeometry, DeltaTime); - if (!IsSelectorValid() || !bSetupStarted) return; - - if (bMovingSelector) - { - HandleSelectorMovement(DeltaTime); - } - else + if (IsSelectorValid()) { - if (!bShouldTick) return; - - if (WaitForTick == 1) + if (bShouldTickUINavSetup) { - UINavSetup(); - bShouldTick = false; - return; + if (UINavSetupWaitForTick >= 1) + { + UINavSetup(); + bShouldTickUINavSetup = false; + } + else + { + UINavSetupWaitForTick++; + } } + else + { + if (bShouldTickUpdateSelector) + { + if (UpdateSelectorWaitForTick >= 1) + { + if (MoveCurve != nullptr) BeginSelectorMovement(UpdateSelectorPrevButtonIndex, UpdateSelectorNextButtonIndex); + else UpdateSelectorLocation(UpdateSelectorNextButtonIndex); + bShouldTickUpdateSelector = false; + } + else + { + UpdateSelectorWaitForTick++; + } + } - WaitForTick++; + if (bMovingSelector) + { + HandleSelectorMovement(DeltaTime); + } + } } } @@ -1263,20 +1276,19 @@ void UUINavWidget::ReplaceButtonInNavigationGrid(UUINavButton * ButtonToReplace, void UUINavWidget::UpdateCurrentButton(UUINavButton * NewCurrentButton) { - ButtonIndex = NewCurrentButton->ButtonIndex; if (IsSelectorValid()) { - if (MoveCurve != nullptr) BeginSelectorMovement(NewCurrentButton->ButtonIndex); - else UpdateSelectorLocation(NewCurrentButton->ButtonIndex); + UpdateSelectorWaitForTick = 0; + UpdateSelectorPrevButtonIndex = ButtonIndex; + UpdateSelectorNextButtonIndex = NewCurrentButton->ButtonIndex; + bShouldTickUpdateSelector = true; } + ButtonIndex = NewCurrentButton->ButtonIndex; + for (UScrollBox* ScrollBox : ScrollBoxes) { - if (NewCurrentButton->IsChildOf(ScrollBox)) - { ScrollBox->ScrollWidgetIntoView(NewCurrentButton, bAnimateScrollBoxes); - break; - } } } @@ -2410,8 +2422,10 @@ void UUINavWidget::DispatchNavigation(const int Index) if (Index > -1 && IsSelectorValid()) { - if (MoveCurve != nullptr) BeginSelectorMovement(Index); - else UpdateSelectorLocation(Index); + UpdateSelectorWaitForTick = 0; + UpdateSelectorPrevButtonIndex = ButtonIndex; + UpdateSelectorNextButtonIndex = Index; + bShouldTickUpdateSelector = true; } if (bUseTextColor) UpdateTextColor(Index); @@ -2424,12 +2438,12 @@ void UUINavWidget::DispatchNavigation(const int Index) if (UINavAnimations.Num() > 0) ExecuteAnimations(ButtonIndex, Index); } -void UUINavWidget::BeginSelectorMovement(const int Index) +void UUINavWidget::BeginSelectorMovement(const int PrevButtonIndex, const int NextButtonIndex) { if (MoveCurve == nullptr) return; - SelectorOrigin = bMovingSelector ? TheSelector->RenderTransform.Translation : GetButtonLocation(ButtonIndex); - SelectorDestination = GetButtonLocation(Index); + SelectorOrigin = bMovingSelector ? TheSelector->RenderTransform.Translation : GetButtonLocation(PrevButtonIndex); + SelectorDestination = GetButtonLocation(NextButtonIndex); Distance = SelectorDestination - SelectorOrigin; float MinTime, MaxTime; diff --git a/Source/UINavigation/Public/UINavButton.h b/Source/UINavigation/Public/UINavButton.h index 378d0917..ad706a60 100644 --- a/Source/UINavigation/Public/UINavButton.h +++ b/Source/UINavigation/Public/UINavButton.h @@ -59,7 +59,7 @@ class UINAVIGATION_API UUINavButton : public UButton UPROPERTY(BlueprintReadOnly, Category = UINavButton) int IndexInGrid = - 1; - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = UINavButton) + UPROPERTY(BlueprintReadOnly, Category = UINavButton) UUINavComponent* NavComp = nullptr; EButtonStyle CurrentStyle = EButtonStyle::Normal; diff --git a/Source/UINavigation/Public/UINavHorizontalComponent.h b/Source/UINavigation/Public/UINavHorizontalComponent.h index dee35d78..7fe3e46c 100644 --- a/Source/UINavigation/Public/UINavHorizontalComponent.h +++ b/Source/UINavigation/Public/UINavHorizontalComponent.h @@ -35,7 +35,7 @@ class UINAVIGATION_API UUINavHorizontalComponent : public UUINavComponent virtual void UpdateTextToIndex(int NewIndex); //Changes the text displayed in the NavText element UFUNCTION(BlueprintCallable, Category = UINavComponentBox) - void ChangeText(FText NewText); + void ChangeText(const FText NewText); UFUNCTION(BlueprintCallable, Category = UINavComponentBox) virtual FORCEINLINE int GetMaxOptionIndex() const { return 0; } diff --git a/Source/UINavigation/Public/UINavOptionBox.h b/Source/UINavigation/Public/UINavOptionBox.h index 3c40494f..bd924e9c 100644 --- a/Source/UINavigation/Public/UINavOptionBox.h +++ b/Source/UINavigation/Public/UINavOptionBox.h @@ -33,6 +33,6 @@ class UINAVIGATION_API UUINavOptionBox : public UUINavComponentBox TArray StringOptions; UFUNCTION(BlueprintCallable, BlueprintPure, Category = UINavOptionBox) - FORCEINLINE FText GetCurrentString() const { return StringOptions[OptionIndex]; } + FORCEINLINE FText GetCurrentString() const { return StringOptions.IsValidIndex(OptionIndex) ? StringOptions[OptionIndex] : FText(); } }; diff --git a/Source/UINavigation/Public/UINavPCComponent.h b/Source/UINavigation/Public/UINavPCComponent.h index 7e5bf201..fe104346 100644 --- a/Source/UINavigation/Public/UINavPCComponent.h +++ b/Source/UINavigation/Public/UINavPCComponent.h @@ -124,6 +124,8 @@ class UINAVIGATION_API UUINavPCComponent : public UActorComponent void CallCustomInput(const FName ActionName, const bool bPressed); + UFUNCTION() + void OnControllerConnectionChanged(bool bConnected, int32 UserId, int32 UserIndex); public: diff --git a/Source/UINavigation/Public/UINavPCReceiver.h b/Source/UINavigation/Public/UINavPCReceiver.h index 45bcb9eb..a42739ec 100644 --- a/Source/UINavigation/Public/UINavPCReceiver.h +++ b/Source/UINavigation/Public/UINavPCReceiver.h @@ -41,6 +41,13 @@ class UINAVIGATION_API IUINavPCReceiver void OnInputChanged(EInputType From, EInputType To); virtual void OnInputChanged_Implementation(EInputType From, EInputType To); + /** + * Called when a controller is connected and disconnected + */ + UFUNCTION(BlueprintNativeEvent, Category = UINavController) + void OnControllerConnectionChanged(bool bConnected, int32 UserId, int32 UserIndex); + virtual void OnControllerConnectionChanged_Implementation(bool bConnected, int32 UserId, int32 UserIndex); + /** * Called when the active widget changes * diff --git a/Source/UINavigation/Public/UINavSlider.h b/Source/UINavigation/Public/UINavSlider.h index 43c49409..8dedc2a7 100644 --- a/Source/UINavigation/Public/UINavSlider.h +++ b/Source/UINavigation/Public/UINavSlider.h @@ -1,4 +1,4 @@ -// Copyright (C) 2019 Gonçalo Marques - All Rights Reserved +// Copyright (C) 2019 Gonçalo Marques - All Rights Reserved #pragma once @@ -21,8 +21,6 @@ class UINAVIGATION_API UUINavSlider : public UUINavHorizontalComponent UPROPERTY(BlueprintReadWrite, Category = UINavSlider, meta = (BindWidget, OptionalWidget = true)) class USpinBox* NavSpinBox; - bool bIgnoreSpinBoxCommit = false; - UFUNCTION() void HandleOnSliderValueChanged(const float InValue); UFUNCTION() diff --git a/Source/UINavigation/Public/UINavWidget.h b/Source/UINavigation/Public/UINavWidget.h index c7837f1f..bd46e96b 100644 --- a/Source/UINavigation/Public/UINavWidget.h +++ b/Source/UINavigation/Public/UINavWidget.h @@ -31,19 +31,24 @@ class UINAVIGATION_API UUINavWidget : public UUserWidget bool bCompletedSetup = false; bool bSetupStarted = false; - bool bShouldTick = true; bool bMovingSelector = false; bool bIgnoreMouseEvent = false; bool bReturning = false; + + bool bShouldTickUINavSetup = false; + int UINavSetupWaitForTick=0; + + bool bShouldTickUpdateSelector = false; + int UpdateSelectorPrevButtonIndex; + int UpdateSelectorNextButtonIndex; + int UpdateSelectorWaitForTick=0; + bool bReturningToParent = false; bool bAutoAppended = false; bool bDestroying = false; bool bHasNavigation = false; - //Used to track when the selector's position should be updated - int WaitForTick; - //The index of the button that will be navigated to when movement is allowed int HaltedIndex = -1; @@ -125,7 +130,7 @@ class UINAVIGATION_API UUINavWidget : public UUserWidget */ FVector2D GetButtonLocation(const int Index); - void BeginSelectorMovement(const int Index); + void BeginSelectorMovement(const int PrevButtonIndex, const int NextButtonIndex); void HandleSelectorMovement(const float DeltaTime); public: @@ -229,18 +234,18 @@ class UINAVIGATION_API UUINavWidget : public UUserWidget bool bMaintainNavigationForParent = false; /*If set to true, the gamepad's left thumbstick will be used to move the mouse */ - UPROPERTY(EditDefaultsOnly, Category = UINavWidget) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = UINavWidget) bool bUseLeftThumbstickAsMouse = false; //The index of the button to be first navigated to (when the widget is added to viewport) - UPROPERTY(EditDefaultsOnly, Category = UINavWidget) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = UINavWidget) int FirstButtonIndex = 0; //If set to true, this widget will be removed if it has no ParentWidget and is returned from - UPROPERTY(EditDefaultsOnly, Category = UINavWidget) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = UINavWidget) bool bAllowRemoveIfRoot = true; - UPROPERTY(EditDefaultsOnly, Category = UINavWidget) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = UINavWidget) bool bAnimateScrollBoxes = false; //UINavAnimations Playback Speed @@ -251,15 +256,15 @@ class UINAVIGATION_API UUINavWidget : public UUserWidget UPROPERTY(EditDefaultsOnly, Category = UINavWidget) bool bUseFullscreenWhenSplitscreen = false; - UPROPERTY(EditDefaultsOnly, Category = "UINavigation Selector", meta = (EditCondition = "bUseMovementCurve")) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "UINavigation Selector", meta = (EditCondition = "bUseMovementCurve")) UCurveFloat* MoveCurve; //The position the selector will be in relative to the button - UPROPERTY(EditDefaultsOnly, Category = "UINavigation Selector") + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "UINavigation Selector") ESelectorPosition SelectorPositioning = ESelectorPosition::Position_Center; //The offset to apply when positioning the selector on a button - UPROPERTY(EditDefaultsOnly, Category = "UINavigation Selector") + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "UINavigation Selector") FVector2D SelectorOffset; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "UINavigation Text", meta = (EditCondition = "bUseTextColor")) diff --git a/UINavigation.uplugin b/UINavigation.uplugin index 6a072a08..158ecb1a 100644 --- a/UINavigation.uplugin +++ b/UINavigation.uplugin @@ -10,7 +10,7 @@ "DocsURL": "", "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/4601ff4d12fc4ed1a7418e1585374a48", "SupportURL": "", - "EngineVersion": "4.26.0", + "EngineVersion": "5.0.0", "CanContainContent": true, "Installed": true, "Modules": [