Download

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

I’m using this plugin for handling Loading Screen specifics. From what I understand it takes advantage of the built in MoviePlayer Loading Screen abilities. GitHub - ue4plugins/LoadingScreen: A plugin for Unreal Engine 4 to expose simple controls for managing

Goal: I’m trying to create a node that I can call before loading a new level that allows me to set the movie that plays during the next load. (Utilizing cutscenes to take advantage of the downtime during loads)

Face value obsticle: I tried exposing the variable to blueprints the general way by exposing the UProperty. The problem is it requires a target which is the Loading Screen Reference. I have no idea how to expose the reference that would make it work.
*
Three possible ways to solve the problem that I need help with: *

  • A) How to expose the Loading Screen Reference required to use the exposed Uproperties in blueprint
  • **B) **Another way to set the variable that doesn’t require a target like (a)
  • C) Have the code reference a string array in my blueprint Game Instance

All help is greatly appreciated! :smiley: <3

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

Thanks for your perspective! I’ll look into it. Right off the bat, I still have a lot more to learn than I have time for. Getting errors.

So are you saying there is no way to expose the plugins variables to blueprint? So I can interface directly with it instead of make creating a system that bypasses the plugin, which in turn will force me to recreate everything.

Hello!

Yes, you can expose plug-in variables. The information you give is very vague; if you provided source code showing the variable you wish to expose there is likely another solution that suits you. From what you described it seemed (to me) like the approach up there best suits you.

Cheers,
Univise

Thanks for the reply Univise! I thought I was super clear on EXACTLY what I was trying to do. The source code is right on the Github link I originally provided on the first sentence, though I realized I didn’t specifically state where in the code I was trying to expose, like I stated on my facebook page facepalm. I’m sorry for being so silly.

Under Source > Private is a header file for Settings (LoadingScreenSettings.h). There is a struct here with loading screen variables. Within the struct is MoviePaths, which relays the same variable MoviePlayer needs to search for the movie(s).

Below the struct is a class with more UProperties. There are two instances of the struct there, one for StartupScreen and the other for DefaultScreen (Map Transition Loading Screen). I would love to make DefaultScreen exposed to blueprints so I can change any or all the variables that come with the struct before the next level load. (In my case, mainly to change the MoviePaths to a cutscene during level load).

I was able to expose the UProperty for DefaultScreen to Blueprints, but it requires me to have a reference to Loading Screen plugged into the Target. I’m guess I need to create a node like “Get Player Controller” that grabs the Loading Screen instance of the plugin? I just don’t know how. With all the work I’m doing, I hope the exhaustion isn’t making me ignore the simplest of solutions.

BTW, I wouldn’t mind Crediting you in my game if you would like if this pans out.

Bump! I was hoping not having to go a week without this getting done. Time is counting down on my end and this is a pretty critical part of the project. :frowning:

Hello,

I have already given you the answer above, sbnewsom, for this problem:

Add this code to your ULoadingScreenSettings class:



UFUNCTION(BlueprintPure, Blueprincallable, Category = "Movie")
static ULoadingScreenSettings* GetInstance()
{
    return GetMutableDefault<ULoadingScreenSettings>();
}


In your blueprints, you can then call GetInstance as a pure node (the green ones without exec pins).

Do note, however, that you can also expose these settings to the Project settings window which is a much better workflow than using code to configure code (which you’d be doing). The approach would be the one I described above. If you’d like a hand on getting an implementation done, you can PM me.

Cheers,
Univise

Hey Univise! Before I couldn’t wrap my head around it, but with your modification to the code…IT WORKED! Works perfectly!

Regarding your note, the settings are already exposed to the Project Settings. That’s the main issue. It’s static and prevents me from calling a cutscene during the load of a new map. It allowed me to set any number of videos, but they just play in order of the array. By referencing the Loading Screen, I have full control over how the next loading screen acts before I load a new map. Hell, with this control I’m able to customize the loading screen however I want depending on the scenario/state of the game. Now I can use very specific cutscenes to make loading screens more enjoyable, especially for a story centric game as you’ve seen.

I’m going to PM you anyways to touch base as you have proven ABSOLUTELY helpful one of the major roadblocks I’ve face!

Thanks,
Stuart