summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorAdam Bialogonski <adam.b@samsung.com>2023-06-02 18:09:24 +0100
committerAdam Bialogonski <adam.b@samsung.com>2023-06-02 18:17:33 +0100
commit9fe0bbd7cad662a72ffcadc7d772918e100a8c64 (patch)
tree88a8516f29d9bb3a82d75eb23e502a37cc538631 /examples
parentb9aeca68e82975b574420bee1fd660f4c228e56c (diff)
downloaddali-demo-9fe0bbd7cad662a72ffcadc7d772918e100a8c64.tar.gz
dali-demo-9fe0bbd7cad662a72ffcadc7d772918e100a8c64.tar.bz2
dali-demo-9fe0bbd7cad662a72ffcadc7d772918e100a8c64.zip
Particle System Demo
Change-Id: Ib5cc186c001952c8f2f74c2371575a08d94bb607
Diffstat (limited to 'examples')
-rw-r--r--examples/particle-system/effects/fire-ring-effect-modifier.cpp102
-rw-r--r--examples/particle-system/effects/fire-ring-effect-modifier.h88
-rw-r--r--examples/particle-system/effects/fire-ring-effect-source.cpp87
-rw-r--r--examples/particle-system/effects/fire-ring-effect-source.h55
-rw-r--r--examples/particle-system/effects/image-effect-modifier.cpp77
-rw-r--r--examples/particle-system/effects/image-effect-modifier.h53
-rw-r--r--examples/particle-system/effects/image-effect-source.cpp119
-rw-r--r--examples/particle-system/effects/image-effect-source.h62
-rw-r--r--examples/particle-system/effects/particle-effect.cpp106
-rw-r--r--examples/particle-system/effects/particle-effect.h65
-rw-r--r--examples/particle-system/effects/sparkles-effect-modifier.cpp89
-rw-r--r--examples/particle-system/effects/sparkles-effect-modifier.h54
-rw-r--r--examples/particle-system/effects/sparkles-effect-source.cpp91
-rw-r--r--examples/particle-system/effects/sparkles-effect-source.h56
-rw-r--r--examples/particle-system/particle-system-example.cpp217
15 files changed, 1321 insertions, 0 deletions
diff --git a/examples/particle-system/effects/fire-ring-effect-modifier.cpp b/examples/particle-system/effects/fire-ring-effect-modifier.cpp
new file mode 100644
index 00000000..56f7e5b2
--- /dev/null
+++ b/examples/particle-system/effects/fire-ring-effect-modifier.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "fire-ring-effect-modifier.h"
+#include "fire-ring-effect-source.h"
+
+namespace Dali::ParticleEffect
+{
+FireModifier::FireModifier(ParticleEmitter& emitter)
+: mEmitter(emitter)
+{
+ // initialize gradient with flame colors
+ mFireGradient.PushColor(Vector4(1.0f, 1.0f, 1.0f, 1.0f), 1.0f - 1.0f);
+ mFireGradient.PushColor(Vector4(0.975, 0.955, 0.476, 1.0f), 1.0f - 0.947f);
+ mFireGradient.PushColor(Vector4(0.999, 0.550, 0.194, 1.0f), 1.0f - 0.800f);
+ mFireGradient.PushColor(Vector4(0.861, 0.277, 0.094, 1.0f), 1.0f - 0.670f);
+ mFireGradient.PushColor(Vector4(0.367, 0.0, 0.0, 1.0f), 1.0f - 0.456f);
+ mFireGradient.PushColor(Vector4(0.3, 0.3, 0.3, 1.0f), 1.0f - 0.400f);
+ mFireGradient.PushColor(Vector4(0.3, 0.2, 0.2, 1.0f), 1.0f - 0.200f);
+ mFireGradient.PushColor(Vector4(0.2, 0.1, 0.1, 1.0f), 1.0f - 0.150f);
+ mFireGradient.PushColor(Vector4(0.1, 0.0, 0.0, 1.0f), 1.0f- 0.100f);
+ mFireGradient.PushColor(Vector4(0.0, 0.0, 0.0, 0.5f), 1.0f-0.050f);
+ mFireGradient.PushColor(Vector4(0.0, 0.0, 0.0, 0.2f), 1.0f);
+}
+
+bool FireModifier::IsMultiThreaded()
+{
+ return false;
+}
+
+void FireModifier::Update(ParticleList& particleList, uint32_t first, uint32_t count)
+{
+ // If no acive particles return
+ if(!particleList.GetActiveParticleCount())
+ {
+ return;
+ }
+
+ mAngle = ((mAngle + 2) % 360);
+
+ // Retrieve the Source and get the stream
+ if(!mStreamBasePos)
+ {
+ mStreamBasePos = static_cast<FireSource*>(&mEmitter.GetSource().GetSourceCallback())->mStreamBasePos;
+ }
+
+ // Missing stream, return!
+ if(!mStreamBasePos)
+ {
+ return;
+ }
+
+ auto& activeParticles = particleList.GetActiveParticles();
+
+ auto it = activeParticles.begin();
+ std::advance(it, first);
+
+ int i = 0;
+ for(; count; ++it, count--)
+ {
+ i += 1;
+
+ // Acquire stream data
+ auto& particle = *it;
+ auto& position = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
+ auto& velocity = particle.Get<Vector3>(ParticleStream::VELOCITY_STREAM_BIT);
+ auto& color = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
+ auto& baseLifetime = particle.Get<float>(ParticleStream::LIFETIME_BASE_STREAM_BIT);
+ auto& scale = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
+
+ // Get base positions
+ auto& basePos = particle.GetByIndex<Vector3>(mStreamBasePos);
+
+ float lifetime = particle.Get<float>(ParticleStream::LIFETIME_STREAM_BIT);
+ position.y += -fabs(velocity.y);
+ position.x = basePos.x + 5.0f * sin((((mAngle + i)%360)*M_PI)/180.f );
+
+ velocity *= 0.990f;
+ auto newColor = mFireGradient.GetColorAt((baseLifetime - lifetime) / baseLifetime);
+ float normalizedTime = (lifetime / baseLifetime);
+ newColor.a = normalizedTime * normalizedTime;
+
+ scale = Vector3(64.0f*(normalizedTime * normalizedTime * normalizedTime * normalizedTime), 64.0f*(normalizedTime * normalizedTime * normalizedTime * normalizedTime), 1.0);
+
+ color = newColor;
+ }
+}
+} \ No newline at end of file
diff --git a/examples/particle-system/effects/fire-ring-effect-modifier.h b/examples/particle-system/effects/fire-ring-effect-modifier.h
new file mode 100644
index 00000000..3f9f6ea4
--- /dev/null
+++ b/examples/particle-system/effects/fire-ring-effect-modifier.h
@@ -0,0 +1,88 @@
+#ifndef DALI_PROJECT_FIRE_RING_EFFECT_MODIFIER_H
+#define DALI_PROJECT_FIRE_RING_EFFECT_MODIFIER_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <ctime>
+
+namespace Dali::ParticleEffect
+{
+using namespace Dali::Toolkit::ParticleSystem;
+
+class FireModifier : public ParticleModifierInterface
+{
+public:
+
+ struct ColorGradient
+ {
+ std::vector<Vector4> colors;
+ std::vector<float> position;
+
+ void PushColor(const Vector4& color, float pos)
+ {
+ colors.emplace_back(color);
+ position.emplace_back(pos);
+ }
+
+ Vector4 GetColorAt(float pos)
+ {
+ if(pos >= 1.0f)
+ {
+ return colors.back();
+ }
+ else if(pos <= 0.0f)
+ {
+ return colors[0];
+ }
+ for(auto i = 0u; i < position.size() - 1; ++i)
+ {
+ if(pos >= position[i] && pos < position[i + 1])
+ {
+ auto colorDiff = colors[i + 1] - colors[i];
+ return colors[i] + (colorDiff * ((pos - position[i]) / (position[i + 1] - position[i])));
+ }
+ }
+ return colors[0];
+ }
+ };
+
+
+ explicit FireModifier(ParticleEmitter& emitter);
+
+ bool IsMultiThreaded() override;
+
+ void Update(ParticleList& particleList, uint32_t first, uint32_t count) override;
+
+ ColorGradient mFireGradient;
+ ParticleEmitter mEmitter;
+ uint32_t mStreamBasePos{0u};
+ uint32_t mAngle{0u};
+};
+
+
+
+}
+
+#endif // DALI_PROJECT_FIRE_RING_EFFECT_MODIFIER_H
diff --git a/examples/particle-system/effects/fire-ring-effect-source.cpp b/examples/particle-system/effects/fire-ring-effect-source.cpp
new file mode 100644
index 00000000..0ff0652a
--- /dev/null
+++ b/examples/particle-system/effects/fire-ring-effect-source.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "fire-ring-effect-source.h"
+#include <random>
+
+namespace Dali::ParticleEffect
+{
+static float LIFETIME = 5.0f;
+FireSource::FireSource(ParticleEmitter& emitter)
+: mEmitter(emitter)
+{
+ std::time_t result = std::time(nullptr);
+ srand(result);
+ mRadius = Vector2::ONE;
+}
+
+FireSource::FireSource(ParticleEmitter& emitter, Dali::Vector2 ringRadius) :
+mEmitter(emitter)
+{
+ std::time_t result = std::time(nullptr);
+ srand(result);
+ mRadius = ringRadius;
+
+}
+
+void FireSource::Init()
+{
+ mStreamBasePos = mEmitter.GetParticleList().AddLocalStream<Vector3>(Vector3::ZERO);
+}
+
+uint32_t FireSource::Update(ParticleList& particleList, uint32_t count)
+{
+ while(count--)
+ {
+ auto particle = particleList.NewParticle(LIFETIME * (float(std::rand() % 1000)/1000.0f) + 1.0f );
+ if(!particle)
+ {
+ return 0u;
+ }
+
+ auto& basePosition = particle.GetByIndex<Vector3>(mStreamBasePos);
+
+ auto& position = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
+ auto& color = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
+ auto& velocity = particle.Get<Vector3>(ParticleStream::VELOCITY_STREAM_BIT);
+ auto& scale = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
+ UpdateParticle(position, basePosition, color, velocity, scale);
+ }
+
+ return 0;
+}
+
+void FireSource::UpdateParticle(Vector3& position, Vector3& basePosition, Vector4& color, Vector3& velocity, Vector3& scale)
+{
+ float posRadians = ((rand() % 360) * M_PI) / 180.0f;
+
+ basePosition.x = position.x = mRadius.x * sin(posRadians);
+ basePosition.y = position.y = mRadius.y * cos(posRadians);
+ color = Dali::Color::WHITE; // white color when emitted
+
+ // angle of motion
+ float radians = ((rand() % 360) * M_PI) / 180.0f;
+ float speed = ((rand() % 5) + 5);
+ velocity.x = sin(radians) * speed;
+ velocity.y = cos(radians) * speed;
+
+ // Random initial scale
+ float currentScale = float(rand() % 32) + 32;
+ scale = Vector3(currentScale, currentScale, 1);
+}
+
+} // namespace Dali::ParticleEffect \ No newline at end of file
diff --git a/examples/particle-system/effects/fire-ring-effect-source.h b/examples/particle-system/effects/fire-ring-effect-source.h
new file mode 100644
index 00000000..28f78efa
--- /dev/null
+++ b/examples/particle-system/effects/fire-ring-effect-source.h
@@ -0,0 +1,55 @@
+#ifndef DALI_FIRE_RING_EFFECT_SOURCE_H
+#define DALI_FIRE_RING_EFFECT_SOURCE_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle.h>
+#include <ctime>
+
+namespace Dali::ParticleEffect
+{
+using namespace Dali::Toolkit::ParticleSystem;
+
+class FireSource : public Toolkit::ParticleSystem::ParticleSourceInterface
+{
+public:
+
+ explicit FireSource(ParticleEmitter& emitter);
+
+ explicit FireSource(ParticleEmitter& emitter, Dali::Vector2 ringRadius);
+
+ uint32_t Update(ParticleList& particleList, uint32_t count) override;
+
+ void Init() override;
+
+ void UpdateParticle(Vector3& position, Vector3& basePosition, Vector4& color, Vector3& velocity, Vector3& scale);
+
+ ParticleEmitter mEmitter;
+
+ Dali::Vector2 mRadius;
+
+ uint32_t mStreamBasePos{0u};
+
+};
+
+}
+#endif // DALI_FIRE_RING_EFFECT_SOURCE_H
diff --git a/examples/particle-system/effects/image-effect-modifier.cpp b/examples/particle-system/effects/image-effect-modifier.cpp
new file mode 100644
index 00000000..395040c7
--- /dev/null
+++ b/examples/particle-system/effects/image-effect-modifier.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "image-effect-modifier.h"
+#include "image-effect-source.h"
+namespace Dali::ParticleEffect
+{
+
+#define RAD(x) (float(x)*M_PI/180.0f)
+
+ImageExplodeEffectModifier::ImageExplodeEffectModifier(ParticleEmitter& emitter)
+: mEmitter(emitter)
+{
+
+}
+
+bool ImageExplodeEffectModifier::IsMultiThreaded()
+{
+ return false;
+}
+
+void ImageExplodeEffectModifier::Update(ParticleList& particleList, uint32_t first, uint32_t count)
+{
+ // If no acive particles return
+ if(!particleList.GetActiveParticleCount())
+ {
+ return;
+ }
+
+ // Retrieve the Source and get the stream
+ if(!mStreamBasePos)
+ {
+ mStreamBasePos = static_cast<ImageExplodeEffectSource*>(&mEmitter.GetSource().GetSourceCallback())->mStreamBasePos;
+ }
+
+ // Missing stream, return!
+ if(!mStreamBasePos)
+ {
+ return;
+ }
+
+ auto& activeParticles = particleList.GetActiveParticles();
+
+ auto it = activeParticles.begin();
+ std::advance(it, first);
+
+ mAngle += 5.0f;
+
+ for(; count; ++it, count--)
+ {
+ // Acquire stream data
+ auto& particle = *it;
+ auto& position = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
+ auto& color = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
+
+ // Get base positions
+ auto& basePos = particle.GetByIndex<Vector3>(mStreamBasePos);
+ position.z = 200.f * sin(RAD(mAngle+basePos.x));
+ color.a = position.z < 0.0f ? 1.0f : 1.0f - position.z/500.0f;
+ position.z = 500 + position.z;
+ }
+}
+} \ No newline at end of file
diff --git a/examples/particle-system/effects/image-effect-modifier.h b/examples/particle-system/effects/image-effect-modifier.h
new file mode 100644
index 00000000..8a0781e4
--- /dev/null
+++ b/examples/particle-system/effects/image-effect-modifier.h
@@ -0,0 +1,53 @@
+#ifndef DALI_IMAGE_EFFECT_MODIFIER_H
+#define DALI_IMAGE_EFFECT_MODIFIER_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle.h>
+#include <ctime>
+
+namespace Dali::ParticleEffect
+{
+using namespace Dali::Toolkit::ParticleSystem;
+
+class ImageExplodeEffectModifier : public ParticleModifierInterface
+{
+public:
+
+ explicit ImageExplodeEffectModifier(ParticleEmitter& emitter);
+
+ bool IsMultiThreaded() override;
+
+ void Update(ParticleList& particleList, uint32_t first, uint32_t count) override;
+
+ ParticleEmitter mEmitter;
+ uint32_t mStreamBasePos{0u};
+ float mAngle{0.0f};
+
+};
+
+
+
+}
+
+#endif // DALI_IMAGE_EFFECT_MODIFIER_H
diff --git a/examples/particle-system/effects/image-effect-source.cpp b/examples/particle-system/effects/image-effect-source.cpp
new file mode 100644
index 00000000..2e52a1e2
--- /dev/null
+++ b/examples/particle-system/effects/image-effect-source.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "image-effect-source.h"
+#include <dali/devel-api/rendering/texture-devel.h>
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <random>
+
+namespace Dali::ParticleEffect
+{
+namespace
+{
+Vector4 GetColorAt(uint32_t x, uint32_t y, Devel::PixelBuffer& buffer)
+{
+ if(buffer.GetPixelFormat() == Pixel::Format::RGBA8888)
+ {
+ const auto ptr = reinterpret_cast<uint32_t*>(buffer.GetBuffer());
+ auto value = *(ptr + x + (y * buffer.GetHeight()));
+ auto rgba = reinterpret_cast<uint8_t*>(&value);
+ return Vector4(float(rgba[0]) / 255.0f, float(rgba[1]) / 255.0f, float(rgba[2]) / 255.0f, 1.0f);
+ }
+ else
+ {
+ auto rgba = reinterpret_cast<uint8_t*>(buffer.GetBuffer() + (y*buffer.GetWidth()*3) + (x*3));
+ return Vector4(float(rgba[0]) / 255.0f, float(rgba[1]) / 255.0f, float(rgba[2]) / 255.0f, 1.0f);
+ }
+}
+}
+
+static float LIFETIME = 50000.0f; // we need infinite lifetime?
+ImageExplodeEffectSource::ImageExplodeEffectSource(ParticleEmitter& emitter)
+: mEmitter(emitter)
+{
+}
+
+ImageExplodeEffectSource::ImageExplodeEffectSource(ParticleEmitter& emitter, const std::string& imageFileName, uint32_t width, uint32_t height) :
+mEmitter(emitter)
+{
+
+ // Create texture
+ std::string filePath(DEMO_IMAGE_DIR);
+ filePath += imageFileName;
+ ImageDimensions dimensions(width, height);
+ // Pixel buffer will be used as a source of pixels (populating colors of particles based on image pixels)
+ Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile(filePath, dimensions, FittingMode::SHRINK_TO_FIT, SamplingMode::DEFAULT, false);
+ mImageWidth = pixelBuffer.GetWidth();
+ mImageHeight = pixelBuffer.GetHeight();
+ mPixelBuffer = pixelBuffer;
+}
+
+void ImageExplodeEffectSource::Init()
+{
+ mStreamBasePos = mEmitter.GetParticleList().AddLocalStream<Vector3>(Vector3::ZERO);
+}
+
+uint32_t ImageExplodeEffectSource::Update(ParticleList& particleList, uint32_t count)
+{
+ if(!mShouldEmit)
+ {
+ return 0;
+ }
+
+ if(mPixelBuffer.GetPixelFormat() != Dali::Pixel::RGBA8888 &&
+ mPixelBuffer.GetPixelFormat() != Dali::Pixel::RGB888)
+ {
+ return 0;
+ }
+
+ auto i = 0u;
+ float particleScale = 4.0f;
+ float pixelSize = 2.0f;
+
+ uint32_t halfWidth = (mImageWidth/2) * particleScale;
+ uint32_t halfHeight = (mImageHeight/2) * particleScale;
+
+ for(auto y = 0u ; y < mImageHeight; ++y)
+ {
+ for(auto x = 0u; x < mImageWidth; ++x)
+ {
+ if(i < particleList.GetCapacity())
+ {
+ // Ignore count, populating all pixels instantly (emitter must account for all the points)
+ auto particle = particleList.NewParticle(LIFETIME);
+
+ auto& basePosition = particle.GetByIndex<Vector3>(mStreamBasePos);
+ auto& position = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
+ auto& color = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
+ auto& velocity = particle.Get<Vector3>(ParticleStream::VELOCITY_STREAM_BIT);
+ auto& scale = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
+ color = GetColorAt(x, y, mPixelBuffer);
+ // Set basePosition
+ position = basePosition = Vector3(x* particleScale -halfWidth, y* particleScale -halfHeight, 0);
+ scale = Vector3(pixelSize, pixelSize, 1);
+ velocity = Vector3::ZERO;
+ }
+ ++i;
+ }
+ }
+
+ mShouldEmit = false;
+ return mImageWidth * mImageHeight;
+}
+
+
+} // namespace Dali::ParticleEffect \ No newline at end of file
diff --git a/examples/particle-system/effects/image-effect-source.h b/examples/particle-system/effects/image-effect-source.h
new file mode 100644
index 00000000..49d84c91
--- /dev/null
+++ b/examples/particle-system/effects/image-effect-source.h
@@ -0,0 +1,62 @@
+#ifndef DALI_IMAGE_EFFECT_SOURCE_H
+#define DALI_IMAGE_EFFECT_SOURCE_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <ctime>
+
+namespace Dali::ParticleEffect
+{
+using namespace Dali::Toolkit::ParticleSystem;
+
+/**
+ * Image source will use 2D image to populate points for the emitter
+ * This particular implementation populates points only once.
+ */
+class ImageExplodeEffectSource : public Toolkit::ParticleSystem::ParticleSourceInterface
+{
+public:
+
+ explicit ImageExplodeEffectSource(ParticleEmitter& emitter);
+
+ explicit ImageExplodeEffectSource(ParticleEmitter& emitter, const std::string& imageFileName, uint32_t width, uint32_t height);
+
+ uint32_t Update(ParticleList& particleList, uint32_t count) override;
+
+ void Init() override;
+
+ ParticleEmitter mEmitter;
+
+ uint32_t mImageWidth{0u};
+ uint32_t mImageHeight{0u};
+
+ uint32_t mStreamBasePos{0u};
+
+ Devel::PixelBuffer mPixelBuffer;
+
+ bool mShouldEmit {true};
+};
+
+}
+#endif // DALI_IMAGE_EFFECT_SOURCE_H
diff --git a/examples/particle-system/effects/particle-effect.cpp b/examples/particle-system/effects/particle-effect.cpp
new file mode 100644
index 00000000..e4f2c302
--- /dev/null
+++ b/examples/particle-system/effects/particle-effect.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "particle-effect.h"
+#include "fire-ring-effect-source.h"
+#include "sparkles-effect-source.h"
+#include "image-effect-source.h"
+#include "fire-ring-effect-modifier.h"
+#include "sparkles-effect-modifier.h"
+#include "image-effect-modifier.h"
+
+#include <dali-toolkit/public-api/particle-system/particle-domain.h>
+#include <dali-toolkit/public-api/particle-system/particle-renderer.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <functional>
+
+#ifndef DEMO_IMAGE_DIR
+#define DEMO_IMAGE_DIR ""
+#endif
+
+namespace Dali::ParticleEffect
+{
+using ParticleEmitter = Dali::Toolkit::ParticleSystem::ParticleEmitter;
+using ParticleSource = Dali::Toolkit::ParticleSystem::ParticleSource;
+using ParticleModifier = Dali::Toolkit::ParticleSystem::ParticleModifier;
+
+struct FunctorReturn
+{
+ ParticleEmitter emitter;
+ ParticleSource source;
+ ParticleModifier modifier;
+};
+
+static std::vector<FunctorReturn(*)(const ParticleEffectParams&)> gEffectInitializers =
+{
+ [](const ParticleEffectParams& params){
+ ParticleEmitter emitter = ParticleEmitter::New();
+ return FunctorReturn{emitter, ParticleSource::New<FireSource>(emitter, params.sourceSize), ParticleModifier::New<FireModifier>(emitter) };
+ },
+ [](const ParticleEffectParams& params){
+ ParticleEmitter emitter = ParticleEmitter::New();
+ return FunctorReturn{emitter, ParticleSource::New<SparklesSource>(emitter), ParticleModifier::New<SparklesModifier>(emitter) };
+ },
+ [](const ParticleEffectParams& params){
+ ParticleEmitter emitter = ParticleEmitter::New();
+ return FunctorReturn{emitter, ParticleSource::New<ImageExplodeEffectSource>(emitter,
+ params.strImageSourceName,
+ uint32_t(params.sourceSize.width),
+ uint32_t(params.sourceSize.height)
+ ), ParticleModifier::New<ImageExplodeEffectModifier>(emitter) };
+ },
+};
+
+ParticleEffect::ParticleEffect() = default;
+
+ParticleEffect::~ParticleEffect() = default;
+
+Dali::Toolkit::ParticleSystem::ParticleEmitter ParticleEffect::CreateEffectEmitter( EffectType effectType, Actor parentActor, const ParticleEffectParams& params )
+{
+ auto retval = gEffectInitializers[int(effectType)](params);
+ auto emitter = retval.emitter;
+
+ ParticleRenderer renderer = ParticleRenderer::New();
+
+ if(!params.strTexture.empty())
+ {
+ // Create texture
+ std::string filename(DEMO_IMAGE_DIR);
+ filename += params.strTexture;
+ Dali::PixelData pixelData = Dali::Toolkit::SyncImageLoader::Load(filename);
+ auto texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+ texture.Upload(pixelData);
+ renderer.SetTexture(texture);
+ }
+
+ emitter.AttachTo(std::move(parentActor));
+ emitter.SetEmissionRate( params.emissionRate ); // 20 particles emitted per second
+ emitter.SetParticleCount( params.particleCount );
+ emitter.SetSource( retval.source );
+ emitter.SetDomain( ParticleDomain::New() );
+ emitter.AddModifier(retval.modifier);
+ emitter.SetRenderer( renderer );
+ renderer.SetBlendingMode(Dali::Toolkit::ParticleSystem::BlendingMode::SCREEN);
+ emitter.SetInitialParticleCount( params.initialParticleCount );
+
+ return emitter;
+}
+
+
+}
+
diff --git a/examples/particle-system/effects/particle-effect.h b/examples/particle-system/effects/particle-effect.h
new file mode 100644
index 00000000..a1277ef2
--- /dev/null
+++ b/examples/particle-system/effects/particle-effect.h
@@ -0,0 +1,65 @@
+#ifndef DALI_PARTICLE_EFFECT_H
+#define DALI_PARTICLE_EFFECT_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <memory>
+
+namespace Dali::ParticleEffect
+{
+
+using EffectIndex = uint32_t;
+
+enum class EffectType
+{
+ FIRE_RING,
+ SPARKLES,
+ IMAGE_EXPLOSION
+};
+
+struct ParticleEffectParams
+{
+ uint32_t emissionRate;
+ uint32_t particleCount;
+ uint32_t initialParticleCount;
+ Vector2 sourceSize;
+ std::string strTexture;
+ std::string strImageSourceName;
+};
+
+/**
+ * Simple manager to spawn and control partcile emitters
+ */
+class ParticleEffect
+{
+public:
+
+ ParticleEffect();
+
+ ~ParticleEffect();
+
+ Dali::Toolkit::ParticleSystem::ParticleEmitter CreateEffectEmitter( EffectType effectType, Actor parentActor, const ParticleEffectParams& params );
+
+private:
+
+
+};
+}
+
+#endif // DALI_PARTICLE_MANAGER_H \ No newline at end of file
diff --git a/examples/particle-system/effects/sparkles-effect-modifier.cpp b/examples/particle-system/effects/sparkles-effect-modifier.cpp
new file mode 100644
index 00000000..dda93da9
--- /dev/null
+++ b/examples/particle-system/effects/sparkles-effect-modifier.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "sparkles-effect-modifier.h"
+#include "sparkles-effect-source.h"
+
+namespace Dali::ParticleEffect
+{
+static float LIFETIME = 3.0f;
+SparklesModifier::SparklesModifier(ParticleEmitter& emitter)
+: mEmitter(emitter)
+{
+}
+
+bool SparklesModifier::IsMultiThreaded()
+{
+ return true;
+}
+
+void SparklesModifier::Update(ParticleList& particleList, uint32_t first, uint32_t count)
+{
+ // If no acive particles return
+ if(!particleList.GetActiveParticleCount())
+ {
+ return;
+ }
+
+ mAngle = ((mAngle + 2) % 360);
+
+ // Retrieve the Source and get the stream
+ if(!mStreamBasePos)
+ {
+ mStreamBasePos = static_cast<SparklesSource*>(&mEmitter.GetSource().GetSourceCallback())->mStreamBasePos;
+ }
+ if(!mStreamBaseAngle)
+ {
+ mStreamBaseAngle = static_cast<SparklesSource*>(&mEmitter.GetSource().GetSourceCallback())->mStreamBaseAngle;
+ }
+
+ // Missing stream, return!
+ if(!mStreamBasePos)
+ {
+ return;
+ }
+
+ auto& activeParticles = particleList.GetActiveParticles();
+
+ auto it = activeParticles.begin();
+ std::advance(it, first);
+
+ for(; count; ++it, count--)
+ {
+ // Acquire stream data
+ auto& particle = *it;
+ auto& position = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
+ auto& velocity = particle.Get<Vector3>(ParticleStream::VELOCITY_STREAM_BIT);
+ auto& color = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
+ auto& scale = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
+
+ // Get base positions
+ [[maybe_unused]] auto& basePos = particle.GetByIndex<Vector3>(mStreamBasePos);
+
+ auto angle = particle.GetByIndex<float>(mStreamBaseAngle);
+ auto radians = ((angle * M_PI)/180.f);
+ float lifetime = particle.Get<float>(ParticleStream::LIFETIME_STREAM_BIT);
+ position.y += velocity.y *sin(radians);
+ position.x += velocity.x * cos(radians);
+
+ velocity *= 0.990f;
+ float normalizedTime = (lifetime / LIFETIME);
+ color.a = normalizedTime;
+ scale = Vector3(64.0f*(normalizedTime * normalizedTime * normalizedTime * normalizedTime), 64.0f*(normalizedTime * normalizedTime * normalizedTime * normalizedTime), 1.0);
+ }
+}
+} \ No newline at end of file
diff --git a/examples/particle-system/effects/sparkles-effect-modifier.h b/examples/particle-system/effects/sparkles-effect-modifier.h
new file mode 100644
index 00000000..1c64bd63
--- /dev/null
+++ b/examples/particle-system/effects/sparkles-effect-modifier.h
@@ -0,0 +1,54 @@
+#ifndef DALI_PARTICLES_SPARKLES_EFFECT_MODIFIER_H
+#define DALI_PARTICLES_SPARKLES_EFFECT_MODIFIER_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <ctime>
+
+namespace Dali::ParticleEffect
+{
+using namespace Dali::Toolkit::ParticleSystem;
+
+class SparklesModifier : public ParticleModifierInterface
+{
+public:
+
+ explicit SparklesModifier(ParticleEmitter& emitter);
+
+ bool IsMultiThreaded() override;
+
+ void Update(ParticleList& particleList, uint32_t first, uint32_t count) override;
+
+ ParticleEmitter mEmitter;
+ uint32_t mStreamBasePos{0u};
+ uint32_t mStreamBaseAngle{0u};
+ uint32_t mAngle{0u};
+};
+
+
+
+}
+
+#endif // DALI_PARTICLES_SPARKLES_EFFECT_MODIFIER_H
diff --git a/examples/particle-system/effects/sparkles-effect-source.cpp b/examples/particle-system/effects/sparkles-effect-source.cpp
new file mode 100644
index 00000000..56eb2987
--- /dev/null
+++ b/examples/particle-system/effects/sparkles-effect-source.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "sparkles-effect-source.h"
+
+namespace Dali::ParticleEffect
+{
+static float LIFETIME = 3.0f;
+SparklesSource::SparklesSource(ParticleEmitter& emitter)
+: mEmitter(emitter)
+{
+ std::time_t result = std::time(nullptr);
+ srand(result);
+ mRadius = Vector2::ONE;
+}
+
+SparklesSource::SparklesSource(ParticleEmitter& emitter, Dali::Vector2 ringRadius) :
+mEmitter(emitter)
+{
+ std::time_t result = std::time(nullptr);
+ srand(result);
+ mRadius = ringRadius;
+
+}
+
+void SparklesSource::Init()
+{
+ mStreamBasePos = mEmitter.GetParticleList().AddLocalStream<Vector3>(Vector3::ZERO);
+ mStreamBaseAngle = mEmitter.GetParticleList().AddLocalStream<float>(0.0f);
+}
+
+uint32_t SparklesSource::Update(ParticleList& particleList, uint32_t count)
+{
+ while(count--)
+ {
+ auto particle = particleList.NewParticle(LIFETIME);
+ if(!particle)
+ {
+ return 0u;
+ }
+
+ auto& basePosition = particle.GetByIndex<Vector3>(mStreamBasePos);
+ auto& angle = particle.GetByIndex<float>(mStreamBaseAngle);
+ auto& position = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
+ auto& color = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
+ auto& velocity = particle.Get<Vector3>(ParticleStream::VELOCITY_STREAM_BIT);
+ auto& scale = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
+
+
+ UpdateParticle(position, basePosition, color, velocity, scale, angle);
+ }
+
+ return 0;
+}
+
+void SparklesSource::UpdateParticle(Vector3& position, Vector3& basePosition, Vector4& color, Vector3& velocity, Vector3& scale, float& angle)
+{
+ static uint32_t a = 0.0f;
+ float posRadians = ((rand() % 360) * M_PI) / 180.0f;
+
+ basePosition.x = position.x = mRadius.x * sin(posRadians);
+ basePosition.y = position.y = mRadius.y * cos(posRadians);
+ color = Dali::Color::WHITE;
+
+ angle = float(a);
+ a = ((a+5)%360);
+ float rad = ((rand() % 360) * M_PI) / 180.0f;
+ float speed = ((rand() % 5) + 5);
+ velocity.x = sin(rad) * speed;
+ velocity.y = cos(rad) * speed;
+
+ // Random initial scale
+ float initialScale = float(rand() % 32) + 32;
+ scale = Vector3(initialScale, initialScale, 1);
+}
+
+} // namespace Dali::ParticleEffect \ No newline at end of file
diff --git a/examples/particle-system/effects/sparkles-effect-source.h b/examples/particle-system/effects/sparkles-effect-source.h
new file mode 100644
index 00000000..466c49b9
--- /dev/null
+++ b/examples/particle-system/effects/sparkles-effect-source.h
@@ -0,0 +1,56 @@
+#ifndef DALI_PARTICLES_SPARKLES_EFFECT_SOURCE_H
+#define DALI_PARTICLES_SPARKLES_EFFECT_SOURCE_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle.h>
+#include <ctime>
+
+namespace Dali::ParticleEffect
+{
+using namespace Dali::Toolkit::ParticleSystem;
+
+class SparklesSource : public Toolkit::ParticleSystem::ParticleSourceInterface
+{
+public:
+
+ explicit SparklesSource(ParticleEmitter& emitter);
+
+ explicit SparklesSource(ParticleEmitter& emitter, Dali::Vector2 ringRadius);
+
+ uint32_t Update(ParticleList& particleList, uint32_t count) override;
+
+ void Init() override;
+
+ void UpdateParticle(Vector3& position, Vector3& basePosition, Vector4& color, Vector3& velocity, Vector3& scale, float& angle);
+
+ ParticleEmitter mEmitter;
+
+ Dali::Vector2 mRadius;
+
+ uint32_t mStreamBasePos{0u};
+ uint32_t mStreamBaseAngle{0u};
+
+};
+
+}
+#endif // DALI_PARTICLES_SPARKLES_EFFECT_SOURCE_H
diff --git a/examples/particle-system/particle-system-example.cpp b/examples/particle-system/particle-system-example.cpp
new file mode 100644
index 00000000..7d6a8898
--- /dev/null
+++ b/examples/particle-system/particle-system-example.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/dali-toolkit.h>
+
+#include <dali-toolkit/public-api/particle-system/particle-emitter.h>
+#include <dali-toolkit/public-api/particle-system/particle-source.h>
+#include <dali-toolkit/public-api/particle-system/particle-domain.h>
+#include <dali-toolkit/public-api/particle-system/particle-list.h>
+#include <dali-toolkit/public-api/particle-system/particle-renderer.h>
+#include <dali-toolkit/public-api/particle-system/particle-types.h>
+
+#include <utility>
+#include <ctime>
+#include <dali-toolkit/public-api/particle-system/particle-modifier.h>
+#include <unistd.h>
+#include <map>
+
+#include "effects/particle-effect.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit::ParticleSystem;
+using namespace Dali::Toolkit;
+using Dali::Toolkit::TextLabel;
+
+using namespace Dali::ParticleEffect;
+
+/**
+ * This example shows Particle System feature
+ */
+class ParticleEffectController : public ConnectionTracker
+{
+public:
+
+ ParticleEffectController(Application& application)
+ : mApplication(application)
+ {
+ // Connect to the Application's Init signal
+ mApplication.InitSignal().Connect(this, &ParticleEffectController::Create);
+ }
+
+ ~ParticleEffectController() = default; // Nothing to do in destructor
+
+ template<class ButtonType>
+ ButtonType MakeButton( std::string title,
+ Vector2 position,
+ Vector2 size,
+ bool toggleable,
+ std::function<bool(Button)> onClick )
+ {
+ ButtonType button = ButtonType::New();
+ button.SetProperty( Button::Property::LABEL, title);
+ button.SetProperty( Actor::Property::POSITION, position);
+ button.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ button.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ button.SetProperty(Button::Property::TOGGLABLE, toggleable);
+ static std::map<RefObject*, std::function<bool(Button)>> callbackMap;
+ struct OnClick
+ {
+ static bool Slot(Button btn)
+ {
+ auto ptr = btn.GetObjectPtr();
+ return callbackMap[ptr](btn);
+ }
+ };
+
+ mUILastControlPosition = position;
+ mUILastControlSize = (size == Vector2::ZERO ? Vector2(button.GetNaturalSize()) : size);
+
+ callbackMap[button.GetObjectPtr()] = onClick;
+ button.ClickedSignal().Connect(OnClick::Slot);
+ return button;
+ }
+
+ // The Init signal is received once (only) during the Application lifetime
+ void Create(Application& application)
+ {
+ using namespace Dali::ParticleEffect;
+
+ // Get a handle to the window
+ Window window = application.GetWindow();
+ window.SetBackgroundColor(Color::BLACK);
+ {
+ Actor emitterActor = Actor::New();
+ emitterActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ emitterActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ emitterActor.SetProperty(Actor::Property::POSITION, Vector2(0.0, 0.0f));
+ emitterActor.SetProperty(Actor::Property::SIZE, Vector2(1.0, 1.0f));
+ window.Add(emitterActor);
+
+ mEmitterActor = emitterActor;
+ PushButton lastButton;
+ window.Add(
+ MakeButton<PushButton>("Fire Effect", Vector2::ZERO, {}, true, [&](Button button){
+
+ if(mCurrentEmitter)
+ {
+ mCurrentEmitter.Stop();
+ mCurrentEmitter.Reset();
+ }
+
+ ParticleEffectParams params{};
+ params.particleCount = 5000;
+ params.emissionRate = 1000;
+ params.initialParticleCount = 0;
+ params.sourceSize = Vector2(200, 10);
+ params.strTexture = "sparkle-part1.png";
+
+ mCurrentEmitter = mParticleSystem->CreateEffectEmitter( EffectType::FIRE_RING, mEmitterActor, params );
+ mCurrentEmitter.Start();
+ return true;
+ })
+ );
+
+ window.Add(
+ MakeButton<PushButton>("Sparkle Effect", Vector2(0.0f, mUILastControlSize.height), {}, true, [&](Button button){
+ if(mCurrentEmitter)
+ {
+ mCurrentEmitter.Stop();
+ mCurrentEmitter.Reset();
+ }
+
+ ParticleEffectParams params{};
+ params.particleCount = 10000;
+ params.emissionRate = 500;
+ params.initialParticleCount = 0;
+ params.sourceSize = Vector2(10, 10);
+ params.strTexture = "blue-part2.png";
+
+ mCurrentEmitter = mParticleSystem->CreateEffectEmitter( EffectType::SPARKLES, mEmitterActor, params );
+ mCurrentEmitter.Start();
+ return true;
+ })
+ );
+
+ window.Add(
+ MakeButton<PushButton>("Image Source Effect", Vector2(0.0f, mUILastControlPosition.y + mUILastControlSize.height), {}, true, [&](Button button){
+ if(mCurrentEmitter)
+ {
+ mCurrentEmitter.Stop();
+ mCurrentEmitter.Reset();
+ }
+
+ ParticleEffectParams params{};
+ params.particleCount = 20000;
+ params.emissionRate = 0;
+ params.initialParticleCount = 10;
+ params.sourceSize = Vector2(64, 64);
+ params.strImageSourceName = "particle-image-source.jpg";
+
+ mCurrentEmitter = mParticleSystem->CreateEffectEmitter( EffectType::IMAGE_EXPLOSION, mEmitterActor, params );
+ mCurrentEmitter.Start();
+ return true;
+ })
+ );
+ window.Add(
+ MakeButton<PushButton>("Quit", Vector2(0.0f, mUILastControlPosition.y + mUILastControlSize.height * 2), {}, true, [&](Button button){
+ if(mCurrentEmitter)
+ {
+ mCurrentEmitter.Stop();
+ mCurrentEmitter.Reset();
+ }
+ mApplication.Quit();
+ return true;
+ })
+ );
+ }
+
+ // Respond to key events
+ window.KeyEventSignal().Connect(this, &ParticleEffectController::OnKeyEvent);
+ }
+
+ void OnKeyEvent(const KeyEvent& event)
+ {
+ if(event.GetState() == KeyEvent::DOWN)
+ {
+ if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
+ {
+ mApplication.Quit();
+ }
+ }
+ }
+
+private:
+
+ Application& mApplication;
+ std::unique_ptr<Dali::ParticleEffect::ParticleEffect> mParticleSystem;
+ ParticleEmitter mCurrentEmitter;
+ Actor mEmitterActor;
+
+ // Needed for buttons
+ Vector2 mUILastControlPosition;
+ Vector2 mUILastControlSize;
+
+};
+
+int DALI_EXPORT_API main(int argc, char** argv)
+{
+ Application application = Application::New(&argc, &argv);
+ ParticleEffectController test(application);
+ application.MainLoop();
+ return 0;
+}