Convert buttons in Main Menu to Custom Buttons

This commit is contained in:
baz 2025-08-25 23:25:58 +01:00
parent 784a373c33
commit a8d6e76fbf
11 changed files with 133 additions and 88 deletions

BIN
Content/Widgets/BP_CustomButton.uasset (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,16 @@
// Louis Hobbs | 2024-2025
#include "DetectGamepad.h"
bool UDetectGamepad::IsControllerConnected()
{
TSharedPtr<class GenericApplication> Game = FSlateApplication::Get().GetPlatformApplication();
if (Game.Get() != nullptr && Game->IsGamepadAttached())
{
return true;
}
return false;
}

View File

@ -13,4 +13,9 @@ UCLASS()
class VAMPIRES_API UDetectGamepad : public UBlueprintFunctionLibrary class VAMPIRES_API UDetectGamepad : public UBlueprintFunctionLibrary
{ {
GENERATED_BODY() GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "DetectGamepad")
static bool IsControllerConnected();
}; };

View File

@ -5,16 +5,19 @@
#include "Components/Button.h" #include "Components/Button.h"
#include "Components/TextBlock.h" #include "Components/TextBlock.h"
#include "Kismet/GameplayStatics.h"
void UCustomButton::NativeConstruct() void UCustomButton::NativeConstruct()
{ {
Super::NativeConstruct(); Super::NativeConstruct();
SetIsFocusable(true);
ButtonBody->OnClicked.AddUniqueDynamic(this, &UCustomButton::OnButtonClicked); ButtonBody->OnClicked.AddUniqueDynamic(this, &UCustomButton::OnButtonClicked);
ButtonBody->OnPressed.AddUniqueDynamic(this, &UCustomButton::OnButtonPressed); ButtonBody->OnPressed.AddUniqueDynamic(this, &UCustomButton::OnButtonPressed);
ButtonBody->OnReleased.AddUniqueDynamic(this, &UCustomButton::OnButtonReleased); ButtonBody->OnReleased.AddUniqueDynamic(this, &UCustomButton::OnButtonReleased);
ButtonBody->OnHovered.AddUniqueDynamic(this, &UCustomButton::OnButtonHovered); ButtonBody->OnHovered.AddUniqueDynamic(this, &UCustomButton::OnButtonHovered);
ButtonBody->OnUnhovered.AddUniqueDynamic(this, &UCustomButton::OnButtonHovered); ButtonBody->OnUnhovered.AddUniqueDynamic(this, &UCustomButton::OnButtonUnhovered);
TextBlock->SetText(ButtonText); TextBlock->SetText(ButtonText);
} }
@ -34,19 +37,53 @@ TObjectPtr<UTextBlock> UCustomButton::GetTextBlock()
void UCustomButton::OnButtonClicked() void UCustomButton::OnButtonClicked()
{ {
OnClicked.Broadcast(); OnClicked.Broadcast();
if (ButtonClickedSound)
{
UGameplayStatics::PlaySound2D(GetWorld(), ButtonClickedSound);
}
} }
void UCustomButton::OnButtonPressed() void UCustomButton::OnButtonPressed()
{ {
OnPressed.Broadcast(); OnPressed.Broadcast();
if (ButtonPressedSound)
{
UGameplayStatics::PlaySound2D(GetWorld(), ButtonPressedSound);
}
} }
void UCustomButton::OnButtonReleased() void UCustomButton::OnButtonReleased()
{ {
OnReleased.Broadcast(); OnReleased.Broadcast();
if (ButtonReleasedSound)
{
UGameplayStatics::PlaySound2D(GetWorld(), ButtonReleasedSound);
}
} }
void UCustomButton::OnButtonHovered() void UCustomButton::OnButtonHovered()
{ {
OnHovered.Broadcast(); OnHovered.Broadcast();
if (ButtonHoveredSound)
{
UGameplayStatics::PlaySound2D(GetWorld(), ButtonHoveredSound);
}
TextBlock->SetColorAndOpacity(FSlateColor(ButtonHoveredTextColor));
}
void UCustomButton::OnButtonUnhovered()
{
OnUnhovered.Broadcast();
if (ButtonUnhoveredSound)
{
UGameplayStatics::PlaySound2D(GetWorld(), ButtonUnhoveredSound);
}
TextBlock->SetColorAndOpacity(FSlateColor(ButtonUnhoveredTextColor));
} }

View File

@ -35,9 +35,33 @@ public:
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
FOnButtonHoverEventCustom OnHovered; FOnButtonHoverEventCustom OnHovered;
UPROPERTY(BlueprintAssignable)
FOnButtonHoverEventCustom OnUnhovered;
UPROPERTY(EditAnywhere, BlueprintReadOnly) UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Button Settings | Text")
FText ButtonText = FText::FromString("Default"); FText ButtonText = FText::FromString("Default");
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Color")
FLinearColor ButtonHoveredTextColor = {0, 1, 0, 1};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Color")
FLinearColor ButtonUnhoveredTextColor = {1, 1, 1, 1};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Sound")
TObjectPtr<USoundBase> ButtonClickedSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Sound")
TObjectPtr<USoundBase> ButtonPressedSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Sound")
TObjectPtr<USoundBase> ButtonReleasedSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Sound")
TObjectPtr<USoundBase> ButtonHoveredSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Button Settings | Sound")
TObjectPtr<USoundBase> ButtonUnhoveredSound;
private: private:
UPROPERTY(meta = (BindWidget)) UPROPERTY(meta = (BindWidget))
@ -68,4 +92,7 @@ private:
UFUNCTION() UFUNCTION()
void OnButtonHovered(); void OnButtonHovered();
UFUNCTION()
void OnButtonUnhovered();
}; };

View File

@ -3,6 +3,7 @@
#include "MainMenuWidget.h" #include "MainMenuWidget.h"
#include "CustomButton.h"
#include "SelectWeaponWidget.h" #include "SelectWeaponWidget.h"
#include "Blueprint/WidgetBlueprintLibrary.h" #include "Blueprint/WidgetBlueprintLibrary.h"
#include "Components/Button.h" #include "Components/Button.h"
@ -15,37 +16,36 @@ void UMainMenuWidget::NativeConstruct()
if (NewGameButton) if (NewGameButton)
{ {
NewGameButton->OnClicked.AddUniqueDynamic(this, &UMainMenuWidget::NewGameButtonOnClicked); NewGameButton->OnClicked.AddUniqueDynamic(this, &UMainMenuWidget::NewGameButtonOnClicked);
NewGameButton->OnHovered.AddUniqueDynamic(this, &UMainMenuWidget::NewGameButtonOnHovered);
NewGameButton->OnUnhovered.AddUniqueDynamic(this, &UMainMenuWidget::NewGameButtonOnUnhovered);
} }
if (OptionsButton) if (OptionsButton)
{ {
OptionsButton->OnClicked.AddUniqueDynamic(this, &UMainMenuWidget::OptionsButtonOnClicked); OptionsButton->OnClicked.AddUniqueDynamic(this, &UMainMenuWidget::OptionsButtonOnClicked);
OptionsButton->OnHovered.AddUniqueDynamic(this, &UMainMenuWidget::OptionsButtonOnHovered);
OptionsButton->OnUnhovered.AddUniqueDynamic(this, &UMainMenuWidget::OptionsButtonOnUnhovered);
} }
if (QuitButton) if (QuitButton)
{ {
QuitButton->OnClicked.AddUniqueDynamic(this, &UMainMenuWidget::QuitButtonOnClicked); QuitButton->OnClicked.AddUniqueDynamic(this, &UMainMenuWidget::QuitButtonOnClicked);
QuitButton->OnHovered.AddUniqueDynamic(this, &UMainMenuWidget::QuitButtonOnHovered);
QuitButton->OnUnhovered.AddUniqueDynamic(this, &UMainMenuWidget::QuitButtonOnUnhovered);
} }
QuitButton->SetIsEnabled(false); QuitButton->SetIsEnabled(false);
if (APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0)) if (APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{ {
UWidgetBlueprintLibrary::SetInputMode_UIOnlyEx(PlayerController, this, EMouseLockMode::LockAlways); UWidgetBlueprintLibrary::SetInputMode_UIOnlyEx(PlayerController, NewGameButton, EMouseLockMode::LockAlways);
PlayerController->bShowMouseCursor = true; PlayerController->bShowMouseCursor = true;
} }
} }
FReply UMainMenuWidget::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
NewGameButton->SetKeyboardFocus();
return Super::NativeOnMouseButtonUp(InGeometry, InMouseEvent);
}
void UMainMenuWidget::NewGameButtonOnClicked() void UMainMenuWidget::NewGameButtonOnClicked()
{ {
PlayClickedSound();
if (NewGameMenuWidget) if (NewGameMenuWidget)
{ {
RemoveFromParent(); RemoveFromParent();
@ -62,8 +62,6 @@ void UMainMenuWidget::NewGameButtonOnClicked()
void UMainMenuWidget::OptionsButtonOnClicked() void UMainMenuWidget::OptionsButtonOnClicked()
{ {
PlayClickedSound();
if (OptionsMenuWidget) if (OptionsMenuWidget)
{ {
RemoveFromParent(); RemoveFromParent();
@ -80,46 +78,8 @@ void UMainMenuWidget::OptionsButtonOnClicked()
void UMainMenuWidget::QuitButtonOnClicked() void UMainMenuWidget::QuitButtonOnClicked()
{ {
PlayClickedSound();
// TODO: Add platform specific Exit requests // TODO: Add platform specific Exit requests
// This is not a bit deal for the moment as we are only building for windows // This is not a bit deal for the moment as we are only building for windows
// For some reason the generic version does not work the same as FWindowsPlatformMisc // For some reason the generic version does not work the same as FWindowsPlatformMisc
FWindowsPlatformMisc::RequestExit(false); FWindowsPlatformMisc::RequestExit(false);
} }
void UMainMenuWidget::NewGameButtonOnHovered()
{
PlayHoveredSound();
SetTextBlockHovered(NewGameTextBlock);
}
void UMainMenuWidget::NewGameButtonOnUnhovered()
{
PlayUnhoveredSound();
SetTextBlockUnhovered(NewGameTextBlock);
}
void UMainMenuWidget::OptionsButtonOnHovered()
{
PlayHoveredSound();
SetTextBlockHovered(OptionsTextBlock);
}
void UMainMenuWidget::OptionsButtonOnUnhovered()
{
PlayUnhoveredSound();
SetTextBlockUnhovered(OptionsTextBlock);
}
void UMainMenuWidget::QuitButtonOnHovered()
{
PlayHoveredSound();
SetTextBlockHovered(QuitTextBlock);
}
void UMainMenuWidget::QuitButtonOnUnhovered()
{
PlayUnhoveredSound();
SetTextBlockUnhovered(QuitTextBlock);
}

View File

@ -6,32 +6,24 @@
#include "VampireInteractiveWidget.h" #include "VampireInteractiveWidget.h"
#include "MainMenuWidget.generated.h" #include "MainMenuWidget.generated.h"
class UCustomButton;
class UButton; class UButton;
/** /**
* *
*/ */
UCLASS() UCLASS()
class VAMPIRES_API UMainMenuWidget : public UVampireInteractiveWidget class VAMPIRES_API UMainMenuWidget : public UUserWidget
{ {
GENERATED_BODY() GENERATED_BODY()
UPROPERTY(meta = (BindWidget)) UPROPERTY(meta = (BindWidget))
TObjectPtr<UButton> NewGameButton; TObjectPtr<UCustomButton> NewGameButton;
UPROPERTY(meta = (BindWidget)) UPROPERTY(meta = (BindWidget))
TObjectPtr<UTextBlock> NewGameTextBlock; TObjectPtr<UCustomButton> OptionsButton;
UPROPERTY(meta = (BindWidget)) UPROPERTY(meta = (BindWidget))
TObjectPtr<UButton> OptionsButton; TObjectPtr<UCustomButton> QuitButton;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UTextBlock> OptionsTextBlock;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UButton> QuitButton;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UTextBlock> QuitTextBlock;
UPROPERTY(EditDefaultsOnly, Category = "Widget Settings | New Game") UPROPERTY(EditDefaultsOnly, Category = "Widget Settings | New Game")
TSubclassOf<UUserWidget> NewGameMenuWidget; TSubclassOf<UUserWidget> NewGameMenuWidget;
@ -45,6 +37,9 @@ class VAMPIRES_API UMainMenuWidget : public UVampireInteractiveWidget
public: public:
virtual void NativeConstruct() override; virtual void NativeConstruct() override;
protected:
virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
private: private:
UFUNCTION() UFUNCTION()
void NewGameButtonOnClicked(); void NewGameButtonOnClicked();
@ -54,22 +49,4 @@ private:
UFUNCTION() UFUNCTION()
void QuitButtonOnClicked(); void QuitButtonOnClicked();
UFUNCTION()
void NewGameButtonOnHovered();
UFUNCTION()
void NewGameButtonOnUnhovered();
UFUNCTION()
void OptionsButtonOnHovered();
UFUNCTION()
void OptionsButtonOnUnhovered();
UFUNCTION()
void QuitButtonOnHovered();
UFUNCTION()
void QuitButtonOnUnhovered();
}; };

View File

@ -6,6 +6,19 @@
#include "Components/TextBlock.h" #include "Components/TextBlock.h"
#include "GameFramework/GameUserSettings.h" #include "GameFramework/GameUserSettings.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "vampires/DetectGamepad.h"
void UVampireInteractiveWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
GamepadConnected = UDetectGamepad::IsControllerConnected();
}
FReply UVampireInteractiveWidget::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
return Super::NativeOnMouseButtonUp(InGeometry, InMouseEvent);
}
void UVampireInteractiveWidget::SetReturnScreen(UUserWidget* UserWidget) void UVampireInteractiveWidget::SetReturnScreen(UUserWidget* UserWidget)
{ {

View File

@ -6,6 +6,7 @@
#include "Blueprint/UserWidget.h" #include "Blueprint/UserWidget.h"
#include "VampireInteractiveWidget.generated.h" #include "VampireInteractiveWidget.generated.h"
class UButton;
class UTextBlock; class UTextBlock;
/** /**
* *
@ -31,10 +32,19 @@ protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Widget Settings | Sound") UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Widget Settings | Sound")
TObjectPtr<USoundBase> ButtonClickedSound; TObjectPtr<USoundBase> ButtonClickedSound;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Widget Settings")
TArray<TObjectPtr<UButton>> InteractableButtons;
protected: protected:
UPROPERTY() UPROPERTY()
TObjectPtr<UUserWidget> PreviousScreen; TObjectPtr<UUserWidget> PreviousScreen;
bool GamepadConnected = false;
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
public: public:
UFUNCTION() UFUNCTION()
void SetReturnScreen(UUserWidget* UserWidget); void SetReturnScreen(UUserWidget* UserWidget);

View File

@ -10,7 +10,7 @@ public class vampires : ModuleRules
PublicDependencyModuleNames.AddRange(new[] PublicDependencyModuleNames.AddRange(new[]
{ {
"Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "Paper2D", "Niagara", "SlateCore", "RHI" "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "Paper2D", "Niagara", "SlateCore", "RHI", "Slate"
}); });
PrivateDependencyModuleNames.AddRange(new string[] { }); PrivateDependencyModuleNames.AddRange(new string[] { });