[Newb] Exposing plugin variable to blueprint (Loading Screen Plugin)

Hello!

I assume you only require one instance of your movie player, right? You can simply create a static getter like in the Singleton design pattern. Unreal helps you with this: for every UClass registered, Unreal create a default object obtainable by GetDefault<Type>() and GetMutableDefault<Type>().



// in header file

UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Movie")
static class UMoviePlayer* GetInstance();

// in source file
class UMoviePlayer* UMoviePlayer::GetInstance()
{
    return GetMutableDefault<UMoviePlayer>();
}


If you want to be able to use a (blueprint-derived) class, this is also possible. GetMutableDefault and GetDefault both except a class parameter for. To do this, create a settings class, like UPluginSettings, add a TSubclassOf UProperty that is marked as config, and in your plugin module (IModuleInterface) do this:



// in header file

class FMoviePlayerModule : public IModuleInterface
{
public:

	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};

// in source file

#if WITH_EDITOR
#include "ISettingsModule.h"
#define LOCTEXT_NAMESPACE "MoviePlayerModule"
#endif

void FMoviePlayerModule::StartupModule()
{
	#if WITH_EDITOR
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->RegisterSettings("Project", "Project", "Movie Player",
			LOCTEXT("MoviePlayerSettingsName", "Movie Player"),
			LOCTEXT("MoviePlayerDescription", "Configure Movie Player"),
			UMoviePlayerSettings::GetMutableDefault<UMoviePlayerSettings>()
			);
	}
#endif
}

void FMoviePlayerModule::ShutdownModule()
{
	#if WITH_EDITOR
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->UnregisterSettings("Project", "Project", "Movie Player");
	}
#endif
}

#if WITH_EDITOR
#undef LOCTEXT_NAMESPACE 
#endif



Inside the project settings, a new option will now appear where you can set the movie player class to a blue-print derived one. Now you could change your UMoviePlayer::GetInstance implementation to:



class UMoviePlayer* UMoviePlayer::GetInstance()
{
    return GetMutableDefault<UMoviePlayer>(GetMutableDefault<UMoviePlayerSettings>()->MoviePlayerClass); // Important note: you should do a null pointer check for MoviePlayerClass and do a UE_LOG if it is null. This is just in case you forget to configure the setting.
}


A short discussion for the designers among us: If you are about to say Singletons are evil, this approach is not strictly one. This class to not constrain the instanciation of itself and hence does not violate the single responsibility princple, which many people claim the Singleton pattern does.

Cheers,
Univise