Manipulating Slate content during and after Construct()

Hi,

I am getting started with the Slate framework. I have created various UI components, set up style, callbacks, etc. Now I want to go a little further and I am stuck on two things.

The first question is about updating FSlateBrushes. I have a big menu with a few of those, I want to hide/show the menu. That is easy but I also want to change the brushes each time I show the menu. Of course, I could simply destroy and Construct the menu again each time but this is going to happen every few seconds, I think there is a better way. How can I change FSlateBrushes after they’ve been constructed ?

More generally, how can I re-initialize or delete content that was declared with SNew ? Should I use SEssignNew then Reset() the reference ?

The second question is a bit more trivial. What would be the syntax for using SNew in a for loop inside ChildSlot[], or even deeper into the Construct() (e.g. in a box slot, etc) ?

Thanks !

You really are the lifesaver today !

Okay so the loop thing is good, I did like in SShooterScoreboardWidget that does it, for anyone else reading. Works very well and the code is clean.

Now for the delegate thing, does this mean that each Construct call will simply load the resource from a user callback ? Can I use Slate parameters with this (that would be the icing on the cake) ?

Updating a Slate brush would generally be done via a delegate. Slate widgets can take arguments in the form of SLATE_ARGUMENT, or SLATE_ATTRIBUTE; an attribute can be optionally bound to a delegate to allow you to dynamically change the value at runtime, eg)

SNew(SImage).Image(this, &MyWidget::GetMyBrush)

If you want to populate a slot via a for loop, you can use SAssignNew to assign the thing with the slots (eg, SHorizontalBox) to a variable, and then use AddSlot(…) on that variable rather than using the Slate declarative syntax directly.

Assuming I understand your question correctly, yes, and yes.

If you have a Slate parameter which is from a SLATE_ATTRIBUTE with the same signature as the widget you ultimately give it to, then that can be passed through as is via the InArgs for your widget.

If your widget is custom enough that it doesn’t take this data via a Slate parameter, then you can just give it a callback local to that widget.

Ultimately you should end up with a delegate somewhere returning a const FSlateBrush* returned from a Slate style set.

void SMyWidget::Construct(const FArguments& InArgs)
{
    ChildContent
    [
        SNew(SImage).Image(this, &SMyWidget::GetMyBrush)
    ];
}

const FSlateBrush* SMyWidget::GetMyBrush() const
{
    return (MySuperStateThatNeedsADifferentBrush)
        ? FMySlateStyle::Get().GetBrush("MySuperBrush")
        : FMySlateStyle::Get().GetBrush("MyNormalBrush");

}

Ah, yes, you can totally do that via binding :slight_smile:

Assuming you have a variable available to Construct called RandomVarToBind of type TSharedPtr of FMyType (this can be any type, but also remember it’s bound by value).

void SMyWidget::Construct(const FArguments& InArgs)
{
    TSharedPtr<FMyType> RandomVarToBind = /* ... */

    ChildContent
    [
        SNew(SImage).Image(this, &SMyWidget::GetMyBrush, RandomVarToBind)
    ];
}

const FSlateBrush* SMyWidget::GetMyBrush(TSharedPtr<FMyType> RandomVarThatWasBound) const
{
    return (MySuperStateThatNeedsADifferentBrush)
        ? FMySlateStyle::Get().GetBrush("MySuperBrush")
        : FMySlateStyle::Get().GetBrush("MyNormalBrush");
}

Okay, I wanted to directly pass parameters to the delegate but this will do very well too since I’m going to have a few different callbacks.

Thank you very much for your help.

Yes, I just tried that. Slate really is awesome !

Thanks again. Hopefully I’m done with the noob questions :slight_smile:

I need to use this in a subcomponent. A Slate widget has the method and passes it as a Slate parameter to a sub-widget that has the actual Image() construct.

Is this possible ? How should I declare the callback parameter ?

I tried this :

DECLARE_DELEGATE_RetVal(
const FSlateBrush*,
FLoadImage)

SLATE_ARGUMENT(FLoadImage, IconCallback)

But thill get this :

‘widgetname::FArguments::IconCallback’ : function does not take 3 arguments

How does it work for my OnClicked method ? How is FonReply different from my custom type ?

Use SLATE_EVENT(FLoadImage, IconCallback) instead

Am I correct in my understanding that you have WidgetA, containing WidgetB, which contains an SImage, and that you need to pass a delegate from WidgetA through to the SImage which will control the brush used?

If so, you’d simply use a SLATE_ATTRIBUTE on WidgetB in the same way that SImage uses a SLATE_ATTRIBUTE to specify the brush used.

SLATE_ATTRIBUTE(const FSlateBrush*, IconCallback)

You would then forward that directly through to the SImage.

SNew(SImage).Image(InArgs._IconCallback)

Yes you are, and it works ! As always :slight_smile:

Thank you for your help !

Can you guys just point me to some of good tutorials or documentation of slates. i have just started it , but its hard to find any resources on that