MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
Modules.h
Go to the documentation of this file.
1/** @noop License Comment
2 * @file
3 * @copyright
4 * This Source Code is subject to the terms of the Mozilla Public License, v2.0.
5 * If a copy of the MPL was not distributed with this file You can obtain one at
6 * https://mozilla.org/MPL/2.0/
7 *
8 * @author David Mórász
9 * @date 2025
10 */
11
12#pragma once
13#include "CoreMinimal.h"
14#include "Mcro/TypeName.h"
16
17/** Namespace for utilities handling Unreal modules */
19{
20 using namespace Mcro::Delegates;
21 using namespace Mcro::Concepts;
22 using namespace Mcro::TypeName;
23
24 /** Add this interface to your module class if other things can listen to module startup or shutdown */
25 class MCRO_API IObservableModule : public IModuleInterface
26 {
27 public:
28
29 /**
30 * Event broadcasted on module startup or immediately executed upon subscription if module has already been
31 * started up.
32 */
34
35 /**
36 * Event broadcasted on module shutdown or immediately executed upon subscription if module has already been
37 * shut down.
38 */
40
41 virtual void StartupModule() override;
42 virtual void ShutdownModule() override;
43 };
44
45 /** Use this in global variables to automatically do things on module startup or shutdown */
46 template <CDerivedFrom<IObservableModule> M>
48 {
49 /**
50 * Default constructor will try to infer module name from type name. Given convention
51 * `(F|I)Foobar(Module(Interface)?)? the extracted name will be Foobar. If your module doesn't follow this
52 * naming use the constructor accepting an FName
53 */
55 {
56 auto moduleName = TTypeString<M>.Mid(1);
57 moduleName.RemoveFromEnd(TEXT("Module"));
58 moduleName.RemoveFromEnd(TEXT("ModuleInterface"));
59 ObserveModule(moduleName);
60 }
61
62 /** This constructor provides an explicit FName for getting the module */
63 TObserveModule(FName const& moduleName)
64 {
65 ObserveModule(moduleName);
66 }
67
68 /**
69 * Event broadcasted on module startup or immediately executed upon subscription if module has already been
70 * started up.
71 */
73
74 /**
75 * Event broadcasted on module shutdown or immediately executed upon subscription if module has already been
76 * shut down.
77 */
79
80 /** Specify function to be executed on startup */
81 TObserveModule& OnStartup(TFunction<void()>&& func)
82 {
83 OnStartupModule.Add(From(func));
84 return *this;
85 }
86
87 /** Specify function to be executed on shutdown */
88 TObserveModule& OnShutdown(TFunction<void()>&& func)
89 {
90 OnShutdownModule.Add(From(func));
91 return *this;
92 }
93
94 private:
95 M* Module = nullptr;
96
97 void ObserveModule(FName const& moduleName)
98 {
99 decltype(auto) manager = FModuleManager::Get();
100 M* module = static_cast<M*>(manager.GetModule(moduleName));
101 if (!module)
102 {
103 manager.OnModulesChanged().AddLambda([this, moduleName](FName name, EModuleChangeReason changeReason)
104 {
105 if (changeReason == EModuleChangeReason::ModuleLoaded && moduleName == name)
106 ObserveModule(moduleName);
107 });
108 }
109 else
110 {
111 Module = module;
112 module->OnStartupModule.Add(OnStartupModule.Delegation());
113 module->OnShutdownModule.Add(OnShutdownModule.Delegation());
114 }
115 }
116 };
117}
virtual void ShutdownModule() override
virtual void StartupModule() override
TBelatedEventDelegate< void()> OnStartupModule
Definition Modules.h:33
TBelatedEventDelegate< void()> OnShutdownModule
Definition Modules.h:39
TInferredDelegate< Function, Captures... > From(Function func, const Captures &... captures)
const FString TTypeString
Definition TypeName.h:146
TObserveModule & OnStartup(TFunction< void()> &&func)
Definition Modules.h:81
TObserveModule(FName const &moduleName)
Definition Modules.h:63
TBelatedEventDelegate< void()> OnShutdownModule
Definition Modules.h:78
TObserveModule & OnShutdown(TFunction< void()> &&func)
Definition Modules.h:88
TBelatedEventDelegate< void()> OnStartupModule
Definition Modules.h:72