Download

Custom UMG slider

Hello,
looking for a solution to have a two-handed slider in UMG, I spent a lot of time looking on the internet with no real success.

I was happy to find this post (How to create custom widget element? - UE4 AnswerHub) where someone provided C ++ code to do what I needed.
However the code is written for UE 4.13 and reusing it in UE 4.26.2 I got this error message when I compiled:

:no_entry_sign: …/DoubleSlider.h(106) : LogCompile: Error: SetSliderBarColor: Override of UFUNCTION in parent class (Slider) cannot have a UFUNCTION() declaration above it; it will use the same parameters as the original declaration.

Having very limited knowledge of C ++ I have no idea what to do to correct the code.

If anyone has any idea how to get this code to work on UE 4.26, I would be very grateful.

DoubleSlider.h :

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Runtime/UMG/Public/UMG.h"
#include "Components/Slider.h"
#include "DoubleSlider.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFloatValueStartChangedEvent, float, ValueStart);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFloatValueEndChangedEvent, float, ValueEnd);

UCLASS()
class NBHD_PANEL_API UDoubleSlider : public USlider
{
	GENERATED_BODY()
	
public:

	UPROPERTY(EditAnywhere, Category = Appearance, meta = (ClampMin = "0", ClampMax = "1", UIMin = "0", UIMax = "1"))
	float ValueStart;
		
	UPROPERTY()
	FGetFloat ValueStartDelegate;

	UPROPERTY(EditAnywhere, Category = Appearance, meta = (ClampMin = "0", ClampMax = "1", UIMin = "0", UIMax = "1"))
	float ValueEnd;
	
	UPROPERTY()
	FGetFloat ValueEndDelegate;

public:
	/** The color to draw the slider handle in. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance)
	FLinearColor SliderHandleStartColor;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance)
	FLinearColor SliderHandleEndColor;

	/** Whether the slidable area should be indented to fit the handle. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance, AdvancedDisplay)
	bool IndentHandleStart;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance, AdvancedDisplay)
	bool IndentHandleEnd;

	/** Whether the handle is interactive or fixed. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance, AdvancedDisplay)
	bool LockedStart;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance, AdvancedDisplay)
	bool LockedEnd;

	/** The amount to adjust the value by, when using a controller or keyboard */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance, meta = (ClampMin = "0", ClampMax = "1", UIMin = "0", UIMax = "1"))
	float StepSizeStart;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Appearance, meta = (ClampMin = "0", ClampMax = "1", UIMin = "0", UIMax = "1"))
	float StepSizeEnd;


public:
	/** Called when the value is changed by slider or typing. */
	UPROPERTY(BlueprintAssignable, Category = "Widget Event")
	FOnFloatValueStartChangedEvent OnValueStartChanged;

	UPROPERTY(BlueprintAssignable, Category = "Widget Event")
	FOnFloatValueEndChangedEvent OnValueEndChanged;

	/** Gets the current value of the slider. */
	UFUNCTION(BlueprintCallable, Category = "Behavior")
	float GetValueStart() const;

	UFUNCTION(BlueprintCallable, Category = "Behavior")
	float GetValueEnd() const;

	/** Sets the current value of the slider. */
	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetValueStart(float InValue);

	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetValueEnd(float InValue);

	/** Sets if the slidable area should be indented to fit the handle */
	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetIndentHandleStart(bool InValue);

	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetIndentHandleEnd(bool InValue);

	/** Sets the handle to be interactive or fixed */
	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetLockedStart(bool InValue);

	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetLockedEnd(bool InValue);

	/** Sets the amount to adjust the value by, when using a controller or keyboard */
	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetStepSizeStart(float InValue);

	UFUNCTION(BlueprintCallable, Category = "Behavior")
	void SetStepSizeEnd(float InValue);

	/** Sets the color of the slider bar */
	UFUNCTION(BlueprintCallable, Category = "Appearance")
	void SetSliderBarColor(FLinearColor InValue);

	/** Sets the color of the handle bar */
	UFUNCTION(BlueprintCallable, Category = "Appearance")
	void SetSliderHandleStartColor(FLinearColor InValue);

	UFUNCTION(BlueprintCallable, Category = "Appearance")
	void SetSliderHandleEndColor(FLinearColor InValue);

	// UWidget interface
	virtual void SynchronizeProperties() override;
	// End of UWidget interface

	// UVisual interface
	virtual void ReleaseSlateResources(bool bReleaseChildren) override;
	// End of UVisual interface

#if WITH_EDITOR
	virtual const FText GetPaletteCategory() override;
#endif

protected:
	/** Native Slate Widget */
	TSharedPtr<SDoubleSlider> MyDoubleSlider;
	
	// UWidget interface
	virtual TSharedRef<SWidget> RebuildWidget() override;
	// End of UWidget interface

	void HandleOnValueStartChanged(float InValue);
	void HandleOnValueEndChanged(float InValue);
	void HandleOnMouseCaptureBegin();
	void HandleOnMouseCaptureEnd();
	void HandleOnControllerCaptureBegin();
	void HandleOnControllerCaptureEnd();
	
	
};

DoubleSlider.cpp :

// Fill out your copyright notice in the Description page of Project Settings.

#include "NBHD_PANEL.h"
#include "DoubleSlider.h"

#define LOCTEXT_NAMESPACE "UMG"

/////////////////////////////////////////////////////
// UDoubleSlider

UDoubleSlider::UDoubleSlider(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	Orientation = EOrientation::Orient_Horizontal;
	SliderBarColor = FLinearColor::White;
	SliderHandleStartColor = FLinearColor::White;
	SliderHandleEndColor = FLinearColor::White;
	StepSizeStart = 0.01f;
	StepSizeEnd = 0.01f;
	SDoubleSlider::FArguments Defaults;
	WidgetStyle = *Defaults._Style;
	IsFocusable = true;
}

TSharedRef<SWidget> UDoubleSlider::RebuildWidget()
{
	MyDoubleSlider = SNew(SDoubleSlider)
		.Style(&WidgetStyle)
		.IsFocusable(IsFocusable)
		.OnMouseCaptureBegin(BIND_UOBJECT_DELEGATE(FSimpleDelegate, HandleOnMouseCaptureBegin))
		.OnMouseCaptureEnd(BIND_UOBJECT_DELEGATE(FSimpleDelegate, HandleOnMouseCaptureEnd))
		.OnControllerCaptureBegin(BIND_UOBJECT_DELEGATE(FSimpleDelegate, HandleOnControllerCaptureBegin))
		.OnControllerCaptureEnd(BIND_UOBJECT_DELEGATE(FSimpleDelegate, HandleOnControllerCaptureEnd))
		.OnValueStartChanged(BIND_UOBJECT_DELEGATE(FOnFloatValueChanged, HandleOnValueStartChanged))
		.OnValueEndChanged(BIND_UOBJECT_DELEGATE(FOnFloatValueChanged, HandleOnValueEndChanged));

	return MyDoubleSlider.ToSharedRef();
}

void UDoubleSlider::SynchronizeProperties()
{
	Super::SynchronizeProperties();

	TAttribute<float> ValueStartBinding = OPTIONAL_BINDING(float, ValueStart);
	TAttribute<float> ValueEndBinding = OPTIONAL_BINDING(float, ValueEnd);

	MyDoubleSlider->SetOrientation(Orientation);
	MyDoubleSlider->SetSliderBarColor(SliderBarColor);
	MyDoubleSlider->SetSliderHandleStartColor(SliderHandleStartColor);
	MyDoubleSlider->SetSliderHandleEndColor(SliderHandleEndColor);
	MyDoubleSlider->SetValueStart(ValueStartBinding);
	MyDoubleSlider->SetValueEnd(ValueEndBinding);
	MyDoubleSlider->SetLockedStart(LockedStart);
	MyDoubleSlider->SetLockedEnd(LockedEnd);
	MyDoubleSlider->SetIndentHandle(IndentHandle);
	MyDoubleSlider->SetStepSize(StepSize);
}

void UDoubleSlider::ReleaseSlateResources(bool bReleaseChildren)
{
	Super::ReleaseSlateResources(bReleaseChildren);

	MyDoubleSlider.Reset();
}

void UDoubleSlider::HandleOnValueStartChanged(float InValue)
{
	OnValueStartChanged.Broadcast(InValue);
}

void UDoubleSlider::HandleOnValueEndChanged(float InValue)
{
	OnValueEndChanged.Broadcast(InValue);
}

void UDoubleSlider::HandleOnMouseCaptureBegin()
{
	OnMouseCaptureBegin.Broadcast();
}

void UDoubleSlider::HandleOnMouseCaptureEnd()
{
	OnMouseCaptureEnd.Broadcast();
}

void UDoubleSlider::HandleOnControllerCaptureBegin()
{
	OnControllerCaptureBegin.Broadcast();
}

void UDoubleSlider::HandleOnControllerCaptureEnd()
{
	OnControllerCaptureEnd.Broadcast();
}

float UDoubleSlider::GetValueStart() const
{
	if (MyDoubleSlider.IsValid())
	{
		return MyDoubleSlider->GetValueStart();
	}

	return ValueStart;
}

float UDoubleSlider::GetValueEnd() const
{
	if (MyDoubleSlider.IsValid())
	{
		return MyDoubleSlider->GetValueEnd();
	}

	return ValueEnd;
}

void UDoubleSlider::SetValueStart(float InValue)
{
	ValueStart = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetValueStart(InValue);
	}
}

void UDoubleSlider::SetValueEnd(float InValue)
{
	ValueEnd = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetValueEnd(InValue);
	}
}

void UDoubleSlider::SetIndentHandleStart(bool InIndentHandle)
{
	IndentHandleStart = InIndentHandle;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetIndentHandleStart(InIndentHandle);
	}
}

void UDoubleSlider::SetIndentHandleEnd(bool InIndentHandle)
{
	IndentHandleEnd = InIndentHandle;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetIndentHandleEnd(InIndentHandle);
	}
}

void UDoubleSlider::SetLockedStart(bool InLocked)
{
	LockedStart = InLocked;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetLockedStart(InLocked);
	}
}

void UDoubleSlider::SetLockedEnd(bool InLocked)
{
	LockedEnd = InLocked;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetLockedEnd(InLocked);
	}
}

void UDoubleSlider::SetStepSizeStart(float InValue)
{
	StepSizeStart = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetStepSizeStart(InValue);
	}
}

void UDoubleSlider::SetStepSizeEnd(float InValue)
{
	StepSizeEnd = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetStepSizeEnd(InValue);
	}
}

void UDoubleSlider::SetSliderHandleStartColor(FLinearColor InValue)
{
	SliderHandleColorStart = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetSliderHandleColorStart(InValue);
	}
}

void UDoubleSlider::SetSliderHandleEndColor(FLinearColor InValue)
{
	SliderHandleColorEnd = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetSliderHandleColorEnd(InValue);
	}
}

void UDoubleSlider::SetSliderBarColor(FLinearColor InValue)
{
	SliderBarColor = InValue;
	if (MyDoubleSlider.IsValid())
	{
		MyDoubleSlider->SetSliderBarColor(InValue);
	}
}


#if WITH_EDITOR

const FText UDoubleSlider::GetPaletteCategory()
{
	return LOCTEXT("Common", "Common");
}

#endif

/////////////////////////////////////////////////////

#undef LOCTEXT_NAMESPACE


Thank’s

the class DoubleSlider is extending the class Slider you can see that here:

class NBHD_PANEL_API UDoubleSlider : public USlider

The error says that the Slider class already contains a function called SetSliderBarColor. The error also says you cannot redefine that function. So to fix this you could just remove the function in your DoubleSlider class, and you will be able to use the original function from the parent class because you extended from that class.

BUT, if the child function really needs to be different, you can go to the parent class and change it to be a virtual function. I think virtual functions are allowed to have a default implementation that can be overridden, and pure virtual functions have no default implementation.