Merge "Fix the normalization factor calculation for blendshapes" into 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
27 template<>
28 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector3>::GetType()
29 {
30   return ParticleStream::StreamDataType::FLOAT3;
31 }
32
33 template<>
34 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector4>::GetType()
35 {
36   return ParticleStream::StreamDataType::FLOAT4;
37 }
38
39 template<>
40 ParticleStream::StreamDataType StreamDataTypeWrapper<Vector2>::GetType()
41 {
42   return ParticleStream::StreamDataType::FLOAT2;
43 }
44
45 template<>
46 ParticleStream::StreamDataType StreamDataTypeWrapper<float>::GetType()
47 {
48   return ParticleStream::StreamDataType::FLOAT;
49 }
50
51 ParticleList::ParticleList(uint32_t capacity, ParticleSystem::ParticleList::ParticleStreamTypeFlags streamFlags)
52 {
53   // capacity makes for max immutable particle count
54   mMaxParticleCount = capacity;
55
56   // initialize built-in streams and build map (to optimize later)
57   if(streamFlags & ParticleStream::POSITION_STREAM_BIT)
58   {
59     AddStream(Vector3::ZERO, "aStreamPosition", false);
60     mBuiltInStreamMap[uint32_t(ParticleStream::POSITION_STREAM_BIT)] = mDataStreams.size() - 1;
61   }
62   if(streamFlags & ParticleStream::ROTATION_STREAM_BIT)
63   {
64     AddStream(Vector4::ZERO, "aStreamRotation", false);
65     mBuiltInStreamMap[uint32_t(ParticleStream::ROTATION_STREAM_BIT)] = mDataStreams.size() - 1;
66   }
67   if(streamFlags & ParticleStream::SCALE_STREAM_BIT)
68   {
69     AddStream(Vector3::ONE, "aStreamScale", false);
70     mBuiltInStreamMap[uint32_t(ParticleStream::SCALE_STREAM_BIT)] = mDataStreams.size() - 1;
71   }
72   if(streamFlags & ParticleStream::VELOCITY_STREAM_BIT)
73   {
74     AddStream(Vector3::ZERO, "aStreamVelocity", false);
75     mBuiltInStreamMap[uint32_t(ParticleStream::VELOCITY_STREAM_BIT)] = mDataStreams.size() - 1;
76   }
77   if(streamFlags & ParticleStream::COLOR_STREAM_BIT)
78   {
79     AddStream(Color::YELLOW, "aStreamColor", false);
80     mBuiltInStreamMap[uint32_t(ParticleStream::COLOR_STREAM_BIT)] = mDataStreams.size() - 1;
81   }
82   if(streamFlags & ParticleStream::OPACITY_STREAM_BIT)
83   {
84     AddStream(0.0f, "aStreamOpacity", false);
85     mBuiltInStreamMap[uint32_t(ParticleStream::OPACITY_STREAM_BIT)] = mDataStreams.size() - 1;
86   }
87   if(streamFlags & ParticleStream::LIFETIME_STREAM_BIT)
88   {
89     AddStream(0.0f, "aStreamLifetime", false);
90     mBuiltInStreamMap[uint32_t(ParticleStream::LIFETIME_STREAM_BIT)] = mDataStreams.size() - 1;
91   }
92
93   // create free chain
94   mFreeChain.resize(capacity);
95   for(auto i = 0u; i < mFreeChain.size(); ++i)
96   {
97     mFreeChain[i] = i + 1;
98   }
99   mFreeChain[mFreeChain.size() - 1] = 0;
100   mFreeIndex                        = 0;
101 }
102
103 ParticleList::~ParticleList() = default;
104
105 uint32_t ParticleList::AddStream(uint32_t sizeOfDataType, const void* defaultValue, ParticleStream::StreamDataType dataType, const char* streamName, bool localStream)
106 {
107   mDataStreams.emplace_back(new ParticleDataStream(mMaxParticleCount, sizeOfDataType, defaultValue, dataType));
108   if(streamName)
109   {
110     mDataStreams.back()->SetStreamName(streamName);
111   }
112
113   mDataStreams.back()->SetStreamLocal(localStream);
114
115   // Update element size
116   mParticleStreamElementSize          = 0;
117   mParticleStreamElementSizeWithLocal = 0;
118   for(auto& ds : mDataStreams)
119   {
120     if(!ds->localStream)
121     {
122       mParticleStreamElementSize += ds->dataSize;
123     }
124     mParticleStreamElementSizeWithLocal += ds->dataSize;
125   }
126
127   return mDataStreams.size() - 1;
128 }
129
130 void* ParticleList::GetRawStream(uint32_t index)
131 {
132   if(index < mDataStreams.size() && mDataStreams[index])
133   {
134     return mDataStreams[index]->data.data();
135   }
136   return nullptr;
137 }
138
139 uint32_t ParticleList::GetStreamCount() const
140 {
141   return mDataStreams.size();
142 }
143
144 uint32_t ParticleList::GetParticleCount() const
145 {
146   return mMaxParticleCount;
147 }
148
149 uint32_t ParticleList::GetActiveParticleCount() const
150 {
151   return mParticles.size();
152 }
153
154 ParticleStream::StreamDataType ParticleList::GetStreamDataType(uint32_t streamIndex)
155 {
156   return mDataStreams[streamIndex]->type;
157 }
158
159 const std::string& ParticleList::GetStreamName(uint32_t streamIndex) const
160 {
161   return mDataStreams[streamIndex]->streamName;
162 }
163
164 bool ParticleList::IsStreamLocal(uint32_t streamIndex) const
165 {
166   return mDataStreams[streamIndex]->localStream;
167 }
168
169 uint32_t ParticleList::GetStreamDataTypeSize(uint32_t streamIndex) const
170 {
171   return mDataStreams[streamIndex]->dataSize;
172 }
173
174 ParticleSystem::Particle ParticleList::NewParticle(float lifetime)
175 {
176   if(mParticles.size() < mMaxParticleCount)
177   {
178     auto newIndex = int32_t(mFreeIndex);
179     mFreeIndex    = int32_t(mFreeChain[mFreeIndex]);
180     mAliveParticleCount++;
181
182     // Add particle
183     mParticles.emplace_back(new Internal::Particle(*this, newIndex));
184
185     // Set particle lifetime
186     auto& particle = mParticles.back();
187
188     particle.Get<float>(ParticleStream::LIFETIME_STREAM_BIT) = lifetime;
189
190     return mParticles.back();
191   }
192   return {nullptr};
193 }
194
195 uint32_t ParticleList::GetStreamElementSize(bool includeLocalStream)
196 {
197   if(includeLocalStream)
198   {
199     return mParticleStreamElementSizeWithLocal;
200   }
201   else
202   {
203     return mParticleStreamElementSize;
204   }
205 }
206
207 void ParticleList::ReleaseParticle(uint32_t particleIndex)
208 {
209   auto it = mParticles.begin();
210   std::advance(it, particleIndex);
211
212   // Point at this slot of memory as next free slot
213   auto& p = *it;
214   if(mFreeIndex)
215   {
216     mFreeChain[p.GetIndex()] = mFreeIndex;
217     mFreeIndex               = p.GetIndex();
218   }
219
220   // Remove particle from the list
221   mParticles.erase(it);
222   mAliveParticleCount--;
223 }
224
225 void* ParticleList::GetDefaultStream(ParticleStreamTypeFlagBit streamBit)
226 {
227   return GetRawStream(mBuiltInStreamMap[streamBit]);
228 }
229
230 uint32_t ParticleList::GetDefaultStreamIndex(ParticleStreamTypeFlagBit streamBit)
231 {
232   return mBuiltInStreamMap[uint32_t(streamBit)];
233 }
234
235 std::list<ParticleSystem::Particle>& ParticleList::GetParticles()
236 {
237   return mParticles;
238 }
239
240 } // namespace Dali::Toolkit::ParticleSystem::Internal