A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
BucketUpdateSubsystem.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
4
5 bool UBucketUpdateSubsystem::AddObjectToBucket(int32 UpdateHTZ, UObject* InObject, FName FunctionName)
6 {
7 if (!InObject || UpdateHTZ < 1)
8 return false;
9
10 return BucketContainer.AddBucketObject(UpdateHTZ, InObject, FunctionName);
11 }
12
13 bool UBucketUpdateSubsystem::K2_AddObjectToBucket(int32 UpdateHTZ, UObject* InObject, FName FunctionName)
14 {
15 if (!InObject || UpdateHTZ < 1)
16 return false;
17
18 return BucketContainer.AddBucketObject(UpdateHTZ, InObject, FunctionName);
19 }
20
21
22 bool UBucketUpdateSubsystem::K2_AddObjectEventToBucket(FDynamicBucketUpdateTickSignature Delegate, int32 UpdateHTZ)
23 {
24 if (!Delegate.IsBound())
25 return false;
26
27 return BucketContainer.AddBucketObject(UpdateHTZ, Delegate);
28 }
29
31 {
32 if (!InObject)
33 return false;
34
35 return BucketContainer.RemoveBucketObject(InObject, FunctionName);
36 }
37
38 bool UBucketUpdateSubsystem::RemoveObjectFromBucketByEvent(FDynamicBucketUpdateTickSignature Delegate)
39 {
40 if (!Delegate.IsBound())
41 return false;
42
43 return BucketContainer.RemoveBucketObject(Delegate);
44 }
45
47 {
48 if (!InObject)
49 return false;
50
52 }
53
55 {
56 if (!InObject)
57 return false;
58
59 return BucketContainer.IsObjectFunctionInBucket(InObject, FunctionName);
60 }
61
66
67 void UBucketUpdateSubsystem::Tick(float DeltaTime)
68 {
70 }
71
76
78 {
79 return GetWorld();
80 }
81
83 {
84 return false;
85 }
86
88 {
89 return false;
90 }
91
93 {
94 if (IsTemplate(RF_ClassDefaultObject))
95 return ETickableTickType::Never;
96
97 return ETickableTickType::Conditional;
98 }
99
101 {
102 RETURN_QUICK_DECLARE_CYCLE_STAT(UVRGripScriptBase, STATGROUP_Tickables);
103 }
104
106 {
107 if (NativeCallback.IsBound())
108 {
109 return NativeCallback.Execute();
110 }
111 else if (DynamicCallback.IsBound())
112 {
113 DynamicCallback.Execute();
114 return true;
115 }
116
117 return false;
118 }
119
121 {
122 return (NativeCallback.IsBoundToObject(Obj) && FunctionName == FuncName);
123 }
124
125 bool FUpdateBucketDrop::IsBoundToObjectDelegate(FDynamicBucketUpdateTickSignature & DynEvent)
126 {
127 return DynamicCallback == DynEvent;
128 }
129
131 {
132 return (NativeCallback.IsBoundToObject(Obj) || DynamicCallback.IsBoundToObject(Obj));
133 }
134
139
140 FUpdateBucketDrop::FUpdateBucketDrop(FDynamicBucketUpdateTickSignature & DynCallback)
141 {
142 DynamicCallback = DynCallback;
143 }
144
146 {
147 if (Obj && Obj->FindFunction(FuncName))
148 {
149 FunctionName = FuncName;
150 NativeCallback.BindUFunction(Obj, FunctionName);
151 }
152 else
153 {
154 FunctionName = NAME_None;
155 }
156 }
157
158 bool FUpdateBucket::Update(float DeltaTime)
159 {
160 //#TODO: Need to consider batching / spreading out load if there are a lot of updating objects in the bucket
161 if (Callbacks.Num() < 1)
162 return false;
163
164 // Check for if this bucket is ready to fire events
165 nUpdateCount += DeltaTime;
167 {
168 nUpdateCount = 0.0f;
169 for (int i = Callbacks.Num() - 1; i >= 0; --i)
170 {
171 if (Callbacks[i].ExecuteBoundCallback())
172 {
173 // If this returns true then we keep it in the queue
174 continue;
175 }
176
177 // Remove the callback, it is complete or invalid
178 Callbacks.RemoveAt(i);
179 }
180 }
181
182 return Callbacks.Num() > 0;
183 }
184
186 {
187 TArray<uint32> BucketsToRemove;
188 for(auto& Bucket : ReplicationBuckets)
189 {
190 if (!Bucket.Value.Update(DeltaTime))
191 {
192 // Add Bucket to list to remove at end of update
193 BucketsToRemove.Add(Bucket.Key);
194 }
195 }
196
197 // Remove unused buckets so that they don't get ticked
198 for (const uint32 Key : BucketsToRemove)
199 {
200 ReplicationBuckets.Remove(Key);
201 }
202
203 if (ReplicationBuckets.Num() < 1)
204 bNeedsUpdate = false;
205 }
206
207 bool FUpdateBucketContainer::AddBucketObject(uint32 UpdateHTZ, UObject* InObject, FName FunctionName)
208 {
209 if (!InObject || InObject->FindFunction(FunctionName) == nullptr || UpdateHTZ < 1)
210 return false;
211
212 // First verify that this object isn't already contained in a bucket, if it is then erase it so that we can replace it below
213 RemoveBucketObject(InObject, FunctionName);
214
215 if (ReplicationBuckets.Contains(UpdateHTZ))
216 {
217 ReplicationBuckets[UpdateHTZ].Callbacks.Add(FUpdateBucketDrop(InObject, FunctionName));
218 }
219 else
220 {
221 FUpdateBucket & newBucket = ReplicationBuckets.Add(UpdateHTZ, FUpdateBucket(UpdateHTZ));
222 ReplicationBuckets[UpdateHTZ].Callbacks.Add(FUpdateBucketDrop(InObject, FunctionName));
223 }
224
225 if (ReplicationBuckets.Num() > 0)
226 bNeedsUpdate = true;
227
228 return true;
229 }
230
231
232 bool FUpdateBucketContainer::AddBucketObject(uint32 UpdateHTZ, FDynamicBucketUpdateTickSignature &Delegate)
233 {
234 if (!Delegate.IsBound() || UpdateHTZ < 1)
235 return false;
236
237 // First verify that this object isn't already contained in a bucket, if it is then erase it so that we can replace it below
238 RemoveBucketObject(Delegate);
239
240 if (ReplicationBuckets.Contains(UpdateHTZ))
241 {
242 ReplicationBuckets[UpdateHTZ].Callbacks.Add(FUpdateBucketDrop(Delegate));
243 }
244 else
245 {
246 FUpdateBucket & newBucket = ReplicationBuckets.Add(UpdateHTZ, FUpdateBucket(UpdateHTZ));
247 ReplicationBuckets[UpdateHTZ].Callbacks.Add(FUpdateBucketDrop(Delegate));
248 }
249
250 if (ReplicationBuckets.Num() > 0)
251 bNeedsUpdate = true;
252
253 return true;
254 }
255
256 bool FUpdateBucketContainer::RemoveBucketObject(UObject * ObjectToRemove, FName FunctionName)
257 {
258 if (!ObjectToRemove || ObjectToRemove->FindFunction(FunctionName) == nullptr)
259 return false;
260
261 // Store if we ended up removing it
262 bool bRemovedObject = false;
263
264 TArray<uint32> BucketsToRemove;
265 for (auto& Bucket : ReplicationBuckets)
266 {
267 for (int i = Bucket.Value.Callbacks.Num() - 1; i >= 0; --i)
268 {
269 if (Bucket.Value.Callbacks[i].IsBoundToObjectFunction(ObjectToRemove, FunctionName))
270 {
271 Bucket.Value.Callbacks.RemoveAt(i);
272 bRemovedObject = true;
273
274 // Leave the loop, this is called in add as well so we should never get duplicate entries
275 break;
276 }
277 }
278
279 if (bRemovedObject)
280 {
281 break;
282 }
283 }
284
285 return bRemovedObject;
286 }
287
288 bool FUpdateBucketContainer::RemoveBucketObject(FDynamicBucketUpdateTickSignature &DynEvent)
289 {
290 if (!DynEvent.IsBound())
291 return false;
292
293 // Store if we ended up removing it
294 bool bRemovedObject = false;
295
296 TArray<uint32> BucketsToRemove;
297 for (auto& Bucket : ReplicationBuckets)
298 {
299 for (int i = Bucket.Value.Callbacks.Num() - 1; i >= 0; --i)
300 {
301 if (Bucket.Value.Callbacks[i].IsBoundToObjectDelegate(DynEvent))
302 {
303 Bucket.Value.Callbacks.RemoveAt(i);
304 bRemovedObject = true;
305
306 // Leave the loop, this is called in add as well so we should never get duplicate entries
307 break;
308 }
309 }
310
311 if (bRemovedObject)
312 {
313 break;
314 }
315 }
316
317 return bRemovedObject;
318 }
319
321 {
322 if (!ObjectToRemove)
323 return false;
324
325 // Store if we ended up removing it
326 bool bRemovedObject = false;
327
328 TArray<uint32> BucketsToRemove;
329 for (auto& Bucket : ReplicationBuckets)
330 {
331 for (int i = Bucket.Value.Callbacks.Num() - 1; i >= 0; --i)
332 {
333 if (Bucket.Value.Callbacks[i].IsBoundToObject(ObjectToRemove))
334 {
335 Bucket.Value.Callbacks.RemoveAt(i);
336 bRemovedObject = true;
337 }
338 }
339 }
340
341 return bRemovedObject;
342 }
343
345 {
346 if (!ObjectToRemove)
347 return false;
348 for (auto& Bucket : ReplicationBuckets)
349 {
350 for (int i = Bucket.Value.Callbacks.Num() - 1; i >= 0; --i)
351 {
352 if (Bucket.Value.Callbacks[i].IsBoundToObject(ObjectToRemove))
353 {
354 return true;
355 }
356 }
357 }
358
359 return false;
360 }
361
362 bool FUpdateBucketContainer::IsObjectFunctionInBucket(UObject * ObjectToRemove, FName FunctionName)
363 {
364 if (!ObjectToRemove)
365 return false;
366 for (auto& Bucket : ReplicationBuckets)
367 {
368 for (int i = Bucket.Value.Callbacks.Num() - 1; i >= 0; --i)
369 {
370 if (Bucket.Value.Callbacks[i].IsBoundToObjectFunction(ObjectToRemove, FunctionName))
371 {
372 return true;
373 }
374 }
375 }
376
377 return false;
378 }
379
380 bool FUpdateBucketContainer::IsObjectDelegateInBucket(FDynamicBucketUpdateTickSignature &DynEvent)
381 {
382 if (!DynEvent.IsBound())
383 return false;
384
385 for (auto& Bucket : ReplicationBuckets)
386 {
387 for (int i = Bucket.Value.Callbacks.Num() - 1; i >= 0; --i)
388 {
389 if (Bucket.Value.Callbacks[i].IsBoundToObjectDelegate(DynEvent))
390 {
391 return true;
392 }
393 }
394 }
395
396 return false;
397 }
bool RemoveObjectFromBucketByEvent(UPARAM(DisplayName="Event") FDynamicBucketUpdateTickSignature Delegate)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Remove Object From Bucket Updates By Event",...
virtual ETickableTickType GetTickableTickType() const
bool IsObjectFunctionInBucket(UObject *InObject=nullptr, FName FunctionName=NAME_None)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Is Object In Bucket", ScriptName = "IsObjectInBuc...
virtual bool IsTickableWhenPaused() const override
bool RemoveObjectFromAllBuckets(UObject *InObject=nullptr)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Remove Object From All Bucket Updates",...
bool IsActive()
UFUNCTION(BlueprintPure, Category = "BucketUpdateSubsystem")
virtual UWorld * GetTickableGameObjectWorld() const override
virtual bool IsTickableInEditor() const
bool AddObjectToBucket(int32 UpdateHTZ, UObject *InObject, FName FunctionName)
virtual bool IsTickable() const override
bool RemoveObjectFromBucketByFunctionName(UObject *InObject=nullptr, FName FunctionName=NAME_None)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Remove Object From Bucket Updates By Function",...
bool K2_AddObjectEventToBucket(UPARAM(DisplayName="Event") FDynamicBucketUpdateTickSignature Delegate, int32 UpdateHTZ=100)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Object to Bucket Updates by Event",...
bool K2_AddObjectToBucket(int32 UpdateHTZ=100, UObject *InObject=nullptr, FName FunctionName=NAME_None)
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Object to Bucket Updates",...
FUpdateBucketContainer BucketContainer
virtual void Tick(float DeltaTime) override
virtual TStatId GetStatId() const override
UCLASS(NotBlueprintable, BlueprintType, EditInlineNew, DefaultToInstanced, Abstract,...
bool IsObjectInBucket(UObject *ObjectToRemove)
void UpdateBuckets(float DeltaTime)
TMap< uint32, FUpdateBucket > ReplicationBuckets
bool RemoveObjectFromAllBuckets(UObject *ObjectToRemove)
bool IsObjectFunctionInBucket(UObject *ObjectToRemove, FName FunctionName)
bool RemoveBucketObject(UObject *ObjectToRemove, FName FunctionName)
bool AddBucketObject(uint32 UpdateHTZ, UObject *InObject, FName FunctionName)
bool IsObjectDelegateInBucket(FDynamicBucketUpdateTickSignature &DynEvent)
bool IsBoundToObjectDelegate(FDynamicBucketUpdateTickSignature &DynEvent)
FDynamicBucketUpdateTickSignature DynamicCallback
bool IsBoundToObjectFunction(UObject *Obj, FName &FuncName)
FBucketUpdateTickSignature NativeCallback
bool IsBoundToObject(UObject *Obj)
bool Update(float DeltaTime)
TArray< FUpdateBucketDrop > Callbacks