2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali-test-suite-utils.h>
19 #include <dali-toolkit/public-api/particle-system/particle-domain.h>
20 #include <dali-toolkit/public-api/particle-system/particle-emitter.h>
21 #include <dali-toolkit/public-api/particle-system/particle-list.h>
22 #include <dali-toolkit/public-api/particle-system/particle-modifier.h>
23 #include <dali-toolkit/public-api/particle-system/particle-renderer.h>
24 #include <dali-toolkit/public-api/particle-system/particle-source.h>
25 #include <dali-toolkit/public-api/particle-system/particle.h>
32 using namespace Dali::Toolkit::ParticleSystem;
35 * Helper function to invoke next function in the call chain
37 template<class R, class T, class... Args>
38 R InvokeNext(T* pObj, Args... args)
41 dladdr(__builtin_return_address(0), &info);
42 using Func = R (*)(T*, Args...);
43 auto sym = (Func)(dlsym(RTLD_NEXT, info.dli_sname));
44 return sym(pObj, args...);
47 static std::chrono::milliseconds currentTime(1u);
48 static void AdvanceTimeByMs(uint32_t ms)
50 currentTime += std::chrono::milliseconds(ms);
53 namespace Dali::Toolkit::ParticleSystem::Internal
55 // Create fake time getter
56 struct ParticleEmitter
58 [[nodiscard]] std::chrono::milliseconds GetCurrentTimeMillis() const;
60 std::chrono::milliseconds ParticleEmitter::GetCurrentTimeMillis() const
62 [[maybe_unused]] auto value = InvokeNext<std::chrono::milliseconds>(this);
63 return std::chrono::milliseconds(currentTime);
65 } // namespace Dali::Toolkit::ParticleSystem::Internal
67 using ParticleEmitterWrapper = Dali::Toolkit::ParticleSystem::Internal::ParticleEmitter;
69 Texture CreateTexture()
71 Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, 100, 100);
72 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(100 * 100 * 4));
73 PixelData pixelData = PixelData::New(data, 100 * 100 * 4, 100, 100, Pixel::Format::RGBA8888, PixelData::FREE);
74 texture.Upload(pixelData);
79 * Test particle source
81 class TestSource : public ParticleSourceInterface
84 TestSource(ParticleEmitter* emitter)
91 mPromise = std::promise<uint32_t>();
92 mFuture = mPromise.get_future();
95 uint32_t Update(ParticleList& outList, uint32_t count) override
97 mPromise.set_value(count);
101 outList.NewParticle(1.0f);
112 bool mInitialized{false};
113 std::future<uint32_t> mFuture;
114 std::promise<uint32_t> mPromise;
115 ParticleEmitter& mEmitter;
118 class TestSource2 : public ParticleSourceInterface
121 TestSource2(ParticleEmitter* emitter)
128 mPromise = std::promise<uint32_t>();
129 mFuture = mPromise.get_future();
132 uint32_t Update(ParticleList& outList, uint32_t count) override
134 mPromise.set_value(count);
138 auto particle = outList.NewParticle(1.0);
144 [[maybe_unused]] auto& pos = particle.GetByIndex<Vector3>(mStreamBasePos);
146 [[maybe_unused]] auto& gpos = particle.Get<Vector3>(ParticleStream::POSITION_STREAM_BIT);
147 [[maybe_unused]] auto& col = particle.Get<Vector4>(ParticleStream::COLOR_STREAM_BIT);
148 [[maybe_unused]] auto& vel = particle.Get<Vector3>(ParticleStream::VELOCITY_STREAM_BIT);
149 [[maybe_unused]] auto& sca = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
150 //auto& basePos = particle.Get<Vector3>(ParticleStream::SCALE_STREAM_BIT);
159 mStreamBasePos = mEmitter.GetParticleList().AddLocalStream<Vector3>(Vector3::ZERO);
163 bool mInitialized{false};
164 std::future<uint32_t> mFuture;
165 std::promise<uint32_t> mPromise;
166 uint32_t mStreamBasePos{0u};
167 ParticleEmitter& mEmitter;
170 * Sample of FlameModifier
172 struct TestModifier : public ParticleModifierInterface
174 void Update(ParticleList& particleList, uint32_t firstParticleIndex, uint32_t particleCount) override
179 struct TestModifierMT : public ParticleModifierInterface
181 void Update(ParticleList& particleList, uint32_t firstParticleIndex, uint32_t particleCount) override
185 bool IsMultiThreaded() override
192 * Another modifier to test modifier stack
194 struct TestModifier2 : public ParticleModifierInterface
196 void Update(ParticleList& particleList, uint32_t firstParticleIndex, uint32_t particleCount) override
203 ParticleEmitter emitter;
204 ParticleRenderer renderer;
205 ParticleModifier modifier;
206 ParticleSource source;
209 // Helper function to create emitter (every test will be doing that)
210 template<class SOURCE, class MODIFIER>
211 ParticleEmitter CreateEmitter(EmitterGroup* output = nullptr)
213 auto emitter = ParticleEmitter::New();
215 bool result = (emitter != nullptr);
216 DALI_TEST_EQUALS(result, true, TEST_LOCATION);
218 // Create test source
219 auto source = ParticleSource::New<SOURCE>(&emitter);
222 BaseHandle handle(source);
223 auto newHandle = ParticleSource::DownCast(handle);
224 DALI_TEST_EQUALS(newHandle, source, TEST_LOCATION);
227 // Create test renderer
228 auto renderer = ParticleRenderer::New();
231 BaseHandle handle(renderer);
232 auto newHandle = ParticleRenderer::DownCast(handle);
233 DALI_TEST_EQUALS(newHandle, renderer, TEST_LOCATION);
237 auto modifier = ParticleModifier::New<MODIFIER>();
240 BaseHandle handle(modifier);
241 auto newHandle = ParticleModifier::DownCast(handle);
242 DALI_TEST_EQUALS(newHandle, modifier, TEST_LOCATION);
245 auto domain = ParticleDomain::New();
248 BaseHandle handle(domain);
249 auto newHandle = ParticleDomain::DownCast(handle);
250 DALI_TEST_EQUALS(newHandle, domain, TEST_LOCATION);
253 // Test emitter readiness
254 auto ready = emitter.GetStatus();
256 // Emitter should return status incomplete
257 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
259 // Attach all components to the emitter
260 emitter.SetSource(source);
261 emitter.SetRenderer(renderer);
262 emitter.AddModifier(modifier);
263 emitter.SetDomain(domain);
265 auto domain0 = emitter.GetDomain();
266 auto renderer0 = emitter.GetRenderer();
268 DALI_TEST_EQUALS(renderer0, renderer, TEST_LOCATION);
269 DALI_TEST_EQUALS(domain0, domain, TEST_LOCATION);
273 output->emitter = emitter;
274 output->renderer = renderer;
275 output->modifier = modifier;
276 output->source = source;
282 int UtcDaliParticleSystemEmitterNew(void)
284 // create particle emitter
285 auto emitter = ParticleEmitter::New();
287 bool result = (emitter != nullptr);
288 DALI_TEST_EQUALS(result, true, TEST_LOCATION);
290 // Create test source
291 auto source = ParticleSource::New<TestSource>(&emitter);
293 // Create test renderer
294 auto renderer = ParticleRenderer::New();
297 auto modifier = ParticleModifier::New<TestModifier>();
300 auto domain = ParticleDomain::New();
302 // Test emitter readiness
303 auto ready = emitter.GetStatus();
305 // Emitter should return status incomplete
306 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
308 // Attach all components to the emitter
309 emitter.SetSource(source);
310 emitter.SetRenderer(renderer);
311 emitter.AddModifier(modifier);
312 emitter.SetDomain(domain);
314 // test status again (domain is optional);
315 ready = emitter.GetStatus();
317 // Emitter should return status incomplete
318 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
323 int UtcDaliParticleSystemEmitterModifierStack(void)
325 // create particle emitter
326 auto emitter = ParticleEmitter::New();
328 bool result = (emitter != nullptr);
329 DALI_TEST_EQUALS(result, true, TEST_LOCATION);
331 // Create test source
332 auto source = ParticleSource::New<TestSource>(&emitter);
334 // Create test renderer
335 auto renderer = ParticleRenderer::New();
338 auto modifier0 = ParticleModifier::New<TestModifier>();
339 auto modifier1 = ParticleModifier::New<TestModifier>();
340 auto modifier2 = ParticleModifier::New<TestModifier>();
343 auto domain = ParticleDomain::New();
345 // Test emitter readiness
346 auto ready = emitter.GetStatus();
348 // Emitter should return status incomplete
349 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
351 // Attach all components to the emitter
352 emitter.SetSource(source);
353 emitter.SetRenderer(renderer);
354 emitter.AddModifier(modifier0);
355 emitter.AddModifier(modifier1);
356 emitter.AddModifier(modifier2);
358 emitter.SetDomain(domain);
360 // test status again (domain is optional);
361 ready = emitter.GetStatus();
363 // Emitter should return status incomplete
364 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
366 auto modifier = emitter.GetModifierAt(1);
367 DALI_TEST_EQUALS(modifier, modifier1, TEST_LOCATION);
369 emitter.RemoveModifierAt(0);
370 modifier = emitter.GetModifierAt(0);
371 DALI_TEST_EQUALS(modifier, modifier1, TEST_LOCATION);
376 int UtcDaliParticleSystemTest(void)
378 TestApplication application;
380 // Create actor to be used with emitter
381 Actor actor = Actor::New();
382 application.GetScene().Add(actor);
383 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
385 auto emitter = CreateEmitter<TestSource, TestModifier>();
387 // test status again (domain is optional);
388 auto ready = emitter.GetStatus();
390 // Emitter should return status incomplete
391 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
393 // Set initial parameters of system
394 emitter.SetInitialParticleCount(1000);
395 emitter.SetActiveParticlesLimit(5000);
398 auto initialParticleCount = emitter.GetInitialParticleCount();
399 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
401 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
402 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
404 // Attach emitter to actor
405 emitter.AttachTo(actor);
410 auto status = emitter.GetStatus();
411 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
413 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
416 sourceCallback.NewFrame();
417 application.SendNotification();
418 application.Render();
420 // First call into source callback should emit initial number of particles
421 auto emittedParticleCount = sourceCallback.mFuture.get();
422 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
424 // Run 3 more frames advancing by 1000ms which should
425 // emit particles based on emission rate
426 AdvanceTimeByMs(1000);
428 sourceCallback.NewFrame();
429 application.SendNotification();
430 application.Render();
432 AdvanceTimeByMs(1000);
434 sourceCallback.NewFrame();
435 application.SendNotification();
436 application.Render();
438 AdvanceTimeByMs(1000);
440 sourceCallback.NewFrame();
441 application.SendNotification();
442 application.Render();
447 int UtcDaliParticleSystemTestWithTextureScreen(void)
449 TestApplication application;
451 // Create actor to be used with emitter
452 Actor actor = Actor::New();
453 application.GetScene().Add(actor);
454 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
458 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
460 // Blending mode with screen
461 auto texture = CreateTexture();
462 group.renderer.SetTexture(texture);
463 group.renderer.SetBlendingMode(BlendingMode::SCREEN);
465 // test status again (domain is optional);
466 auto ready = emitter.GetStatus();
468 // Emitter should return status incomplete
469 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
471 // Set initial parameters of system
472 emitter.SetInitialParticleCount(1000);
473 emitter.SetActiveParticlesLimit(5000);
476 auto initialParticleCount = emitter.GetInitialParticleCount();
477 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
479 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
480 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
482 // Attach emitter to actor
483 emitter.AttachTo(actor);
488 auto status = emitter.GetStatus();
489 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
491 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
494 sourceCallback.NewFrame();
495 application.SendNotification();
496 application.Render();
498 // First call into source callback should emit initial number of particles
499 auto emittedParticleCount = sourceCallback.mFuture.get();
500 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
502 // Run 3 more frames advancing by 1000ms which should
503 // emit particles based on emission rate
504 AdvanceTimeByMs(1000);
506 sourceCallback.NewFrame();
507 application.SendNotification();
508 application.Render();
510 AdvanceTimeByMs(1000);
512 sourceCallback.NewFrame();
513 application.SendNotification();
514 application.Render();
516 AdvanceTimeByMs(1000);
518 sourceCallback.NewFrame();
519 application.SendNotification();
520 application.Render();
525 int UtcDaliParticleSystemTestWithTextureAdd(void)
527 TestApplication application;
529 // Create actor to be used with emitter
530 Actor actor = Actor::New();
531 application.GetScene().Add(actor);
532 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
536 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
538 // Blending mode with screen
539 auto texture = CreateTexture();
540 group.renderer.SetTexture(texture);
541 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
543 // test status again (domain is optional);
544 auto ready = emitter.GetStatus();
546 // Emitter should return status incomplete
547 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
549 // Set initial parameters of system
550 emitter.SetInitialParticleCount(1000);
551 emitter.SetActiveParticlesLimit(5000);
554 auto initialParticleCount = emitter.GetInitialParticleCount();
555 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
557 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
558 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
560 // Attach emitter to actor
561 emitter.AttachTo(actor);
566 auto status = emitter.GetStatus();
567 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
569 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
572 sourceCallback.NewFrame();
573 application.SendNotification();
574 application.Render();
576 // First call into source callback should emit initial number of particles
577 auto emittedParticleCount = sourceCallback.mFuture.get();
578 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
580 // Run 3 more frames advancing by 1000ms which should
581 // emit particles based on emission rate
582 AdvanceTimeByMs(1000);
584 sourceCallback.NewFrame();
585 application.SendNotification();
586 application.Render();
588 AdvanceTimeByMs(1000);
590 sourceCallback.NewFrame();
591 application.SendNotification();
592 application.Render();
594 AdvanceTimeByMs(1000);
596 sourceCallback.NewFrame();
597 application.SendNotification();
598 application.Render();
603 int UtcDaliParticleSystemTestInitialSetup(void)
605 TestApplication application;
607 // Create actor to be used with emitter
608 Actor actor = Actor::New();
609 application.GetScene().Add(actor);
610 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
614 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
616 emitter.SetEmissionRate(1000);
617 emitter.SetInitialParticleCount(1000);
618 emitter.SetActiveParticlesLimit(10000);
620 auto emissionRate = emitter.GetEmissionRate();
621 auto initialCount = emitter.GetInitialParticleCount();
622 auto activeCount = emitter.GetActiveParticlesLimit();
624 DALI_TEST_EQUALS(emissionRate, 1000, TEST_LOCATION);
625 DALI_TEST_EQUALS(initialCount, 1000, TEST_LOCATION);
626 DALI_TEST_EQUALS(activeCount, 10000, TEST_LOCATION);
628 // Blending mode with screen
629 auto texture = CreateTexture();
630 group.renderer.SetTexture(texture);
631 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
633 // test status again (domain is optional);
634 auto ready = emitter.GetStatus();
636 // Emitter should return status incomplete
637 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
639 // Set initial parameters of system
640 emitter.SetInitialParticleCount(1000);
641 emitter.SetActiveParticlesLimit(5000);
644 auto initialParticleCount = emitter.GetInitialParticleCount();
645 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
647 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
648 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
650 // Attach emitter to actor
651 emitter.AttachTo(actor);
656 auto status = emitter.GetStatus();
657 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
659 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
662 sourceCallback.NewFrame();
663 application.SendNotification();
664 application.Render();
666 // First call into source callback should emit initial number of particles
667 auto emittedParticleCount = sourceCallback.mFuture.get();
668 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
670 // Run 3 more frames advancing by 1000ms which should
671 // emit particles based on emission rate
672 AdvanceTimeByMs(1000);
674 sourceCallback.NewFrame();
675 application.SendNotification();
676 application.Render();
678 AdvanceTimeByMs(1000);
680 sourceCallback.NewFrame();
681 application.SendNotification();
682 application.Render();
684 AdvanceTimeByMs(1000);
686 sourceCallback.NewFrame();
687 application.SendNotification();
688 application.Render();
693 int UtcDaliParticleSystemTestMT(void)
695 TestApplication application;
697 // Create actor to be used with emitter
698 Actor actor = Actor::New();
699 application.GetScene().Add(actor);
700 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
704 auto emitter = CreateEmitter<TestSource, TestModifierMT>(&group);
706 emitter.SetEmissionRate(10000);
707 emitter.SetInitialParticleCount(10000);
708 emitter.SetActiveParticlesLimit(20000);
709 emitter.SetParticleCount(300000);
711 auto emissionRate = emitter.GetEmissionRate();
712 auto initialCount = emitter.GetInitialParticleCount();
713 auto activeCount = emitter.GetActiveParticlesLimit();
715 DALI_TEST_EQUALS(emissionRate, 10000, TEST_LOCATION);
716 DALI_TEST_EQUALS(initialCount, 10000, TEST_LOCATION);
717 DALI_TEST_EQUALS(activeCount, 20000, TEST_LOCATION);
719 emitter.EnableParallelProcessing(true);
721 auto mtEnabled = emitter.IsParallelProcessingEnabled();
722 DALI_TEST_EQUALS(mtEnabled, true, TEST_LOCATION);
724 // Blending mode with screen
725 auto texture = CreateTexture();
726 group.renderer.SetTexture(texture);
727 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
729 // test status again (domain is optional);
730 auto ready = emitter.GetStatus();
732 // Emitter should return status incomplete
733 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
735 // Attach emitter to actor
736 emitter.AttachTo(actor);
741 auto status = emitter.GetStatus();
742 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
744 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
747 sourceCallback.NewFrame();
748 application.SendNotification();
749 application.Render();
751 // First call into source callback should emit initial number of particles
752 auto emittedParticleCount = sourceCallback.mFuture.get();
753 DALI_TEST_EQUALS(emittedParticleCount, 10000, TEST_LOCATION);
755 // Run 3 more frames advancing by 1000ms which should
756 // emit particles based on emission rate
757 AdvanceTimeByMs(1000);
759 sourceCallback.NewFrame();
760 application.SendNotification();
761 application.Render();
763 AdvanceTimeByMs(1000);
765 sourceCallback.NewFrame();
766 application.SendNotification();
767 application.Render();
769 AdvanceTimeByMs(1000);
771 sourceCallback.NewFrame();
772 application.SendNotification();
773 application.Render();
778 int UtcDaliParticleSystemTestParticleSource(void)
780 TestApplication application;
782 // Create actor to be used with emitter
783 Actor actor = Actor::New();
784 application.GetScene().Add(actor);
785 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
789 auto emitter = CreateEmitter<TestSource2, TestModifier>(&group);
791 emitter.SetEmissionRate(1000);
792 emitter.SetInitialParticleCount(1000);
793 emitter.SetActiveParticlesLimit(10000);
795 auto emissionRate = emitter.GetEmissionRate();
796 auto initialCount = emitter.GetInitialParticleCount();
797 auto activeCount = emitter.GetActiveParticlesLimit();
799 DALI_TEST_EQUALS(emissionRate, 1000, TEST_LOCATION);
800 DALI_TEST_EQUALS(initialCount, 1000, TEST_LOCATION);
801 DALI_TEST_EQUALS(activeCount, 10000, TEST_LOCATION);
803 emitter.EnableParallelProcessing(true);
805 // Blending mode with screen
806 auto texture = CreateTexture();
807 group.renderer.SetTexture(texture);
808 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
810 // test status again (domain is optional);
811 auto ready = emitter.GetStatus();
813 // Emitter should return status incomplete
814 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
816 // Set initial parameters of system
817 emitter.SetInitialParticleCount(1000);
818 emitter.SetActiveParticlesLimit(5000);
821 auto initialParticleCount = emitter.GetInitialParticleCount();
822 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
824 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
825 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
827 // Attach emitter to actor
828 emitter.AttachTo(actor);
833 auto status = emitter.GetStatus();
834 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
836 auto& sourceCallback = static_cast<TestSource2&>(emitter.GetSource().GetSourceCallback());
839 sourceCallback.NewFrame();
840 application.SendNotification();
841 application.Render();
843 // First call into source callback should emit initial number of particles
844 auto emittedParticleCount = sourceCallback.mFuture.get();
845 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
847 // Run 3 more frames advancing by 1000ms which should
848 // emit particles based on emission rate
849 AdvanceTimeByMs(1000);
851 sourceCallback.NewFrame();
852 application.SendNotification();
853 application.Render();
855 AdvanceTimeByMs(1000);
857 sourceCallback.NewFrame();
858 application.SendNotification();
859 application.Render();
861 AdvanceTimeByMs(1000);
863 sourceCallback.NewFrame();
864 application.SendNotification();
865 application.Render();
870 sourceCallback.NewFrame();
871 application.SendNotification();
872 application.Render();
877 int UtcDaliParticleSystemReplaceEmitter(void)
879 TestApplication application;
881 // Create actor to be used with emitter
882 Actor actor = Actor::New();
883 application.GetScene().Add(actor);
884 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
888 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
890 // Blending mode with screen
891 auto texture = CreateTexture();
892 group.renderer.SetTexture(texture);
893 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
895 // test status again (domain is optional);
896 auto ready = emitter.GetStatus();
898 // Emitter should return status incomplete
899 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
901 // Set initial parameters of system
902 emitter.SetInitialParticleCount(1000);
903 emitter.SetActiveParticlesLimit(5000);
906 auto initialParticleCount = emitter.GetInitialParticleCount();
907 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
909 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
910 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
912 // Attach emitter to actor
913 emitter.AttachTo(actor);
918 auto status = emitter.GetStatus();
919 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
921 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
924 sourceCallback.NewFrame();
925 application.SendNotification();
926 application.Render();
928 // First call into source callback should emit initial number of particles
929 auto emittedParticleCount = sourceCallback.mFuture.get();
930 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
932 // Run 3 more frames advancing by 1000ms which should
933 // emit particles based on emission rate
934 AdvanceTimeByMs(1000);
936 sourceCallback.NewFrame();
937 application.SendNotification();
938 application.Render();
940 AdvanceTimeByMs(1000);
942 sourceCallback.NewFrame();
943 application.SendNotification();
944 application.Render();
946 AdvanceTimeByMs(1000);
948 sourceCallback.NewFrame();
949 application.SendNotification();
950 application.Render();
953 auto oldEmitter = emitter.GetObjectPtr(); // store old emitter
954 [[maybe_unused]] auto i = oldEmitter->ReferenceCount();
958 emitter = CreateEmitter<TestSource, TestModifier>(&group);
959 DALI_TEST_EQUALS(bool(emitter.GetObjectPtr() != oldEmitter), true, TEST_LOCATION);