Add Function Call to dynamically created Uslider

Hi all!

I’m creating a bunch of sliders (~100) on the fly at runtime. I’m able to create the sliders no problem but have no idea what to call to add a function call when OnValueChanged gets called…nor would I know how to call it. Would a kind soul be able to point me in the right direction?

    void UGameManager::PopulateGUIWithAttributes(int userIndex, UPanelWidget * facePanel, UPanelWidget * bodyPanel, UPanelWidget * advancedPanel)
        {
        
        //.....blahblahblah grab the array here
        
        //Iterate throught the 'face' object in the json and adds the correct GUI property.
        	for (auto& itr : cat.GetObject())
        	{
        		if (itr.value.IsFloat())
        		{
        			FString nameOfProperty = itr.name.GetString();
        			UTextBlock *sliderLabel = ConstructObject<UTextBlock>(UTextBlock::StaticClass(), this);
        			sliderLabel->SetText(FText::FromString(nameOfProperty));
        			USlider *activeSlider = ConstructObject<USlider>(USlider::StaticClass(), this);
        			activeSlider->SetValue(itr.value.GetFloat());

//THE LINE IN QUESTION 
        			activeSlider->OnValueChanged.....//Call SetItrValue(itr.name, activeSlider->GetValue()
        			USpacer * tstSpacer = ConstructObject<USpacer>(USpacer::StaticClass(), this);
        			tstSpacer->SetSize(FVector2D(0, 40));
        			facePanel->AddChild(sliderLabel);
        			facePanel->AddChild(activeSlider);
        			facePanel->AddChild(tstSpacer);
        		}
        	}
        }

This isn’t really an answer because I’ve not gotten around to trying this out myself yet, however until someone can supply you with an answer this should be a push in the right direction.

I believe what you are looking for is an event dispatcher / Delegates for custom events.

Have a look through these links:

https://answers.unrealengine.com/questions/336314/creating-custom-event-from-c.html

Hopefully these help.

They definitely pointed me in the right direction, however, I’m wanting to call a function and pass more parameters than the 1 the OnValueChanged supplies. I’ve hit a bit of a wall with this one :confused:

Also, learning how unreal handles delegates was vital to doing what I was trying to do.

I ended up creating my own slider that extended uslider. There I was able to store the values I needed to.

My new Slider Class:
#pragma once

#include "CoreMinimal.h"
#include "Components/Slider.h"
#include "IncredibleSlider.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnIncredibleFloatValueChangedEvent, float, Value, FString, ParameterName, int, CharacterIndex);

/**
 * 
 */
UCLASS()
class INCREDIBLY_YOU_API UIncredibleSlider : public USlider
{
	GENERATED_BODY()
	
	UIncredibleSlider();

public:
	void SetParameterName(const FString paramName) { parameterName = paramName; }
	FString GetParameterName() { return parameterName; }
	void SetCharacterIndex(const int charIndex) { characterIndex = charIndex; }
	int GetCharacterIndex() { return characterIndex; }

	UPROPERTY(BlueprintAssignable, Category = "Widget Event")
    FOnIncredibleFloatValueChangedEvent OnIncredibleValueChanged;
	
private:

	FString parameterName;
	int characterIndex;

protected:
	// UWidget interface
	virtual TSharedRef<SWidget> RebuildWidget() override;

	void HandleOnValueChanged(float InValue);
	
};

The CPP:
#include “IncredibleSlider.h”
#include “Widgets/DeclarativeSyntaxSupport.h”
#include “Widgets/Input/SSlider.h”

UIncredibleSlider::UIncredibleSlider() :
	Super(), parameterName("")
{

}

TSharedRef<SWidget> UIncredibleSlider::RebuildWidget()
{
	MySlider = SNew(SSlider)
		.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))
		.OnValueChanged(BIND_UOBJECT_DELEGATE(FOnFloatValueChanged, HandleOnValueChanged));

	return MySlider.ToSharedRef();
}

void UIncredibleSlider::HandleOnValueChanged(float InValue)
{
	UE_LOG(LogTemp, Warning, TEXT("******UPDATING SLIDER!!!!******"));
	OnValueChanged.Broadcast(InValue);
	OnIncredibleValueChanged.Broadcast(InValue, parameterName, characterIndex);
}

THEN I created the slider in code. I eventually call the following function from my manager class (UGameManager):

void UGameManager::CreateSliderControl(int userIndex, FString nameOfProperty, float floatValue, UPanelWidget * parentPanel)
{
	UTextBlock *sliderLabel = ConstructObject<UTextBlock>(UTextBlock::StaticClass(), this);
	sliderLabel->SetText(FText::FromString(nameOfProperty));
	UIncredibleSlider *activeSlider = ConstructObject<UIncredibleSlider>(UIncredibleSlider::StaticClass(), this);
	activeSlider->SetParameterName(nameOfProperty);
	activeSlider->SetValue(floatValue);
	activeSlider->SetCharacterIndex(userIndex);

	activeSlider->OnIncredibleValueChanged.AddDynamic(this, &UGameManager::SetCharacterFloat);

	FString paramName = activeSlider->GetParameterName();
	UE_LOG(LogTemp, Warning, TEXT("%s"), *paramName);

	parentPanel->AddChild(sliderLabel);
	parentPanel->AddChild(activeSlider);
}