[dali_2.3.21] Merge branch 'devel/master'
[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     AddStream(0.0f, "aStreamLifetimeBase", true);
91     mBuiltInStreamMap[uint32_t(ParticleStream::LIFETIME_BASE_STREAM_BIT)] = mDataStreams.size() - 1;
92   }
93
94   // create free chain
95   mFreeChain.resize(capacity);
96   for(auto i = 0u; i < mFreeChain.size(); ++i)
97   {
98     mFreeChain[i] = i + 1;
99   }
100   mFreeChain[mFreeChain.size() - 1] = 0;
101   mFreeIndex                        = 0;
102 }
103
104 ParticleList::~ParticleList() = default;
105
106 uint32_t ParticleList::AddStream(uint32_t sizeOfDataType, const void* defaultValue, ParticleStream::StreamDataType dataType, const char* streamName, bool localStream)
107 {
108   mDataStreams.emplace_back(new ParticleDataStream(mMaxParticleCount, sizeOfDataType, defaultValue, dataType));
109   if(streamName)
110   {
111     mDataStreams.back()->SetStreamName(streamName);
112   }
113
114   mDataStreams.back()->SetStreamLocal(localStream);
115
116   // Update element size
117   mParticleStreamElementSize          = 0;
118   mParticleStreamElementSizeWithLocal = 0;
119   for(auto& ds : mDataStreams)
120   {
121     if(!ds->localStream)
122     {
123       mParticleStreamElementSize += ds->dataSize;
124     }
125     mParticleStreamElementSizeWithLocal += ds->dataSize;
126   }
127
128   return mDataStreams.size() - 1;
129 }
130
131 void* ParticleList::GetRawStream(uint32_t index)
132 {
133   if(index < mDataStreams.size() && mDataStreams[index])
134   {
135     return mDataStreams[index]->data.data();
136   }
137   return nullptr;
138 }
139
140 uint32_t ParticleList::GetStreamCount() const
141 {
142   return mDataStreams.size();
143 }
144
145 uint32_t ParticleList::GetParticleCount() const
146 {
147   return mMaxParticleCount;
148 }
149
150 uint32_t ParticleList::GetActiveParticleCount() const
151 {
152   return mParticles.size();
153 }
154
155 ParticleStream::StreamDataType ParticleList::GetStreamDataType(uint32_t streamIndex)
156 {
157   return mDataStreams[streamIndex]->type;
158 }
159
160 const std::string& ParticleList::GetStreamName(uint32_t streamIndex) const
161 {
162   return mDataStreams[streamIndex]->streamName;
163 }
164
165 bool ParticleList::IsStreamLocal(uint32_t streamIndex) const
166 {
167   return mDataStreams[streamIndex]->localStream;
168 }
169
170 uint32_t ParticleList::GetStreamDataTypeSize(uint32_t streamIndex) const
171 {
172   return mDataStreams[streamIndex]->dataSize;
173 }
174
175 ParticleSystem::Particle ParticleList::NewParticle(float lifetime)
176 {
177   if(mParticles.size() < mMaxParticleCount)
178   {
179     auto newIndex = int32_t(mFreeIndex);
180     mFreeIndex    = int32_t(mFreeChain[mFreeIndex]);
181     mAliveParticleCount++;
182
183     // Add particle
184     mParticles.emplace_back(new Internal::Particle(*this, newIndex));
185
186     // Set particle lifetime
187     auto& particle = mParticles.back();
188
189     particle.Get<float>(ParticleStream::LIFETIME_STREAM_BIT) = lifetime;
190
191     // Store initial lifetime
192     particle.Get<float>(ParticleStream::LIFETIME_BASE_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 > -1)
219   {
220     mFreeChain[p.GetIndex()] = mFreeIndex;
221   }
222   mFreeIndex = p.GetIndex();
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