Plasma Engine  2.0
Loading...
Searching...
No Matches
WorldData_inl.h
1
2namespace plInternal
3{
4 // static
5 PL_ALWAYS_INLINE WorldData::HierarchyType::Enum WorldData::GetHierarchyType(bool bIsDynamic)
6 {
7 return bIsDynamic ? HierarchyType::Dynamic : HierarchyType::Static;
8 }
9
10 // static
11 template <typename VISITOR>
12 PL_FORCE_INLINE plVisitorExecution::Enum WorldData::TraverseHierarchyLevel(Hierarchy::DataBlockArray& blocks, void* pUserData /* = nullptr*/)
13 {
14 for (WorldData::Hierarchy::DataBlock& block : blocks)
15 {
16 plGameObject::TransformationData* pCurrentData = block.m_pData;
17 plGameObject::TransformationData* pEndData = block.m_pData + block.m_uiCount;
18
19 while (pCurrentData < pEndData)
20 {
21 plVisitorExecution::Enum execution = VISITOR::Visit(pCurrentData, pUserData);
22 if (execution != plVisitorExecution::Continue)
23 return execution;
24
25 ++pCurrentData;
26 }
27 }
28
30 }
31
32 // static
33 template <typename VISITOR>
34 PL_FORCE_INLINE plVisitorExecution::Enum WorldData::TraverseHierarchyLevelMultiThreaded(
35 Hierarchy::DataBlockArray& blocks, void* pUserData /* = nullptr*/)
36 {
37 plParallelForParams parallelForParams;
38 parallelForParams.m_uiBinSize = 100;
39 parallelForParams.m_uiMaxTasksPerThread = 2;
40 parallelForParams.m_pTaskAllocator = m_StackAllocator.GetCurrentAllocator();
41
43 blocks.GetArrayPtr(),
44 [pUserData](plArrayPtr<WorldData::Hierarchy::DataBlock> blocksSlice) {
45 for (WorldData::Hierarchy::DataBlock& block : blocksSlice)
46 {
47 plGameObject::TransformationData* pCurrentData = block.m_pData;
48 plGameObject::TransformationData* pEndData = block.m_pData + block.m_uiCount;
49
50 while (pCurrentData < pEndData)
51 {
52 VISITOR::Visit(pCurrentData, pUserData);
53 ++pCurrentData;
54 }
55 }
56 },
57 "World DataBlock Traversal Task", parallelForParams);
58
60 }
61
62 // static
63 PL_FORCE_INLINE void WorldData::UpdateGlobalTransform(plGameObject::TransformationData* pData, plUInt32 uiUpdateCounter)
64 {
65 pData->UpdateGlobalTransformWithoutParent(uiUpdateCounter);
66 pData->UpdateGlobalBounds();
67 }
68
69 // static
70 PL_FORCE_INLINE void WorldData::UpdateGlobalTransformWithParent(plGameObject::TransformationData* pData, plUInt32 uiUpdateCounter)
71 {
72 pData->UpdateGlobalTransformWithParent(uiUpdateCounter);
73 pData->UpdateGlobalBounds();
74 }
75
76 // static
77 PL_FORCE_INLINE void WorldData::UpdateGlobalTransformAndSpatialData(plGameObject::TransformationData* pData, plUInt32 uiUpdateCounter, plSpatialSystem& spatialSystem)
78 {
79 pData->UpdateGlobalTransformWithoutParent(uiUpdateCounter);
80 pData->UpdateGlobalBoundsAndSpatialData(spatialSystem);
81 }
82
83 // static
84 PL_FORCE_INLINE void WorldData::UpdateGlobalTransformWithParentAndSpatialData(plGameObject::TransformationData* pData, plUInt32 uiUpdateCounter, plSpatialSystem& spatialSystem)
85 {
86 pData->UpdateGlobalTransformWithParent(uiUpdateCounter);
87 pData->UpdateGlobalBoundsAndSpatialData(spatialSystem);
88 }
89
91
92 PL_ALWAYS_INLINE const plGameObject& WorldData::ConstObjectIterator::operator*() const
93 {
94 return *m_Iterator;
95 }
96
97 PL_ALWAYS_INLINE const plGameObject* WorldData::ConstObjectIterator::operator->() const
98 {
99 return m_Iterator;
100 }
101
102 PL_ALWAYS_INLINE WorldData::ConstObjectIterator::operator const plGameObject*() const
103 {
104 return m_Iterator;
105 }
106
107 PL_ALWAYS_INLINE void WorldData::ConstObjectIterator::Next()
108 {
109 m_Iterator.Next();
110
111 while (m_Iterator.IsValid() && m_Iterator->GetHandle().IsInvalidated())
112 {
113 m_Iterator.Next();
114 }
115 }
116
117 PL_ALWAYS_INLINE bool WorldData::ConstObjectIterator::IsValid() const
118 {
119 return m_Iterator.IsValid();
120 }
121
122 PL_ALWAYS_INLINE void WorldData::ConstObjectIterator::operator++()
123 {
124 Next();
125 }
126
127 PL_ALWAYS_INLINE WorldData::ConstObjectIterator::ConstObjectIterator(ObjectStorage::ConstIterator iterator)
128 : m_Iterator(iterator)
129 {
130 while (m_Iterator.IsValid() && m_Iterator->GetHandle().IsInvalidated())
131 {
132 m_Iterator.Next();
133 }
134 }
135
137
138 PL_ALWAYS_INLINE plGameObject& WorldData::ObjectIterator::operator*()
139 {
140 return *m_Iterator;
141 }
142
143 PL_ALWAYS_INLINE plGameObject* WorldData::ObjectIterator::operator->()
144 {
145 return m_Iterator;
146 }
147
148 PL_ALWAYS_INLINE WorldData::ObjectIterator::operator plGameObject*()
149 {
150 return m_Iterator;
151 }
152
153 PL_ALWAYS_INLINE void WorldData::ObjectIterator::Next()
154 {
155 m_Iterator.Next();
156
157 while (m_Iterator.IsValid() && m_Iterator->GetHandle().IsInvalidated())
158 {
159 m_Iterator.Next();
160 }
161 }
162
163 PL_ALWAYS_INLINE bool WorldData::ObjectIterator::IsValid() const
164 {
165 return m_Iterator.IsValid();
166 }
167
169 {
170 Next();
171 }
172
173 PL_ALWAYS_INLINE WorldData::ObjectIterator::ObjectIterator(ObjectStorage::Iterator iterator)
174 : m_Iterator(iterator)
175 {
176 while (m_Iterator.IsValid() && m_Iterator->GetHandle().IsInvalidated())
177 {
178 m_Iterator.Next();
179 }
180 }
181
183
184 PL_FORCE_INLINE WorldData::InitBatch::InitBatch(plAllocator* pAllocator, plStringView sName, bool bMustFinishWithinOneFrame)
185 : m_bMustFinishWithinOneFrame(bMustFinishWithinOneFrame)
186 , m_ComponentsToInitialize(pAllocator)
187 , m_ComponentsToStartSimulation(pAllocator)
188 {
189 m_sName.Assign(sName);
190 }
191
193
194 PL_FORCE_INLINE void WorldData::RegisteredUpdateFunction::FillFromDesc(const plWorldModule::UpdateFunctionDesc& desc)
195 {
196 m_Function = desc.m_Function;
197 m_sFunctionName = desc.m_sFunctionName;
198 m_fPriority = desc.m_fPriority;
199 m_uiGranularity = desc.m_uiGranularity;
200 m_bOnlyUpdateWhenSimulating = desc.m_bOnlyUpdateWhenSimulating;
201 }
202
203 PL_FORCE_INLINE bool WorldData::RegisteredUpdateFunction::operator<(const RegisteredUpdateFunction& other) const
204 {
205 // higher priority comes first
206 if (m_fPriority != other.m_fPriority)
207 return m_fPriority > other.m_fPriority;
208
209 // sort by function name to ensure determinism
210 plInt32 iNameComp = plStringUtils::Compare(m_sFunctionName, other.m_sFunctionName);
211 PL_ASSERT_DEV(iNameComp != 0, "An update function with the same name and same priority is already registered. This breaks determinism.");
212 return iNameComp < 0;
213 }
214
216
217 PL_ALWAYS_INLINE WorldData::ReadMarker::ReadMarker(const WorldData& data)
218 : m_Data(data)
219 {
220 }
221
222 PL_FORCE_INLINE void WorldData::ReadMarker::Lock()
223 {
224 PL_ASSERT_DEV(m_Data.m_WriteThreadID == (plThreadID)0 || m_Data.m_WriteThreadID == plThreadUtils::GetCurrentThreadID(),
225 "World '{0}' cannot be marked for reading because it is already marked for writing by another thread.", m_Data.m_sName);
226 m_Data.m_iReadCounter.Increment();
227 }
228
229 PL_ALWAYS_INLINE void WorldData::ReadMarker::Unlock()
230 {
231 m_Data.m_iReadCounter.Decrement();
232 }
233
235
236 PL_ALWAYS_INLINE WorldData::WriteMarker::WriteMarker(WorldData& data)
237 : m_Data(data)
238 {
239 }
240
241 PL_FORCE_INLINE void WorldData::WriteMarker::Lock()
242 {
243 // already locked by this thread?
244 if (m_Data.m_WriteThreadID != plThreadUtils::GetCurrentThreadID())
245 {
246 PL_ASSERT_DEV(m_Data.m_iReadCounter == 0, "World '{0}' cannot be marked for writing because it is already marked for reading.", m_Data.m_sName);
247 PL_ASSERT_DEV(m_Data.m_WriteThreadID == (plThreadID)0,
248 "World '{0}' cannot be marked for writing because it is already marked for writing by another thread.", m_Data.m_sName);
249
250 m_Data.m_WriteThreadID = plThreadUtils::GetCurrentThreadID();
251 m_Data.m_iReadCounter.Increment(); // allow reading as well
252 }
253
254 m_Data.m_iWriteCounter++;
255 }
256
257 PL_FORCE_INLINE void WorldData::WriteMarker::Unlock()
258 {
259 m_Data.m_iWriteCounter--;
260
261 if (m_Data.m_iWriteCounter == 0)
262 {
263 m_Data.m_iReadCounter.Decrement();
264 m_Data.m_WriteThreadID = (plThreadID)0;
265 }
266 }
267} // namespace plInternal
Base class for all memory allocators.
Definition Allocator.h:23
This class encapsulates an array and it's size. It is recommended to use this class instead of plain ...
Definition ArrayPtr.h:37
This class represents an object inside the world.
Definition GameObject.h:32
plGameObjectHandle GetHandle() const
Returns a handle to this object.
Definition GameObject_inl.h:64
bool IsValid() const
Checks whether this iterator points to a valid object.
Definition WorldData_inl.h:163
void Next()
Advances the iterator to the next object. The iterator will not be valid anymore, if the last object ...
Definition WorldData_inl.h:153
void operator++()
Shorthand for 'Next'.
Definition WorldData_inl.h:168
Definition SpatialSystem.h:10
static plInt32 Compare(const char *pString1, const char *pString2, const char *pString1End=plUnicodeUtils::GetMaxStringEnd< char >(), const char *pString2End=plUnicodeUtils::GetMaxStringEnd< char >())
Compares two strings for equality.
Definition StringUtils.cpp:218
plStringView represent a read-only sub-string of a larger string, as it can store a dedicated string ...
Definition StringView.h:34
static void ParallelFor(plArrayPtr< ElemType > taskItems, Callback taskCallback, const char *szTaskName=nullptr, const plParallelForParams &params=plParallelForParams())
Definition ParallelFor_inl.h:73
static plThreadID GetCurrentThreadID()
Returns an identifier for the currently running thread.
Definition ThreadUtils_Posix.h:42
Settings for plTaskSystem::ParallelFor invocations.
Definition TaskSystemDeclarations.h:167
plAllocator * m_pTaskAllocator
The allocator used to for the tasks that the parallel-for uses internally. If null,...
Definition TaskSystemDeclarations.h:186
plUInt32 m_uiMaxTasksPerThread
Definition TaskSystemDeclarations.h:181
plUInt32 m_uiBinSize
Definition TaskSystemDeclarations.h:173
Enum
Definition Declarations.h:344
@ Continue
Continue regular iteration.
Definition Declarations.h:345
Description of an update function that can be registered at the world.
Definition WorldModule.h:43