UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
BlendableManager.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
6
7// used to blend IBlendableInterface object data, the member act as a header for a following data block
9{
10 // weight 0..1, 0 to disable this entry
11 float Weight;
12
13private:
14 // to ensure type safety
15 FName BlendableType;
16 // to be able to jump over data
17 uint32 DataSize;
18 // to align the data
19 uint32 PrePadding;
20
21 // @return pointer to the next object or end (can be compared with container end pointer)
22 uint8* GetDataPtr(){ check(this); return ((uint8*)(this + 1)) + PrePadding; }
23 // @return next or end of the array
24 FBlendableEntry* GetNext() { return (FBlendableEntry*)(GetDataPtr() + DataSize); }
25
26 friend class FBlendableManager;
27};
28
29// Manager class which allows blending of FBlendableBase objects, stores a copy (for the render thread)
31{
32public:
33
35 {
36 // can be increased if needed (to avoid reallocations and copies at the cost of more memory allocation)
37 Scratch.Reserve(10 * 1024);
38 }
39
40 // @param InWeight 0..1, excluding 0 as this is used to disable entries
41 // @param InData is copied with a memcpy
42 template <class T>
43 T* PushBlendableData(float InWeight, const T& InData)
44 {
45 FName BlendableType = T::GetFName();
46
47 // at least 4 byte alignment
48 uint32 Alignment = FMath::Max((uint32)4, (uint32)alignof(T));
49
50 FBlendableEntry* Entry = PushBlendableDataPtr(InWeight, BlendableType, (const uint8*)&InData, sizeof(T), Alignment);
51
52 T* Ret = (T*)Entry->GetDataPtr();
53
54 return Ret;
55 }
56
57 // used to blend multiple blendables of the given type with lerp into one final one
58 template <class T>
60 {
61 FBlendableEntry* Iterator = 0;
63
64 if(!FinalDataPtr)
65 {
66 T Base;
67 Base.SetBaseValues();
68
70 // can be optimized
72 }
73
74 return *FinalDataPtr;
75 }
76
77 // use to pickup the on final blendable that was generated by blending 0-n blendables of the given type
78 template <class T>
79 const T& GetSingleFinalDataConst() const
80 {
81 FBlendableEntry* Iterator = 0;
82 const T* FinalDataPtr = IterateBlendables<T>(Iterator);
83
84 if(!FinalDataPtr)
85 {
86 // could be improved
87 static T Base;
88 Base.SetBaseValues();
89
90 return Base;
91 }
92
93 return *FinalDataPtr;
94 }
95
96 // find next that has the given type, O(n), n is number of elements after the given one or all if started with 0
97 // @param InIterator 0 to start iteration
98 // @return 0 if no further one of that type was found
99 template <class T>
101 {
102 FName BlendableType = T::GetFName();
103
104 do
105 {
106 InIterator = GetNextBlendableEntryPtr(InIterator);
107
108 } while (InIterator && InIterator->BlendableType != BlendableType);
109
110 if (InIterator)
111 {
112 return (T*)InIterator->GetDataPtr();
113 }
114
115 return 0;
116 }
117
118private:
119
120 // stored multiple elements with a FBlendableEntry header and following data of a size specified in the header
121 TArray<uint8> Scratch;
122
123 // find next, no restriction on the type O(n), n is number of elements after the given one or all if started with 0
124 FBlendableEntry* GetNextBlendableEntryPtr(FBlendableEntry* InIterator = 0) const
125 {
126 if (!InIterator)
127 {
128 // start at the beginning
129 InIterator = (FBlendableEntry*)Scratch.GetData();
130 }
131 else
132 {
133 // go to next
134 InIterator = InIterator->GetNext();
135 }
136
137 // end reached?
138 if ((uint8*)InIterator == Scratch.GetData() + Scratch.Num())
139 {
140 // no more entries
141 return 0;
142 }
143
144 return InIterator;
145 }
146
147 // @param InWeight 0..1, excluding 0 as this is used to disable entries
148 // @param InData is copied
149 // @param InDataSize >0
150 // @return pointer to the newly added entry
151 FBlendableEntry* PushBlendableDataPtr(float InWeight, FName InBlendableType, const uint8* InData, uint32 InDataSize, uint32 Alignment)
152 {
153 check(InWeight > 0.0f && InWeight <= 1.0f);
154 check(InData);
156
157 uint32 PrePadding;
158 {
159 uint8* DataStart = Scratch.GetData() + Scratch.Num() + sizeof(FBlendableEntry);
160 PrePadding = static_cast<uint32>(Alignment - reinterpret_cast<ptrdiff_t>(DataStart) % Alignment);
161 PrePadding = (PrePadding == Alignment) ? 0 : PrePadding;
162 }
163
164 uint32 OldSize = Scratch.AddUninitialized(sizeof(FBlendableEntry) + InDataSize + PrePadding);
165
166 FBlendableEntry* Dst = (FBlendableEntry*)&Scratch[OldSize];
167
168 Dst->Weight = InWeight;
169 Dst->BlendableType = InBlendableType;
170 Dst->DataSize = InDataSize;
171 Dst->PrePadding = PrePadding;
172 memcpy(Dst->GetDataPtr(), InData, InDataSize);
173
174 return Dst;
175 }
176};
#define check(expr)
Definition AssertionMacros.h:314
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
memcpy(InputBufferBase, BinkBlocksData, BinkBlocksSize)
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition BlendableManager.h:31
FBlendableManager()
Definition BlendableManager.h:34
T * IterateBlendables(FBlendableEntry *&InIterator) const
Definition BlendableManager.h:100
T & GetSingleFinalData()
Definition BlendableManager.h:59
T * PushBlendableData(float InWeight, const T &InData)
Definition BlendableManager.h:43
const T & GetSingleFinalDataConst() const
Definition BlendableManager.h:79
Definition NameTypes.h:617
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT ElementType * GetData() UE_LIFETIMEBOUND
Definition Array.h:1027
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
Definition BlendableManager.h:9
float Weight
Definition BlendableManager.h:11