MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
Init.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
14#include "CoreMinimal.h"
15#include "Mcro/FunctionTraits.h"
16
18{
19 using namespace Mcro::FunctionTraits;
20
21 template <typename T, typename... Args>
22 concept CUObjectInitializable = CUObject<T> && requires(T* t, Args... args)
23 {
24 t->Initialize(args...);
25 };
26
27 /** Mirror of FStaticConstructObjectParameters but it's POCO and doesn't have a constructor */
29 {
30 /** The object to create this object within (the Outer property for the new object will be set to the value specified here). */
31 UObject* Outer = (UObject*)GetTransientPackage();
32
33 /** The class of the object to create */
34 const UClass* Class;
35
36 /** The name to give the new object.If no value(NAME_None) is specified, the object will be given a unique name in the form of ClassName_#. */
37 FName Name = NAME_None;
38
39 /** The ObjectFlags to assign to the new object. some flags can affect the behavior of constructing the object. */
40 EObjectFlags Flags = RF_NoFlags;
41
42 /** The InternalObjectFlags to assign to the new object. some flags can affect the behavior of constructing the object. */
43 EInternalObjectFlags InternalSetFlags = EInternalObjectFlags::None;
44
45 /** If true, copy transient from the class defaults instead of the pass in archetype ptr(often these are the same) */
46 bool bCopyTransientsFromClassDefaults = false;
47
48 /** If true, Template is guaranteed to be an archetype */
49 bool bAssumeTemplateIsArchetype = false;
50
51 /**
52 * If specified, the property values from this object will be copied to the new object, and the new object's ObjectArchetype value will be set to this object.
53 * If nullptr, the class default object is used instead.
54 */
55 UObject* Template = nullptr;
56
57 /** Contains the mappings of instanced objects and components to their templates */
58 FObjectInstancingGraph* InstanceGraph = nullptr;
59
60 /** Assign an external Package to the created object if non-null */
61 UPackage* ExternalPackage = nullptr;
62
63 /** Callback for custom code to initialize properties before PostInitProperties runs */
64 TFunction<void()> PropertyInitCallback;
65 };
66
67 namespace Detail
68 {
69 template <CUObject T, typename... Args>
70 void InitObject(T* object, Args&&... args) {}
71
72 template <CUObject T, typename... Args>
73 requires CUObjectInitializable<T, Args...>
74 void InitObject(T* object, Args&&... args)
75 {
76 object->Initialize(Forward<Args>(args)...);
77 }
78 }
79
80 /**
81 * Create a new object which can also be initialized with an Initialize function if it has one.
82 * In case it has an Initialize function the `args` parameters should match them. This is an equivalent to
83 * the template `Mcro::SharedObjects::MakeShareableInit`
84 *
85 * @tparam T Type of initializable UObject
86 * @tparam Args Arguments for the Initialize function
87 * @param params Parameters for every new object
88 * @param args Arguments for the Initialize function
89 * @return The new object
90 */
91 template <CUObject T, typename... Args>
92 T* NewInit(FConstructObjectParameters&& params, Args&&... args)
93 {
94 T* result = NewObject<T>(
95 params.Outer,
96 params.Class,
97 params.Name,
98 params.Flags,
99 params.Template,
100 params.bCopyTransientsFromClassDefaults,
101 params.InstanceGraph,
102 params.ExternalPackage
103 );
104 Detail::InitObject(result, Forward<Args>(args)...);
105 return result;
106 }
107
108 /**
109 * Equivalent to `Mcro::Construct::Construct` but for UObjects.
110 * Usage:
111 *
112 * @code
113 * using namespace Mcro::UObjects::Init;
114 *
115 * auto myObject = Construct({}, [](UMyObject& _)
116 * {
117 * _.Foo = 42;
118 * _.Bar();
119 * // etc...
120 * });
121 * static_assert(std::is_same_v<decltype(myObject), UMyObject*>);
122 * @endcode
123 *
124 * Notice how the object type is deduced from the argument of the initializer.
125 *
126 * @tparam Initializer Initializer function type
127 * @param params Parameters for every new object
128 * @param init A setup function for the newly created UObject
129 * @return The new object
130 */
131 template <
132 CFunctorObject Initializer,
133 typename TArg = TFunction_Arg<Initializer, 0>,
134 CUObject T = std::decay_t<TArg>
135 >
136 requires std::is_lvalue_reference_v<TArg>
137 T* Construct(FConstructObjectParameters&& params, Initializer&& init)
138 {
139 T* result = NewObject<T>(
140 params.Outer,
141 params.Class,
142 params.Name,
143 params.Flags,
144 params.Template,
145 params.bCopyTransientsFromClassDefaults,
146 params.InstanceGraph,
147 params.ExternalPackage
148 );
149 init(*result);
150 return result;
151 }
152
153 /**
154 * Equivalent to `Mcro::Construct::Construct` but for UObjects. If the constructed UObject type also has an
155 * `Initialize` function call that too after the lambda initializer. The `args` parameters should match the
156 * signature of `Initialize` in that case.
157 * Usage:
158 *
159 * @code
160 * using namespace Mcro::UObjects::Init;
161 *
162 * auto myObject = Construct({}, [](UMyObject& _)
163 * {
164 * _.Foo = 42;
165 * _.Bar();
166 * // etc...
167 * });
168 * static_assert(std::is_same_v<decltype(myObject), UMyObject*>);
169 * @endcode
170 *
171 * Notice how the object type is deduced from the argument of the initializer.
172 *
173 * @tparam Initializer Initializer function type
174 * @tparam Args Arguments for the Initialize function
175 * @param params Parameters for every new object
176 * @param init A setup function for the newly created UObject
177 * @param args Arguments for the Initialize function
178 * @return The new object
179 */
180 template <
181 CFunctorObject Initializer,
182 typename... Args,
183 typename TArg = TFunction_Arg<Initializer, 0>,
184 CUObject T = std::decay_t<TArg>
185 >
186 requires std::is_lvalue_reference_v<TArg>
187 T* ConstructInit(FConstructObjectParameters&& params, Initializer&& init, Args&&... args)
188 {
189 T* result = NewObject<T>(
190 params.Outer,
191 params.Class,
192 params.Name,
193 params.Flags,
194 params.Template,
195 params.bCopyTransientsFromClassDefaults,
196 params.InstanceGraph,
197 params.ExternalPackage
198 );
199 init(*result);
200 Detail::InitObject(result, Forward<Args>(args)...);
201 return result;
202 }
203}
typename TFunctionTraits< std::decay_t< T > >::template Arg< I > TFunction_Arg
void InitObject(T *object, Args &&... args)
Definition Init.h:70
T * ConstructInit(FConstructObjectParameters &&params, Initializer &&init, Args &&... args)
Definition Init.h:187
T * NewInit(FConstructObjectParameters &&params, Args &&... args)
Definition Init.h:92