I’m poking around in Slate for the first time and it’s pretty neat. I’ve created a tab, added some UI and added a button, but when I instantiate the tab in the editor the entire editor hangs.
I was originally getting following error during compile:
error C2039: 'AsShared' : is not a member of 'FMyPluginModule'
So after googling around, in my .h file I inherited from the TSharedFromThis template:
class FMyPluginModule : public IModuleInterface, public TSharedFromThis<FMyPluginModule >
Which is fine until the tab instantiates, then it hangs.
I fired up the debugger with the onclicked() line as a breakpoint but I’m still a bit new to this so without knowing more about the engine and delegates, it wasn’t very helpful.
So, what’d I do wrong?
I understand the basic concept of delegates and I’ve used them in C# but naturally everything is more difficult in C++. In particular I don’t have my head around the TSharedRef<> template yet. In particular, can someone explain what’s happening here?
TSharedRef<class SDockTab> OnSpawnPluginTab(const class FSpawnTabArgs& SpawnTabArgs);
So I’m assuming that when this is instantiated, a value somewhere is incremented so that SDockTab can be garbage collected once OnSpawnPluginTab is removed. Is this right? My description feels a bit ***-backwards to me.
Are there any good resources to read that would help me out here?
OnSpawnPluginTab is just creating a new widget, which it returns wrapped in a shared reference. So yes, essentially it is just something to help maintain the lifetime of the object for as long as something is relying on it.
OnClicked is expecting a shared ptr/ref, or something that can be converted to one. If you use OnClicked_Raw instead, that expects a normal pointer, so you wouldn’t need to derive from TSharedFromThis. It’s hard to say if/why that would be causing the crash though. Posting more contextual code may help, but really you just need to step through the debugger and find what triggered it - most probably accessing a null pointer or freed memory somewhere.
Thanks for the reply! It wasn’t a crash per se, it just hung, as in it was doing something, endlessly.
I should have been more clear as I know what the delegate functions themselves do. My specific question is, what’s this?
TSharedRef<class SDockTab> OnXYZFunction
Is OnXYZFunction passing something to the TSharedRef<class SDockTab> part or something? How do we mentally structure this? What exactly is TSharedRef<class SDockTab> doing? I understand templates as well, just not THIS template, mostly because my grasp of what it’s doing with the reference is still a bit sketchy.
to bind OnClicked delegate. It’s just that slate events takes Shared pointers as default while binding but you’re not limited to them.
You can bind delegates to static functions, UObjects and raw (native) c++ objects. You can actually use this code and it should work as expected:
For more examples check out the source code of other plugins and make use of widget reflector inside Unreal Editor to check out the source code of specific widgets.
Gotcha. It seems to be what I thought then, I just didn’t know about _raw. I thought there was some black magic going on, but I guess not. Thanks again!
I’m not sure I follow, but it seems your question is more of C++ syntax.
TSharedRef<class SDockTab>
This is just a type, just like int or SDockTab or SDockTab*. We can describe it as the type ‘Shared reference to SDockTab’. The fact that the type is generated from a template is essentially irrelevant.
TSharedRef<class SDockTab> OnSpawnPluginTab(const class FSpawnTabArgs& SpawnTabArgs);
So this is just a function declaration, of a function that returns a ‘Shared reference to SDockTab’. If you look at the implementation, it is just calling SNew, which creates a new SDockTab and stuffs it into the shared reference.
Absolutely. On a high conceptual level, they’re the same.
In practice, the latter is a raw C++ reference to a SDockTab, which guarantees nothing about the lifetime of the SDockTab being referenced. The former is a smart reference, an object which conceptually acts like a reference to a SDockTab, but ensures that the SDockTab will continue to exist at least as long as the reference itself does.