Karma Engine
Loading...
Searching...
No Matches
KarmaUtilities.h
1#pragma once
2
3#include "krpch.h"
4#include "SubClassOf.h"
5#include "Actor.h"
6#include "stb_image.h"
7#include "Level.h"
8#include "World.h"
9#include "WorldSettings.h"
10
11namespace Karma
12{
13 class UObject;
14 class AActor;
15 class UClass;
16
17 class KARMA_API KarmaUtilities
18 {
19 public:
20 static std::string ReadFileToSpitString(const std::string& filePath);
21 static std::string GetFilePath(const std::string& str);
22 static unsigned char* GetImagePixelData(char const* fileName, int* width, int* height, int* channels, int req_comp);
23 };
24
31 {
32 public:
35
38
40 int32_t m_Index;
41
44
47
50
53
56
58 //FDelegateHandle ActorSpawnedDelegateHandle;
59
61
65 FActorIteratorState(const UWorld* InWorld, const TSubclassOf<AActor> InClass) :
66 m_CurrentWorld(InWorld),
67 m_Index(-1),
68 m_ReachedEnd(false),
70 m_CurrentActor(nullptr),
71 m_DesiredClass(InClass)
72 {
73 //check(IsInGameThread());
74 KR_CORE_ASSERT(m_CurrentWorld, "");
75
76 #if WITH_EDITOR
77 // In the editor, you are more likely to have many worlds in memory at once.
78 // As an optimization to avoid iterating over many actors that are not in the world we are asking for,
79 // if the filter class is AActor, just use the actors that are in the world you asked for.
80 // This could be useful in runtime code as well if there are many worlds in memory, but for now we will leave
81 // it in editor code.
82 if (InClass == AActor::StaticClass())
83 {
84 // First determine the number of actors in the world to reduce reallocations when we append them to the array below.
85 int32 NumActors = 0;
86 for (ULevel* Level : InWorld->GetLevels())
87 {
88 if (Level)
89 {
90 NumActors += Level->Actors.Num();
91 }
92 }
93
94
95 // Presize the array
96 ObjectArray.Reserve(NumActors);
97
98
99 // Fill the array
100 for (ULevel* Level : InWorld->GetLevels())
101 {
102 if (Level)
103 {
104 ObjectArray.Append(Level->Actors);
105 }
106 }
107 }
108 else
109 #endif // WITH_EDITOR
110 {
111 constexpr EObjectFlags ExcludeFlags = RF_ClassDefaultObject;
112 GetObjectsOfClass(InClass, m_ObjectArray, true, ExcludeFlags, EInternalObjectFlags::Garbage);
113 }
114
115
116 // const auto ActorSpawnedDelegate = FOnActorSpawned::FDelegate::CreateRaw(this, &FActorIteratorState::OnActorSpawned);
117 // m_ActorSpawnedDelegateHandle = m_CurrentWorld->AddOnActorSpawnedHandler(ActorSpawnedDelegate);
118 }
119
120
122 {
123 //m_CurrentWorld->RemoveOnActorSpawnedHandler(ActorSpawnedDelegateHandle);
124 }
125
126
132 FORCEINLINE AActor* GetActorChecked() const
133 {
134 KR_CORE_ASSERT(m_CurrentActor, "");
135 KR_CORE_ASSERT(!m_CurrentActor->IsUnreachable(), "");
136
137 return m_CurrentActor;
138 }
139
140 private:
141 /*
142 void OnActorSpawned(AActor* InActor)
143 {
144 if (InActor->IsA(DesiredClass))
145 {
146 SpawnedActorArray.AddUnique(InActor);
147 }
148 }*/
149 };
150
152 enum EActorIteratorFlags
153 {
154 AllActors = 0x00000000, // No flags, iterate all actors
155 SkipPendingKill = 0x00000001, // Skip pending kill actors
156 OnlySelectedActors = 0x00000002, // Only iterate actors that are selected
157 OnlyActiveLevels = 0x00000004, // Only iterate active levels
158 };
159
161 enum class EActorIteratorType
162 {
163 End
164 };
165
169 template <typename Derived>
171 {
172 private:
173 EActorIteratorFlags m_Flags;
174
175 // smart pointer?
176 std::shared_ptr<FActorIteratorState> m_State;
177
178 protected:
182 TActorIteratorBase(EActorIteratorType)
183 : m_Flags(EActorIteratorFlags::AllActors)
184 {
185 }
186
187 TActorIteratorBase(const UWorld* InWorld, TSubclassOf<AActor> InClass, const EActorIteratorFlags InFlags)
188 : m_Flags(InFlags)
189 {
190 m_State.reset(new FActorIteratorState(InWorld, InClass));
191 }
192
193 public:
198 {
199 // Use local version to avoid LHSs as compiler is not required to write out member variables to memory.
200 AActor* localCurrentActor = nullptr;
201 int32_t localIndex = m_State->m_Index;
202 KarmaVector<UObject*>& localObjectArray = m_State->m_ObjectArray;
203 KarmaVector<AActor*>& localSpawnedActorArray = m_State->m_SpawnedActorArray;
204 const UWorld* localCurrentWorld = m_State->m_CurrentWorld;
205
206 int32_t lObjectArrayNum = int32_t(localObjectArray.Num());
207 int32_t lSAArrayNum = int32_t(localSpawnedActorArray.Num());
208
209 while (++localIndex < (lObjectArrayNum + lSAArrayNum))
210 {
211 if (localIndex < lObjectArrayNum)
212 {
213 localCurrentActor = static_cast<AActor*>(localObjectArray.GetElements()[localIndex]);
214 }
215 else
216 {
217 localCurrentActor = localSpawnedActorArray.GetElements()[localIndex - lObjectArrayNum];
218 }
219 m_State->m_ConsideredCount++;
220
221 ULevel* actorLevel = localCurrentActor ? localCurrentActor->GetLevel() : nullptr;
222
223 if (actorLevel
224 && static_cast<const Derived*>(this)->IsActorSuitable(localCurrentActor)
225 && static_cast<const Derived*>(this)->CanIterateLevel(actorLevel)
226 && actorLevel->GetWorld() == localCurrentWorld)
227 {
228 // ignore non-persistent world settings
229 if (actorLevel == localCurrentWorld->GetPersistentLevel() || !localCurrentActor->IsA(AWorldSettings::StaticClass()))
230 {
231 m_State->m_CurrentActor = localCurrentActor;
232 m_State->m_Index = localIndex;
233 return;
234 }
235 }
236 }
237 m_State->m_CurrentActor = nullptr;
238 m_State->m_ReachedEnd = true;
239 }
240
246 FORCEINLINE AActor* operator*() const
247 {
248 return m_State->GetActorChecked();
249 }
250
256 FORCEINLINE AActor* operator->() const
257 {
258 return m_State->GetActorChecked();
259 }
266 FORCEINLINE explicit operator bool() const
267 {
268 return !m_State->m_ReachedEnd;
269 }
270
275 {
276 KR_CORE_ASSERT(!m_State->m_ReachedEnd, "");
277 m_State->m_CurrentWorld->RemoveActor(m_State->m_CurrentActor, true);
278 }
279
287 {
288 return m_State->m_ConsideredCount;
289 }
290
298 FORCEINLINE bool CanIterateLevel(const ULevel* Level) const
299 {
300 /*
301 if (EnumHasAnyFlags(Flags, EActorIteratorFlags::OnlyActiveLevels))
302 {
303 const bool bIsLevelVisibleOrAssociating = (Level->bIsVisible && !Level->bIsBeingRemoved) || Level->bIsAssociatingLevel || Level->bIsDisassociatingLevel;
304
305 // Only allow iteration of Level if it's in the currently active level collection of the world, or is a static level.
306 const FLevelCollection* const ActorLevelCollection = Level->GetCachedLevelCollection();
307 const FLevelCollection* const ActiveLevelCollection = Level->OwningWorld ? Level->OwningWorld->GetActiveLevelCollection() : nullptr;
308
309 // If the world's active level collection is null, we can't apply any meaningful filter,
310 // so just allow iteration in this case.
311 const bool bIsCurrentLevelCollectionTicking = !ActiveLevelCollection || (ActorLevelCollection == ActiveLevelCollection);
312
313 const bool bIsLevelCollectionNullOrStatic = !ActorLevelCollection || ActorLevelCollection->GetType() == ELevelCollectionType::StaticLevels;
314 const bool bShouldIterateLevelCollection = bIsCurrentLevelCollectionTicking || bIsLevelCollectionNullOrStatic;
315
316 return bIsLevelVisibleOrAssociating && bShouldIterateLevelCollection;
317 }*/
318
319 return true;
320 }
321
329 FORCEINLINE bool IsActorSuitable(const AActor* Actor) const
330 {
331 if (EnumHasAnyFlags(m_Flags, EActorIteratorFlags::SkipPendingKill) && !IsValid(Actor))
332 {
333 return false;
334 }
335
336 if (EnumHasAnyFlags(m_Flags, EActorIteratorFlags::OnlySelectedActors) && !Actor->IsSelected())
337 {
338 return false;
339 }
340
341 return true;
342 }
343 };
344}
FORCEINLINE bool IsValid(const UObject *Test)
Test validity of object.
Definition Object.h:232
Karma's std::vector wrapper.
Definition KarmaTypes.h:128
Definition Actor.h:22
ULevel * GetLevel() const
Definition Actor.cpp:18
Definition KarmaUtilities.h:31
FActorIteratorState(const UWorld *InWorld, const TSubclassOf< AActor > InClass)
Definition KarmaUtilities.h:65
UClass * m_DesiredClass
Definition KarmaUtilities.h:55
FActorIteratorState()
Definition KarmaUtilities.h:60
KarmaVector< UObject * > m_ObjectArray
Definition KarmaUtilities.h:37
bool m_ReachedEnd
Definition KarmaUtilities.h:43
const UWorld * m_CurrentWorld
Definition KarmaUtilities.h:34
KarmaVector< AActor * > m_SpawnedActorArray
Definition KarmaUtilities.h:52
FORCEINLINE AActor * GetActorChecked() const
Definition KarmaUtilities.h:132
int32_t m_Index
Definition KarmaUtilities.h:40
int32_t m_ConsideredCount
Definition KarmaUtilities.h:46
AActor * m_CurrentActor
Definition KarmaUtilities.h:49
Definition KarmaUtilities.h:18
Definition KarmaUtilities.h:171
FORCEINLINE AActor * operator->() const
Definition KarmaUtilities.h:256
void operator++()
Definition KarmaUtilities.h:197
FORCEINLINE bool CanIterateLevel(const ULevel *Level) const
Definition KarmaUtilities.h:298
FORCEINLINE bool IsActorSuitable(const AActor *Actor) const
Definition KarmaUtilities.h:329
FORCEINLINE AActor * operator*() const
Definition KarmaUtilities.h:246
TActorIteratorBase(EActorIteratorType)
Definition KarmaUtilities.h:182
void ClearCurrent()
Definition KarmaUtilities.h:274
int32 GetProgressNumerator() const
Definition KarmaUtilities.h:286
Definition SubClassOf.h:64
Definition Class.h:99
Definition Level.h:21
virtual UWorld * GetWorld() const override final
Returns what UWorld this object is contained within.
Definition Level.cpp:17
bool IsUnreachable() const
Definition UObjectBase.cpp:110
FORCEINLINE bool IsA(OtherClassType SomeBase) const
Definition UObjectBase.h:187
bool IsSelected() const
Test the selection state of a UObject.
Definition Object.cpp:181
Definition World.h:108