13#include "CoreMinimal.h"
14#include "Modules/ModuleInterface.h"
15#include "Modules/ModuleManager.h"
41 template <CDerivedFrom<IModuleInterface> M>
45 moduleName.RemoveFromEnd(
TEXT_"Module");
46 moduleName.RemoveFromEnd(
TEXT_"ModuleInterface");
55 template <CDerivedFrom<IModuleInterface> M>
58 auto loadResult = EModuleLoadResult::Success;
60 auto moduleInterface = FModuleManager::Get().LoadModuleWithFailureReason(*name, loadResult);
61 ASSERT_RETURN(loadResult == EModuleLoadResult::Success && moduleInterface)
63 ->WithMessageF(
TEXT_"Couldn't load module {0} inferred from type {1}",
67 return static_cast<M*
>(moduleInterface);
75 template <CDerivedFrom<IModuleInterface> M>
80 ->WithError(result.GetErrorRef())
82 return *result.GetValue();
86 template <CDerivedFrom<IModuleInterface> M>
93 template <CDerivedFrom<IModuleInterface> M>
98 ->WithMessageF(
TEXT_"Couldn't get module {0} inferred from type {1}",
129 template <
typename T>
146 template <CObservableModule M>
157 BindListeners(
FWD(listeners));
166 BindListeners(
FWD(listeners));
167 ObserveModule(moduleName);
207 void ObserveModule(FName
const& moduleName)
209 decltype(
auto) manager = FModuleManager::Get();
210 M* module =
static_cast<M*
>(manager.GetModule(moduleName));
213 manager.OnModulesChanged().AddLambda([
this, moduleName](FName name, EModuleChangeReason changeReason)
215 if (changeReason == EModuleChangeReason::ModuleLoaded && moduleName == name)
216 ObserveModule(moduleName);
222 module->OnStartupModule.Add(OnStartupModule.Delegation());
223 module->OnShutdownModule.Add(OnShutdownModule.Delegation());
229 template <CObservableModule M,
typename T>
249 T* newObject = !factory.Create ?
new T() : factory.Create();
250 CreateObject(newObject);
251 if (factory.OnAfterCreated) factory.OnAfterCreated(*Storage.Get());
255 if (factory.OnShutdown) factory.OnShutdown(*Storage.Get());
264 ->WithMessage(
TEXT_"Module bound object was not available")
268 return *Storage.Get();
274 ->WithMessage(
TEXT_"Module bound object was not available")
278 return *Storage.Get();
282 const T*
TryGet()
const {
return Storage.Get(); }
286 void CreateObject(T* newObject)
288 if constexpr (CSharedInitializeable<T>)
290 else if constexpr (CSharedFromThis<T>)
291 Storage = MakeShareable<T>(newObject);
293 Storage = TUniquePtr<T>(newObject);
297 TObserveModule<M> Observer;
#define ASSERT_CRASH(condition,...)
Use this instead of check macro if the checked expression shouldn't be ignored in shipping builds....
#define ASSERT_RETURN(...)
Similar to check() macro, but return an error instead of crashing.
#define FWD(...)
Shorten forwarding expression with this macro so one may not need to specify explicit type.
Use leading TEXT_ without parenthesis for Unreal compatible text literals.
#define TEXT_
A convenience alternative to Unreal's own TEXT macro but this one doesn't require parenthesis around ...
"Extension" of a common TMulticastDelegate. It allows to define optional "flags" when adding a bindin...
Add this interface to your module class if other things can listen to module startup or shutdown.
virtual void ShutdownModule() override
virtual void StartupModule() override
TBelatedEventDelegate< void()> OnStartupModule
Event broadcasted on module startup or immediately executed upon subscription if module has already b...
TBelatedEventDelegate< void()> OnShutdownModule
Event broadcasted on module shutdown or immediately executed upon subscription if module has already ...
TInferredDelegate< Function, Captures... > From(Function func, Captures &&... captures)
Instead of specifying manually a delegate type, infer it from the input function and the extra captur...
Contains utilities for handling enums as strings or vice-versa.
FString EnumToStringCopy(Enum input)
Contains utilities for structured error handling.
Namespace for utilities handling Unreal modules.
FString InferModuleName()
Infer the module name from an input type. This exists because there's a very reliable naming conventi...
M & LoadUnrealModule()
Load a module or crash with IError if it cannot be done for any reason Module name is inferred from t...
M & GetUnrealModule()
Get an already loaded unreal module. If for any reason it's not loaded, crash the app.
M * GetUnrealModulePtr()
Shorthand for FModuleManager::GetModulePtr with the name inferred from given type.
TMaybe< M * > TryLoadUnrealModule()
Try to load a module and return an IError when that fails for any reason. Module name is inferred fro...
TSharedRef< T, Mode > MakeShareableInit(T *newObject, Args &&... args)
A wrapper around MakeShareable that automatically calls an initializer method Initialize on the insta...
constexpr FStringView TTypeName
Get a friendly string of an input type without using typeid(T).name().
FString TTypeString()
Same as TTypeName converted to FString. This is not cached and a new FString is created every time th...
A TValueOrError alternative for IError which allows implicit conversion from values and errors (no ne...
A record for the module event listeners.
TFunction< void()> OnShutdown
TFunction< void()> OnStartup
TFunction< void(T &)> OnAfterCreated
TFunction< void(T &)> OnShutdown
A wrapper around a given object which lifespan is bound to given module.
std::conditional_t< CSharedFromThis< T >, TSharedPtr< T >, TUniquePtr< T > > StorageType
TModuleBoundObject(FObjectFactory &&factory={})
T const & GetChecked() const
Use this in global variables to automatically do things on module startup or shutdown.
TObserveModule & OnStartup(TFunction< void()> &&func)
Specify function to be executed on startup.
TBelatedEventDelegate< void()> OnShutdownModule
Event broadcasted on module shutdown or immediately executed upon subscription if module has already ...
TObserveModule & OnShutdown(TFunction< void()> &&func)
Specify function to be executed on shutdown.
TObserveModule(FName const &moduleName, FObserveModuleListener &&listeners)
This constructor provides an explicit FName for getting the module.
TObserveModule(FObserveModuleListener &&listeners)
Default constructor will try to infer module name from type name. Given convention (F|I)Foobar(Module...
TBelatedEventDelegate< void()> OnStartupModule
Event broadcasted on module startup or immediately executed upon subscription if module has already b...