Particle System
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / particle-system / particle-list-impl.h
1 #ifndef DALI_TOOLKIT_PARTICLE_SYSTEM_INTERNAL_PARTICLE_LIST_H
2 #define DALI_TOOLKIT_PARTICLE_SYSTEM_INTERNAL_PARTICLE_LIST_H
3 /*
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 // INTERNAL INCLUDES
21 #include <dali-toolkit/public-api/particle-system/particle-list.h>
22 #include <dali-toolkit/public-api/particle-system/particle.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/public-api/object/base-object.h>
26 #include <algorithm>
27 #include <list>
28 #include <map>
29 #include <memory>
30 #include <vector>
31
32 namespace Dali::Toolkit::ParticleSystem::Internal
33 {
34 template<class T>
35 struct StreamDataTypeWrapper
36 {
37   static ParticleStream::StreamDataType GetType()
38   {
39     return {};
40   }
41 };
42
43 struct ParticleDataStream
44 {
45   ~ParticleDataStream() = default;
46   template<class T>
47   ParticleDataStream(uint32_t capacity, const T& defaultValue, ParticleStream::StreamDataType dataType)
48   : ParticleDataStream(capacity, sizeof(T), &defaultValue, dataType)
49   {
50   }
51
52   /**
53    * Creates new stream of requested capacity and (optionally) fills with default data
54    */
55   ParticleDataStream(uint32_t capacity, uint32_t dataSize, const void* defaultValue, ParticleStream::StreamDataType dataType)
56   {
57     this->capacity = capacity;
58     data.resize(capacity * dataSize);
59     if(defaultValue)
60     {
61       for(auto i = 0u; i < capacity; ++i)
62       {
63         auto dstPtr = data.data() + (i * dataSize);
64         std::copy(reinterpret_cast<const uint8_t*>(defaultValue), reinterpret_cast<const uint8_t*>(defaultValue) + dataSize, dstPtr);
65       }
66     }
67     type           = dataType;
68     alive          = 0u;
69     this->dataSize = dataSize;
70   }
71
72   void SetStreamName(const char* name)
73   {
74     streamName = name;
75   }
76
77   void SetStreamLocal(bool local)
78   {
79     localStream = local;
80   }
81
82   /**
83    * Converts raw data into requested type (does not guarantee compatibility)
84    */
85   template<class T>
86   T* GetAs()
87   {
88     return reinterpret_cast<T*>(data.data());
89   }
90
91   ParticleStream::StreamDataType type;
92   std::vector<uint8_t>           data;
93   std::string                    streamName;
94   uint32_t                       alive{0u};
95   uint32_t                       capacity;
96   uint32_t                       dataSize;
97   bool                           localStream{true};
98 };
99
100 /**
101  * Particle list stores particle-specific data and manages the particles memory
102  * It can return a sub-list.
103  *
104  * ParticleList manages the storage memory.
105  *
106  *
107  */
108 class ParticleList : public Dali::BaseObject
109 {
110 public:
111
112   ParticleList(uint32_t capacity, ParticleSystem::ParticleList::ParticleStreamTypeFlags streamFlags);
113
114   ~ParticleList();
115
116   /**
117    * Returns raw pointer to the stream data
118    */
119   void* GetRawStream(uint32_t index);
120
121   /**
122    * Returns number of available data streams
123    * @return
124    */
125   uint32_t GetStreamCount() const;
126
127   /**
128    * Returns number of particles per list
129    * @return
130    */
131   uint32_t GetParticleCount() const;
132
133   /**
134    * Returns number of currently active particles
135    * @return
136    */
137   uint32_t GetActiveParticleCount() const;
138
139   /**
140    * Returns stream data-type
141    * @param streamIndex
142    * @return
143    */
144   ParticleStream::StreamDataType GetStreamDataType(uint32_t streamIndex);
145
146   /**
147    * Returns stream data type size
148    * @param streamIndex
149    * @return
150    */
151   [[nodiscard]] uint32_t GetStreamDataTypeSize(uint32_t streamIndex) const;
152
153   [[nodiscard]] const std::string& GetStreamName(uint32_t streamIndex) const;
154
155   [[nodiscard]] bool IsStreamLocal(uint32_t streamIndex) const;
156
157   /**
158    * Allocates new particle in the streams
159    * @param lifetime
160    * @return
161    */
162   ParticleSystem::Particle NewParticle(float lifetime);
163
164   void* GetDefaultStream(ParticleStreamTypeFlagBit streamBit);
165
166   uint32_t GetDefaultStreamIndex(ParticleStreamTypeFlagBit streamBit);
167
168   std::list<ParticleSystem::Particle>& GetParticles();
169
170   void ReleaseParticle(uint32_t particleIndex);
171
172   uint32_t GetStreamElementSize(bool includeLocalStream);
173
174 private:
175   template<class T>
176   uint32_t AddStream(const T& defaultValue, const char* streamName, bool localStream)
177   {
178     return AddStream(sizeof(T), &defaultValue, StreamDataTypeWrapper<T>::GetType(), streamName, localStream);
179   }
180
181 public:
182   /**
183    * Adds new stream and returns index
184    */
185   uint32_t AddStream(uint32_t sizeOfDataType, const void* defaultValue, ParticleStream::StreamDataType dataType, const char* streamName, bool localStream);
186
187 private:
188   std::vector<char> mBuffer[2];
189
190   uint32_t mAliveParticleCount{0u};
191   uint32_t mMaxParticleCount;
192
193   // Data storage
194   std::vector<std::unique_ptr<ParticleDataStream>> mDataStreams;
195
196   std::vector<uint32_t> mFreeChain;
197   int32_t               mFreeIndex{0u};
198
199   std::map<uint32_t, uint32_t> mBuiltInStreamMap;
200
201   std::list<ParticleSystem::Particle> mParticles;
202
203   uint32_t mParticleStreamElementSizeWithLocal{0u};
204   uint32_t mParticleStreamElementSize{0u};
205 };
206
207 } // namespace Dali::Toolkit::ParticleSystem::Internal
208 namespace Dali::Toolkit::ParticleSystem
209 {
210 inline Internal::ParticleList& GetImplementation(ParticleSystem::ParticleList& source)
211 {
212   DALI_ASSERT_ALWAYS(source && "ParticleList handle is empty");
213
214   BaseObject& handle = source.GetBaseObject();
215
216   return static_cast<Internal::ParticleList&>(handle);
217 }
218
219 inline const Internal::ParticleList& GetImplementation(const ParticleSystem::ParticleList& source)
220 {
221   DALI_ASSERT_ALWAYS(source && "ParticleList handle is empty");
222
223   const BaseObject& handle = source.GetBaseObject();
224
225   return static_cast<const Internal::ParticleList&>(handle);
226 }
227
228 } // namespace Dali::Toolkit::ParticleSystem
229
230 #endif // DALI_TOOLKIT_PARTICLE_SYSTEM_INTERNAL_PARTICLE_LIST_H