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 namespace Dali::Toolkit::ParticleSystem::Internal
25 {
26 template<>
27 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector3>::GetType()
28 {
29   return ParticleStream::StreamDataType::FLOAT3;
30 }
31
32 template<>
33 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector4>::GetType()
34 {
35   return ParticleStream::StreamDataType::FLOAT4;
36 }
37
38 template<>
39 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector2>::GetType()
40 {
41   return ParticleStream::StreamDataType::FLOAT2;
42 }
43
44 template<>
45 ParticleStream::StreamDataType StreamDataTypeWrapper<float>::GetType()
46 {
47   return ParticleStream::StreamDataType::FLOAT;
48 }
49
50 ParticleList::ParticleList(uint32_t capacity, ParticleSystem::ParticleList::ParticleStreamTypeFlags streamFlags)
51 {
52   // capacity makes for max immutable particle count
53   mMaxParticleCount = capacity;
54
55   // initialize built-in streams and build map (to optimize later)
56   if(streamFlags & ParticleStream::POSITION_STREAM_BIT)
57   {
58     AddStream(Vector3::ZERO, "aStreamPosition", false);
59     mBuiltInStreamMap[uint32_t(ParticleStream::POSITION_STREAM_BIT)] = mDataStreams.size() - 1;
60   }
61   if(streamFlags & ParticleStream::ROTATION_STREAM_BIT)
62   {
63     AddStream(Vector4::ZERO, "aStreamRotation", false);
64     mBuiltInStreamMap[uint32_t(ParticleStream::ROTATION_STREAM_BIT)] = mDataStreams.size() - 1;
65   }
66   if(streamFlags & ParticleStream::SCALE_STREAM_BIT)
67   {
68     AddStream(Vector3::ONE, "aStreamScale", false);
69     mBuiltInStreamMap[uint32_t(ParticleStream::SCALE_STREAM_BIT)] = mDataStreams.size() - 1;
70   }
71   if(streamFlags & ParticleStream::VELOCITY_STREAM_BIT)
72   {
73     AddStream(Vector3::ZERO, "aStreamVelocity", false);
74     mBuiltInStreamMap[uint32_t(ParticleStream::VELOCITY_STREAM_BIT)] = mDataStreams.size() - 1;
75   }
76   if(streamFlags & ParticleStream::COLOR_STREAM_BIT)
77   {
78     AddStream(Color::YELLOW, "aStreamColor", false);
79     mBuiltInStreamMap[uint32_t(ParticleStream::COLOR_STREAM_BIT)] = mDataStreams.size() - 1;
80   }
81   if(streamFlags & ParticleStream::OPACITY_STREAM_BIT)
82   {
83     AddStream(0.0f, "aStreamOpacity", false);
84     mBuiltInStreamMap[uint32_t(ParticleStream::OPACITY_STREAM_BIT)] = mDataStreams.size() - 1;
85   }
86   if(streamFlags & ParticleStream::LIFETIME_STREAM_BIT)
87   {
88     AddStream(0.0f, "aStreamLifetime", true);
89     mBuiltInStreamMap[uint32_t(ParticleStream::LIFETIME_STREAM_BIT)] = mDataStreams.size() - 1;
90   }
91   if(streamFlags & ParticleStream::LIFETIME_STREAM_BIT)
92   {
93     AddStream(0.0f, "aStreamLifetimeBase", true);
94     mBuiltInStreamMap[uint32_t(ParticleStream::LIFETIME_BASE_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     // Store initial lifetime
195     particle.Get<float>(ParticleStream::LIFETIME_BASE_STREAM_BIT) = lifetime;
196
197     return mParticles.back();
198   }
199   return {nullptr};
200 }
201
202 uint32_t ParticleList::GetStreamElementSize(bool includeLocalStream)
203 {
204   if(includeLocalStream)
205   {
206     return mParticleStreamElementSizeWithLocal;
207   }
208   else
209   {
210     return mParticleStreamElementSize;
211   }
212 }
213
214 void ParticleList::ReleaseParticle(uint32_t particleIndex)
215 {
216   auto it = mParticles.begin();
217   std::advance(it, particleIndex);
218
219   // Point at this slot of memory as next free slot
220   auto& p = *it;
221   if(mFreeIndex > -1)
222   {
223     mFreeChain[p.GetIndex()] = mFreeIndex;
224   }
225   mFreeIndex = p.GetIndex();
226
227   // Remove particle from the list
228   mParticles.erase(it);
229   mAliveParticleCount--;
230 }
231
232 void* ParticleList::GetDefaultStream(ParticleStreamTypeFlagBit streamBit)
233 {
234   return GetRawStream(mBuiltInStreamMap[streamBit]);
235 }
236
237 uint32_t ParticleList::GetDefaultStreamIndex(ParticleStreamTypeFlagBit streamBit)
238 {
239   return mBuiltInStreamMap[uint32_t(streamBit)];
240 }
241
242 std::list<ParticleSystem::Particle>& ParticleList::GetParticles()
243 {
244   return mParticles;
245 }
246
247 } // namespace Dali::Toolkit::ParticleSystem::Internal