Particle System
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / particle-system / particle-list-impl.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/particle-system/particle-list-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/particle-system/particle-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/public-api/common/vector-wrapper.h>
26 #include <memory>
27
28 namespace Dali::Toolkit::ParticleSystem::Internal
29 {
30
31 template<>
32 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector3>::GetType()
33 {
34   return ParticleStream::StreamDataType::FLOAT3;
35 }
36
37 template<>
38 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector4>::GetType()
39 {
40   return ParticleStream::StreamDataType::FLOAT4;
41 }
42
43 template<>
44 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector2>::GetType()
45 {
46   return ParticleStream::StreamDataType::FLOAT2;
47 }
48
49 template<>
50 ParticleStream::StreamDataType StreamDataTypeWrapper<float>::GetType()
51 {
52   return ParticleStream::StreamDataType::FLOAT;
53 }
54
55 ParticleList::ParticleList(uint32_t capacity, ParticleSystem::ParticleList::ParticleStreamTypeFlags streamFlags)
56 {
57   // capacity makes for max immutable particle count
58   mMaxParticleCount = capacity;
59
60   // initialize built-in streams and build map (to optimize later)
61   if(streamFlags & ParticleStream::POSITION_STREAM_BIT)
62   {
63     AddStream(Vector3::ZERO, "aStreamPosition", false);
64     mBuiltInStreamMap[uint32_t(ParticleStream::POSITION_STREAM_BIT)] = mDataStreams.size() - 1;
65   }
66   if(streamFlags & ParticleStream::ROTATION_STREAM_BIT)
67   {
68     AddStream(Vector4::ZERO, "aStreamRotation", false);
69     mBuiltInStreamMap[uint32_t(ParticleStream::ROTATION_STREAM_BIT)] = mDataStreams.size() - 1;
70   }
71   if(streamFlags & ParticleStream::SCALE_STREAM_BIT)
72   {
73     AddStream(Vector3::ONE, "aStreamScale", false);
74     mBuiltInStreamMap[uint32_t(ParticleStream::SCALE_STREAM_BIT)] = mDataStreams.size() - 1;
75   }
76   if(streamFlags & ParticleStream::VELOCITY_STREAM_BIT)
77   {
78     AddStream(Vector3::ZERO, "aStreamVelocity", false);
79     mBuiltInStreamMap[uint32_t(ParticleStream::VELOCITY_STREAM_BIT)] = mDataStreams.size() - 1;
80   }
81   if(streamFlags & ParticleStream::COLOR_STREAM_BIT)
82   {
83     AddStream(Color::YELLOW, "aStreamColor", false);
84     mBuiltInStreamMap[uint32_t(ParticleStream::COLOR_STREAM_BIT)] = mDataStreams.size() - 1;
85   }
86   if(streamFlags & ParticleStream::OPACITY_STREAM_BIT)
87   {
88     AddStream(0.0f, "aStreamOpacity", false);
89     mBuiltInStreamMap[uint32_t(ParticleStream::OPACITY_STREAM_BIT)] = mDataStreams.size() - 1;
90   }
91   if(streamFlags & ParticleStream::LIFETIME_STREAM_BIT)
92   {
93     AddStream(0.0f, "aStreamLifetime", false);
94     mBuiltInStreamMap[uint32_t(ParticleStream::LIFETIME_STREAM_BIT)] = mDataStreams.size() - 1;
95   }
96
97   // create free chain
98   mFreeChain.resize(capacity);
99   for(auto i = 0u; i < mFreeChain.size(); ++i)
100   {
101     mFreeChain[i] = i + 1;
102   }
103   mFreeChain[mFreeChain.size() - 1] = 0;
104   mFreeIndex                        = 0;
105 }
106
107 ParticleList::~ParticleList() = default;
108
109 uint32_t ParticleList::AddStream(uint32_t sizeOfDataType, const void* defaultValue, ParticleStream::StreamDataType dataType, const char* streamName, bool localStream)
110 {
111   mDataStreams.emplace_back(new ParticleDataStream(mMaxParticleCount, sizeOfDataType, defaultValue, dataType));
112   if(streamName)
113   {
114     mDataStreams.back()->SetStreamName(streamName);
115   }
116
117   mDataStreams.back()->SetStreamLocal(localStream);
118
119   // Update element size
120   mParticleStreamElementSize          = 0;
121   mParticleStreamElementSizeWithLocal = 0;
122   for(auto& ds : mDataStreams)
123   {
124     if(!ds->localStream)
125     {
126       mParticleStreamElementSize += ds->dataSize;
127     }
128     mParticleStreamElementSizeWithLocal += ds->dataSize;
129   }
130
131   return mDataStreams.size() - 1;
132 }
133
134 void* ParticleList::GetRawStream(uint32_t index)
135 {
136   if(index < mDataStreams.size() && mDataStreams[index])
137   {
138     return mDataStreams[index]->data.data();
139   }
140   return nullptr;
141 }
142
143 uint32_t ParticleList::GetStreamCount() const
144 {
145   return mDataStreams.size();
146 }
147
148 uint32_t ParticleList::GetParticleCount() const
149 {
150   return mMaxParticleCount;
151 }
152
153 uint32_t ParticleList::GetActiveParticleCount() const
154 {
155   return mParticles.size();
156 }
157
158 ParticleStream::StreamDataType ParticleList::GetStreamDataType(uint32_t streamIndex)
159 {
160   return mDataStreams[streamIndex]->type;
161 }
162
163 const std::string& ParticleList::GetStreamName(uint32_t streamIndex) const
164 {
165   return mDataStreams[streamIndex]->streamName;
166 }
167
168 bool ParticleList::IsStreamLocal(uint32_t streamIndex) const
169 {
170   return mDataStreams[streamIndex]->localStream;
171 }
172
173 uint32_t ParticleList::GetStreamDataTypeSize(uint32_t streamIndex) const
174 {
175   return mDataStreams[streamIndex]->dataSize;
176 }
177
178 ParticleSystem::Particle ParticleList::NewParticle(float lifetime)
179 {
180   if(mParticles.size() < mMaxParticleCount)
181   {
182     auto newIndex = int32_t(mFreeIndex);
183     mFreeIndex    = int32_t(mFreeChain[mFreeIndex]);
184     mAliveParticleCount++;
185
186     // Add particle
187     mParticles.emplace_back(new Internal::Particle(*this, newIndex));
188
189     // Set particle lifetime
190     auto& particle = mParticles.back();
191
192     particle.Get<float>(ParticleStream::LIFETIME_STREAM_BIT) = lifetime;
193
194     return mParticles.back();
195   }
196   return {nullptr};
197 }
198
199 uint32_t ParticleList::GetStreamElementSize(bool includeLocalStream)
200 {
201   if(includeLocalStream)
202   {
203     return mParticleStreamElementSizeWithLocal;
204   }
205   else
206   {
207     return mParticleStreamElementSize;
208   }
209 }
210
211 void ParticleList::ReleaseParticle(uint32_t particleIndex)
212 {
213   auto it = mParticles.begin();
214   std::advance(it, particleIndex);
215
216   // Point at this slot of memory as next free slot
217   auto& p = *it;
218   if(mFreeIndex)
219   {
220     mFreeChain[p.GetIndex()] = mFreeIndex;
221     mFreeIndex               = p.GetIndex();
222   }
223
224   // Remove particle from the list
225   mParticles.erase(it);
226   mAliveParticleCount--;
227 }
228
229 void* ParticleList::GetDefaultStream(ParticleStreamTypeFlagBit streamBit)
230 {
231   return GetRawStream(mBuiltInStreamMap[streamBit]);
232 }
233
234 uint32_t ParticleList::GetDefaultStreamIndex(ParticleStreamTypeFlagBit streamBit)
235 {
236   return mBuiltInStreamMap[uint32_t(streamBit)];
237 }
238
239 std::list<ParticleSystem::Particle>& ParticleList::GetParticles()
240 {
241   return mParticles;
242 }
243
244 } // namespace Dali::Toolkit::ParticleSystem::Internal