[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / particle-system / particle-emitter-impl.h
1 #ifndef DALI_TOOLKIT_PARTICLE_SYSTEM_INTERNAL_PARTICLE_EMITTER_H
2 #define DALI_TOOLKIT_PARTICLE_SYSTEM_INTERNAL_PARTICLE_EMITTER_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 // EXTERNAL INCLUDES
21 #include <dali/public-api/adaptor-framework/timer.h>
22 #include <dali/public-api/object/base-object.h>
23 #include <chrono>
24 #include <ctime>
25 #include <memory>
26
27 // For multithreading update
28 #include <dali/devel-api/threading/thread-pool.h>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/public-api/particle-system/particle-domain.h>
32 #include <dali-toolkit/public-api/particle-system/particle-emitter.h>
33 #include <dali-toolkit/public-api/particle-system/particle-list.h>
34 #include <dali-toolkit/public-api/particle-system/particle-modifier.h>
35 #include <dali-toolkit/public-api/particle-system/particle-renderer.h>
36 #include <dali-toolkit/public-api/particle-system/particle-source.h>
37
38 namespace Dali::Toolkit::ParticleSystem::Internal
39 {
40 class FrameCallback;
41 class ParticleEmitter : public Dali::BaseObject, public Dali::ConnectionTracker
42 {
43 public:
44   /**
45    * @brief Constructor
46    */
47   ParticleEmitter();
48
49   /**
50    * @brief Destructor
51    */
52   ~ParticleEmitter() override;
53
54   /**
55    * @brief Tests whether emitter is complete (ready for simulation)
56    *
57    * @return True if emitter is complete, false otherwise
58    */
59   [[nodiscard]] bool IsComplete() const
60   {
61     return (mParticleStatusBits & STATUS_COMPLETE_BITS) == STATUS_COMPLETE_BITS;
62   }
63
64   [[nodiscard]] ParticleSystem::ParticleSource GetSource() const;
65
66   void SetSource(const ParticleSystem::ParticleSource& source);
67
68   [[nodiscard]] ParticleSystem::ParticleDomain GetDomain() const;
69
70   void SetDomain(const ParticleSystem::ParticleDomain& domain);
71
72   [[nodiscard]] ParticleSystem::ParticleRenderer GetRenderer() const;
73
74   [[nodiscard]] ParticleSystem::ParticleModifier GetModifierAt(uint32_t index);
75
76   void RemoveModifierAt(uint32_t index);
77
78   void SetRenderer(const ParticleSystem::ParticleRenderer& renderer);
79
80   void SetParticleCount(uint32_t maxParticleCount);
81
82   uint32_t GetParticleCount();
83
84   ParticleSystem::ParticleList& GetParticleList();
85
86   uint32_t AddModifier(const ParticleSystem::ParticleModifier& modifier);
87
88   void AttachTo(Actor actor);
89
90   [[nodiscard]] Actor GetActor() const;
91
92   void Update();
93
94   void UpdateSource(uint32_t count);
95
96   void UpdateModifierMT(Dali::Toolkit::ParticleSystem::ParticleModifier& modifier);
97
98   void UpdateDomain();
99
100   void SetEmissionRate(uint32_t ratePerSecond);
101
102   [[nodiscard]] uint32_t GetEmissionRate() const;
103
104   void SetInitialParticleCount(uint32_t count);
105
106   [[nodiscard]] uint32_t GetInitialParticleCount() const;
107
108   void Start();
109
110   void Stop();
111
112   void EnableParallelProcessing(bool enabled);
113
114   [[nodiscard]] bool IsParallelProcessingEnabled() const;
115
116   void SetActiveParticlesLimit(uint32_t count);
117
118   [[nodiscard]] uint32_t GetActiveParticlesLimit() const;
119
120   [[nodiscard]] ParticleSystem::ParticleEmitter::Status GetStatus() const;
121
122   [[nodiscard]] std::chrono::milliseconds GetCurrentTimeMillis() const;
123
124   // All these bits must be set in order to consider emitter COMPLETE
125   const uint32_t SOURCE_SET_STATUS_BIT   = 1 << 0;
126   const uint32_t RENDERER_SET_STATUS_BIT = 1 << 1;
127   const uint32_t DOMAIN_SET_STATUS_BIT   = 1 << 2;
128
129   // 1. Only one of these flags can be set at a time
130   // 2. They are invalid as long as emitter is INCOMPLETE
131   const uint32_t SIMULATION_STARTED_STATUS_BIT = 1 << 3;
132   const uint32_t SIMULATION_PAUSED_STATUS_BIT  = 1 << 4;
133   const uint32_t SIMULATION_STOPPED_STATUS_BIT = 1 << 5;
134
135   const uint32_t STATUS_COMPLETE_BITS = SOURCE_SET_STATUS_BIT | RENDERER_SET_STATUS_BIT | DOMAIN_SET_STATUS_BIT;
136
137   ParticleSystem::ParticleSource mParticleSource; ///< Current particle source object
138   ParticleSystem::ParticleDomain mParticleDomain; ///< Current particle domain object
139
140   uint8_t mParticleStatusBits{0u}; ///< Current status of the emitter
141
142   // List of particles
143   ParticleSystem::ParticleList mParticleList;
144
145   std::vector<ParticleSystem::ParticleModifier> mModifiers;
146
147   ParticleSystem::ParticleRenderer mParticleRenderer;
148
149   Actor mActor;
150
151   uint32_t                  mEmissionRatePerSecond{1u};
152   std::atomic<uint32_t>     mEmissionCountOnStart{0u};
153   std::atomic<uint32_t>     mActiveParticlesLimit{0u}; ///< 0 - unlimited
154   std::atomic<bool>         mSystemStarted{false};
155   std::chrono::milliseconds mCurrentMilliseconds{0};
156   std::chrono::milliseconds mLastUpdateMs{0};
157
158   bool                           mParallelProcessing{false};
159   std::unique_ptr<FrameCallback> mFrameCallback;
160 };
161
162 } // namespace Dali::Toolkit::ParticleSystem::Internal
163
164 namespace Dali::Toolkit::ParticleSystem
165 {
166 // Returns thread pool shared by whole particle system
167 Dali::ThreadPool& GetThreadPool();
168
169 inline Internal::ParticleEmitter& GetImplementation(ParticleSystem::ParticleEmitter& source)
170 {
171   DALI_ASSERT_ALWAYS(source && "ParticleEmitter handle is empty");
172
173   BaseObject& handle = source.GetBaseObject();
174
175   return static_cast<Internal::ParticleEmitter&>(handle);
176 }
177
178 inline const Internal::ParticleEmitter& GetImplementation(const ParticleSystem::ParticleEmitter& source)
179 {
180   DALI_ASSERT_ALWAYS(source && "ParticleEmitter handle is empty");
181
182   const BaseObject& handle = source.GetBaseObject();
183
184   return static_cast<const Internal::ParticleEmitter&>(handle);
185 }
186
187 } // namespace Dali::Toolkit::ParticleSystem
188 #endif // DALI_TOOLKIT_PARTICLE_SYSTEM_INTERNAL_PARTICLE_EMITTER_H