mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 17:45:23 +00:00
Working on a focusable check box for gamepad support
This commit is contained in:
parent
b66805057a
commit
413491fd05
@ -0,0 +1,78 @@
|
||||
#include "StevesUI/FocusableCheckBox.h"
|
||||
#include "StevesUI/SFocusableCheckBox.h"
|
||||
|
||||
|
||||
TSharedRef<SWidget> UFocusableCheckBox::RebuildWidget()
|
||||
{
|
||||
MyCheckbox = SNew(SFocusableCheckBox)
|
||||
.OnCheckStateChanged( BIND_UOBJECT_DELEGATE(FOnCheckStateChanged, SlateOnCheckStateChangedCallback) )
|
||||
.Style(&WidgetStyle)
|
||||
.HAlign( HorizontalAlignment )
|
||||
.ClickMethod(ClickMethod)
|
||||
.TouchMethod(TouchMethod)
|
||||
.PressMethod(PressMethod)
|
||||
.IsFocusable(IsFocusable)
|
||||
// Our new events
|
||||
.OnHovered(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleHovered))
|
||||
.OnUnhovered(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleUnhovered))
|
||||
.OnFocusReceived(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleFocusReceived))
|
||||
.OnFocusLost(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleFocusLost))
|
||||
;
|
||||
|
||||
if ( GetChildrenCount() > 0 )
|
||||
{
|
||||
MyCheckbox->SetContent(GetContentSlot()->Content ? GetContentSlot()->Content->TakeWidget() : SNullWidget::NullWidget);
|
||||
}
|
||||
|
||||
// Copy Widget style but make normal same as hovered
|
||||
FocussedStyle = WidgetStyle;
|
||||
FocussedStyle.UncheckedImage = FocussedStyle.UncheckedHoveredImage;
|
||||
FocussedStyle.CheckedImage = FocussedStyle.CheckedHoveredImage;
|
||||
FocussedStyle.UndeterminedImage = FocussedStyle.UndeterminedHoveredImage;
|
||||
|
||||
return MyCheckbox.ToSharedRef();
|
||||
|
||||
}
|
||||
|
||||
void UFocusableCheckBox::SlateHandleFocusReceived()
|
||||
{
|
||||
ApplyFocusStyle();
|
||||
OnFocusReceived.Broadcast();
|
||||
}
|
||||
|
||||
void UFocusableCheckBox::SlateHandleFocusLost()
|
||||
{
|
||||
UndoFocusStyle();
|
||||
OnFocusLost.Broadcast();
|
||||
}
|
||||
|
||||
|
||||
void UFocusableCheckBox::ApplyFocusStyle()
|
||||
{
|
||||
if (MyCheckbox.IsValid() && bUseHoverStyleWhenFocussed)
|
||||
{
|
||||
MyCheckbox->SetStyle(&FocussedStyle);
|
||||
}
|
||||
}
|
||||
|
||||
void UFocusableCheckBox::UndoFocusStyle()
|
||||
{
|
||||
if (MyCheckbox.IsValid())
|
||||
{
|
||||
MyCheckbox->SetStyle(&WidgetStyle);
|
||||
}
|
||||
}
|
||||
|
||||
void UFocusableCheckBox::SlateHandleHovered()
|
||||
{
|
||||
if (bTakeFocusOnHover)
|
||||
{
|
||||
SetFocus();
|
||||
}
|
||||
OnHovered.Broadcast();
|
||||
}
|
||||
|
||||
void UFocusableCheckBox::SlateHandleUnhovered()
|
||||
{
|
||||
OnUnhovered.Broadcast();
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
#include "SFocusableCheckBox.h"
|
||||
|
||||
void SFocusableCheckBox::Construct(const FArguments& InArgs)
|
||||
{
|
||||
// Call superclass, have to re-construct the args because they're not compatible
|
||||
SCheckBox::Construct(SCheckBox::FArguments()
|
||||
.Padding(InArgs._Padding)
|
||||
.Style(InArgs._Style)
|
||||
.Type(InArgs._Type)
|
||||
.CheckedImage(InArgs._CheckedImage)
|
||||
.ClickMethod(InArgs._ClickMethod)
|
||||
.ForegroundColor(InArgs._ForegroundColor)
|
||||
.HAlign(InArgs._HAlign)
|
||||
.IsChecked(InArgs._IsChecked)
|
||||
.IsFocusable(InArgs._IsFocusable)
|
||||
.PressMethod(InArgs._PressMethod)
|
||||
.TouchMethod(InArgs._TouchMethod)
|
||||
.UncheckedImage(InArgs._UncheckedImage)
|
||||
.UndeterminedImage(InArgs._UndeterminedImage)
|
||||
.CheckedImage(InArgs._CheckedImage)
|
||||
.UncheckedHoveredImage(InArgs._UncheckedHoveredImage)
|
||||
.UndeterminedHoveredImage(InArgs._UndeterminedHoveredImage)
|
||||
.CheckedHoveredImage(InArgs._CheckedHoveredImage)
|
||||
.UncheckedPressedImage(InArgs._UncheckedPressedImage)
|
||||
.UndeterminedPressedImage(InArgs._UndeterminedPressedImage)
|
||||
.CheckedPressedImage(InArgs._CheckedPressedImage)
|
||||
.CheckedSoundOverride(InArgs._CheckedSoundOverride)
|
||||
.UncheckedSoundOverride(InArgs._UncheckedSoundOverride)
|
||||
.HoveredSoundOverride(InArgs._HoveredSoundOverride)
|
||||
.BorderBackgroundColor(InArgs._BorderBackgroundColor)
|
||||
.OnCheckStateChanged(InArgs._OnCheckStateChanged)
|
||||
.IsEnabled(InArgs._IsEnabled)
|
||||
.Clipping(InArgs._Clipping)
|
||||
.Cursor(InArgs._Cursor)
|
||||
.Tag(InArgs._Tag)
|
||||
.Visibility(InArgs._Visibility)
|
||||
.AccessibleParams(InArgs._AccessibleParams)
|
||||
.AccessibleText(InArgs._AccessibleText)
|
||||
.ForceVolatile(InArgs._ForceVolatile)
|
||||
.IsEnabled(InArgs._IsEnabled)
|
||||
.RenderOpacity(InArgs._RenderOpacity)
|
||||
.RenderTransform(InArgs._RenderTransform)
|
||||
.RenderTransformPivot(InArgs._RenderTransformPivot)
|
||||
.ToolTip(InArgs._ToolTip)
|
||||
.ToolTipText(InArgs._ToolTipText)
|
||||
);
|
||||
|
||||
OnHoveredDelegate = InArgs._OnHovered;
|
||||
OnUnhoveredDelegate = InArgs._OnUnhovered;
|
||||
OnFocusReceivedDelegate = InArgs._OnFocusReceived;
|
||||
OnFocusLostDelegate = InArgs._OnFocusLost;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SFocusableCheckBox::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
SCheckBox::OnMouseEnter(MyGeometry, MouseEvent);
|
||||
|
||||
// SCheckbox doesn't have hovered / unhovered events so we need to add them
|
||||
}
|
||||
|
||||
void SFocusableCheckBox::OnMouseLeave(const FPointerEvent& MouseEvent)
|
||||
{
|
||||
SCheckBox::OnMouseLeave(MouseEvent);
|
||||
}
|
||||
|
||||
FReply SFocusableCheckBox::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent)
|
||||
{
|
||||
auto Ret = SCheckBox::OnFocusReceived(MyGeometry, InFocusEvent);
|
||||
|
||||
OnFocusReceivedDelegate.ExecuteIfBound();
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void SFocusableCheckBox::OnFocusLost(const FFocusEvent& InFocusEvent)
|
||||
{
|
||||
SCheckBox::OnFocusLost(InFocusEvent);
|
||||
|
||||
OnFocusLostDelegate.ExecuteIfBound();
|
||||
}
|
||||
|
||||
void SFocusableCheckBox::SetOnFocusReceived(FSimpleDelegate InOnFocusReceived)
|
||||
{
|
||||
OnFocusReceivedDelegate = InOnFocusReceived;
|
||||
}
|
||||
|
||||
void SFocusableCheckBox::SetOnFocusLost(FSimpleDelegate InOnFocusLost)
|
||||
{
|
||||
OnFocusLostDelegate = InOnFocusLost;
|
||||
}
|
146
Source/StevesUEHelpers/Private/StevesUI/SFocusableCheckBox.h
Normal file
146
Source/StevesUEHelpers/Private/StevesUI/SFocusableCheckBox.h
Normal file
@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Widgets/Input/SCheckBox.h"
|
||||
|
||||
|
||||
class SFocusableCheckBox : public SCheckBox
|
||||
{
|
||||
public:
|
||||
|
||||
// Seems in slate we have to duplicate all the args from superclass
|
||||
SLATE_BEGIN_ARGS( SFocusableCheckBox )
|
||||
: _Content()
|
||||
, _Style( &FCoreStyle::Get().GetWidgetStyle< FCheckBoxStyle >("Checkbox") )
|
||||
, _Type()
|
||||
, _OnCheckStateChanged()
|
||||
, _IsChecked( ECheckBoxState::Unchecked )
|
||||
, _HAlign( HAlign_Fill )
|
||||
, _CheckBoxContentUsesAutoWidth(true)
|
||||
, _Padding()
|
||||
, _ClickMethod( EButtonClickMethod::DownAndUp )
|
||||
, _TouchMethod(EButtonTouchMethod::DownAndUp)
|
||||
, _PressMethod(EButtonPressMethod::DownAndUp)
|
||||
, _ForegroundColor()
|
||||
, _BorderBackgroundColor ()
|
||||
, _IsFocusable( true )
|
||||
, _UncheckedImage( nullptr )
|
||||
, _UncheckedHoveredImage( nullptr )
|
||||
, _UncheckedPressedImage( nullptr )
|
||||
, _CheckedImage( nullptr )
|
||||
, _CheckedHoveredImage( nullptr )
|
||||
, _CheckedPressedImage( nullptr )
|
||||
, _UndeterminedImage( nullptr )
|
||||
, _UndeterminedHoveredImage( nullptr )
|
||||
, _UndeterminedPressedImage( nullptr )
|
||||
{
|
||||
}
|
||||
/** Content to be placed next to the check box, or for a toggle button, the content to be placed inside the button */
|
||||
SLATE_DEFAULT_SLOT( FArguments, Content )
|
||||
|
||||
/** The style structure for this checkbox' visual style */
|
||||
SLATE_STYLE_ARGUMENT( FCheckBoxStyle, Style )
|
||||
|
||||
/** Type of check box (set by the Style arg but the Style can be overridden with this) */
|
||||
SLATE_ARGUMENT( TOptional<ESlateCheckBoxType::Type>, Type )
|
||||
|
||||
/** Called when the checked state has changed */
|
||||
SLATE_EVENT( FOnCheckStateChanged, OnCheckStateChanged )
|
||||
|
||||
/** Whether the check box is currently in a checked state */
|
||||
SLATE_ATTRIBUTE( ECheckBoxState, IsChecked )
|
||||
|
||||
/** How the content of the toggle button should align within the given space*/
|
||||
SLATE_ARGUMENT( EHorizontalAlignment, HAlign )
|
||||
|
||||
/** Whether or not the content portion of the checkbox should layout using auto-width. When true the content will always be arranged at its desired size as opposed to resizing to the available space. */
|
||||
SLATE_ARGUMENT(bool, CheckBoxContentUsesAutoWidth)
|
||||
|
||||
/** Spacing between the check box image and its content (set by the Style arg but the Style can be overridden with this) */
|
||||
SLATE_ATTRIBUTE( FMargin, Padding )
|
||||
|
||||
/** Sets the rules to use for determining whether the button was clicked. This is an advanced setting and generally should be left as the default. */
|
||||
SLATE_ARGUMENT( EButtonClickMethod::Type, ClickMethod )
|
||||
|
||||
/** How should the button be clicked with touch events? */
|
||||
SLATE_ARGUMENT(EButtonTouchMethod::Type, TouchMethod)
|
||||
|
||||
/** How should the button be clicked with keyboard/controller button events? */
|
||||
SLATE_ARGUMENT(EButtonPressMethod::Type, PressMethod)
|
||||
|
||||
/** Foreground color for the checkbox's content and parts (set by the Style arg but the Style can be overridden with this) */
|
||||
SLATE_ATTRIBUTE( FSlateColor, ForegroundColor )
|
||||
|
||||
/** The color of the background border (set by the Style arg but the Style can be overridden with this) */
|
||||
SLATE_ATTRIBUTE( FSlateColor, BorderBackgroundColor )
|
||||
|
||||
SLATE_ARGUMENT( bool, IsFocusable )
|
||||
|
||||
SLATE_EVENT( FOnGetContent, OnGetMenuContent )
|
||||
|
||||
/** The sound to play when the check box is checked */
|
||||
SLATE_ARGUMENT( TOptional<FSlateSound>, CheckedSoundOverride )
|
||||
|
||||
/** The sound to play when the check box is unchecked */
|
||||
SLATE_ARGUMENT( TOptional<FSlateSound>, UncheckedSoundOverride )
|
||||
|
||||
/** The sound to play when the check box is hovered */
|
||||
SLATE_ARGUMENT( TOptional<FSlateSound>, HoveredSoundOverride )
|
||||
|
||||
/** The unchecked image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, UncheckedImage)
|
||||
|
||||
/** The unchecked hovered image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, UncheckedHoveredImage)
|
||||
|
||||
/** The unchecked pressed image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, UncheckedPressedImage)
|
||||
|
||||
/** The checked image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, CheckedImage)
|
||||
|
||||
/** The checked hovered image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, CheckedHoveredImage)
|
||||
|
||||
/** The checked pressed image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, CheckedPressedImage)
|
||||
|
||||
/** The undetermined image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, UndeterminedImage)
|
||||
|
||||
/** The undetermined hovered image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, UndeterminedHoveredImage)
|
||||
|
||||
/** The undetermined pressed image for the checkbox - overrides the style's */
|
||||
SLATE_ARGUMENT(const FSlateBrush*, UndeterminedPressedImage)
|
||||
|
||||
// This is the bit we're adding
|
||||
// SCheckBox is missing hovered/unhovered too
|
||||
SLATE_EVENT( FSimpleDelegate, OnHovered )
|
||||
SLATE_EVENT( FSimpleDelegate, OnUnhovered )
|
||||
SLATE_EVENT( FSimpleDelegate, OnFocusReceived )
|
||||
SLATE_EVENT( FSimpleDelegate, OnFocusLost )
|
||||
|
||||
SLATE_END_ARGS()
|
||||
|
||||
public:
|
||||
|
||||
void Construct( const FArguments& InArgs );
|
||||
|
||||
virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent) override;
|
||||
virtual void OnFocusLost(const FFocusEvent& InFocusEvent) override;
|
||||
|
||||
void SetOnFocusReceived(FSimpleDelegate InOnFocusReceived);
|
||||
void SetOnFocusLost(FSimpleDelegate InOnFocusLost);
|
||||
|
||||
protected:
|
||||
FSimpleDelegate OnHoveredDelegate;
|
||||
FSimpleDelegate OnUnhoveredDelegate;
|
||||
FSimpleDelegate OnFocusReceivedDelegate;
|
||||
FSimpleDelegate OnFocusLostDelegate;
|
||||
|
||||
|
||||
public:
|
||||
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
|
||||
};
|
59
Source/StevesUEHelpers/Public/StevesUI/FocusableCheckBox.h
Normal file
59
Source/StevesUEHelpers/Public/StevesUI/FocusableCheckBox.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/CheckBox.h"
|
||||
#include "FocusableCheckBox.generated.h"
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCheckBoxHoveredEvent);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCheckBoxUnhoveredEvent);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCheckBoxFocusReceivedEvent);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCheckBoxFocusLostEvent);
|
||||
/**
|
||||
* This is a simple subclass of UCheckBox to provide some missing features
|
||||
*
|
||||
* * Focus events
|
||||
* * Hover events
|
||||
* * Focus style based on hover style
|
||||
* * Assign focus to self on hover to prevent double-highlighting
|
||||
*/
|
||||
UCLASS()
|
||||
class STEVESUEHELPERS_API UFocusableCheckBox : public UCheckBox
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
bool bUseHoverStyleWhenFocussed = true;
|
||||
|
||||
UPROPERTY( BlueprintAssignable, Category = "CheckBox|Event" )
|
||||
FOnCheckBoxHoveredEvent OnHovered;
|
||||
|
||||
UPROPERTY( BlueprintAssignable, Category = "CheckBox|Event" )
|
||||
FOnCheckBoxUnhoveredEvent OnUnhovered;
|
||||
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="CheckBox|Event")
|
||||
FOnCheckBoxFocusReceivedEvent OnFocusReceived;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="CheckBox|Event")
|
||||
FOnCheckBoxFocusLostEvent OnFocusLost;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
bool bTakeFocusOnHover = true;
|
||||
protected:
|
||||
FCheckBoxStyle FocussedStyle;
|
||||
|
||||
void SlateHandleFocusReceived();
|
||||
void SlateHandleFocusLost();
|
||||
|
||||
void ApplyFocusStyle();
|
||||
void UndoFocusStyle();
|
||||
void SlateHandleHovered();
|
||||
void SlateHandleUnhovered();
|
||||
|
||||
virtual TSharedRef<SWidget> RebuildWidget() override;
|
||||
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user