Display dynamic texture in slate

Haha, yeah it seems like you’ve managed by bad luck to go through all combinations that don’t work before finding the one that does.

Okay, so yeah the delegate expects a pointer which you’ve now sorted.
Also, when you use the _Static binding, you shouldn’t pass in the this pointer at all, since it isn’t binding to any particular object instance. I’d be surprised if it compiles if you do.

Now, the delegate requires a function returning const FSlateBrush*, but that doesn’t mean your variable PreviewImageBrush needs to be either const, or a pointer. You can very well define it as:


static FSlateBrush PreviewImageBrush;

You can then initialize or change it whenever you like. You’d just need to alter your function to be:


const FSlateBrush* FOctaneRenderPluginModule::GetPreviewImage() const{
    return &UOctaneOutput::PreviewImageBrush;
}

So you take the address of an FSlateBrush, yielding a type of FSlateBrush*, which can be converted to const FSlateBrush* no problem. You can always add constness, you just can’t take it away. Adding constness is just like saying “I have a variable that I’m allowed to modify, but I’m giving it to you in const form, so you can’t modify it.”

Now, hopefully that should be enough to get things working. If so you can skip what I’m about to add if you like, otherwise, read on at your peril. :wink:

Slate delegates are used to provide a dynamic attribute to a widget - instead of just passing it a value, you pass it a delegate and tell Slate: “Whenever you need this value, call this function to get it”. That way, you have complete control over what value Slate sees at any time. The thing is, here all your delegate function is doing is just returning a pointer to the same static variable every time. There’s no conditional logic in your function, so you don’t need a delegate at all. You could just as well have written:


SNew(SImage).Image(&UOctaneOutput::PreviewImageBrush)

It’s made complicated by the fact that pointers are involved. Compare it to this:


SNew(STextBlock).Text(MyFTextVariable)

This is passing a copy of a text variable to a widget at construction. That means if you subsequently change the value of MyFTextVariable, it won’t be reflected by the widget. In this case, you would want to use a delegate. That way Slate will get a new copy of the updated text every time.

With the case of SImage, you are giving Slate a pointer to a brush. The internals of that brush may change (for example, the UTexture2D inside it), but the brush itself is always UOctaneOutput::PreviewImageBrush. So you can do without the delegate. Whenever Slate needs to use the brush, it’s going to follow that pointer and access its contents. If the contents have been changed, that will be reflected automatically. Telling Slate every frame, “Hey, here’s the pointer to my brush” is superfluous, since the pointer is the same every time.

Hope that doesn’t add too much extra confusion!

Hmm. I had to do:


SNew(SImage).Image(UOctaneOutput::PreviewImageBrush)

…without the reference to get it to build. That’s probably OK because the original object is still just a pointer, yeah? (static FSlateBrush * PreviewImageBrush)

But then I get a runtime crash on SetResourceObject:


UOctaneOutput::PreviewImageBrush->SetResourceObject(UOctaneOutput::Texture);

I’ve definitely initialized the texture with placeholder colour data at that stage and this is happening before it tries to build the slate hierachy. The error is vague though:


First-chance exception at 0x000007FEE4F3F800 (UE4Editor-SlateCore.dll) in UE4Editor.exe: 0xC0000005: Access violation writing location 0x0000000000000060.

The addresses above don’t change even on a rebuild.

Jiggered some stuff around and now it works! Thanks for the help! I’m going to have to figure out exactly what it is that I did to break it, but I suspect it was to do with texture allocation.

Last question for this thread!

When I save now, the editor crashes. It’s like it’s trying to save the texture resource, even though it doesn’t exist in the content browser, doesn’t have a name, etc.

Is there any way to block the brush or texture from trying to save? This behaviour only came in once I attached it to the brush. I’m not at all positive that’s whats going wrong either.

Alternately, is there an onUnLoad() function or something that I can try binding to, something like that?

That’s because you left PreviewImageBrush as a pointer. If you see the first code section in my previous post, I suggested to change the static member to no longer be a pointer. You then create a pointer to it using the &-operator.

Just using a pointer to a texture within a Slate brush will not cause it to try to save anything it shouldn’t. If you still get a crash after changing the brush declaration as above, you’d have to find out what line is causing it by debugging in Visual Studio, and also posting the stack trace. Without that it’s impossible for me to say what the cause is.

Gotcha. Yeah, that’s what I ended up doing.

The call stack was pretty useless, but I ended up adding:


Texture->AddToRoot();

…and the problem went away. So it was definitely a case of the texture being GCed, since that prevents it.