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 UtcDaliParticleSystemEmitterNew2(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 modifier = ParticleModifier::New<TestModifier>();
341 auto domain = ParticleDomain::New();
343 // Test emitter readiness
344 auto ready = emitter.GetStatus();
346 // Emitter should return status incomplete
347 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
349 // Attach all components to the emitter
350 emitter.SetSource(source);
351 emitter.SetRenderer(renderer);
352 emitter.AddModifier(modifier);
353 emitter.SetDomain(domain);
355 // test blending mode
356 DALI_TEST_EQUALS(renderer.GetBlendingMode(), Dali::Toolkit::ParticleSystem::BlendingMode::DEFAULT, TEST_LOCATION);
358 emitter.SetParticleCount(10000);
359 DALI_TEST_EQUALS(emitter.GetParticleCount(), 10000, TEST_LOCATION);
361 auto m = emitter.GetModifierAt(0);
362 DALI_TEST_EQUALS(m != nullptr, true, TEST_LOCATION);
364 m.GetModifierCallback();
366 // test status again (domain is optional);
367 ready = emitter.GetStatus();
369 // Emitter should return status incomplete
370 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
375 int UtcDaliParticleSystemEmitterDefaultStreams(void)
377 // create particle emitter
378 auto emitter = ParticleEmitter::New();
380 bool result = (emitter != nullptr);
381 DALI_TEST_EQUALS(result, true, TEST_LOCATION);
383 // Create test source
384 auto source = ParticleSource::New<TestSource>(&emitter);
386 // Create test renderer
387 auto renderer = ParticleRenderer::New();
390 auto modifier = ParticleModifier::New<TestModifier>();
393 auto domain = ParticleDomain::New();
395 // Test emitter readiness
396 auto ready = emitter.GetStatus();
398 // Emitter should return status incomplete
399 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
401 // Attach all components to the emitter
402 emitter.SetSource(source);
403 emitter.SetRenderer(renderer);
404 emitter.AddModifier(modifier);
405 emitter.SetDomain(domain);
407 auto particleList = emitter.GetParticleList();
408 std::vector<uint32_t> expectedValues = {
409 ParticleStream::POSITION_STREAM_BIT, 0, ParticleStream::COLOR_STREAM_BIT, 3, ParticleStream::VELOCITY_STREAM_BIT, 2, ParticleStream::SCALE_STREAM_BIT, 1, ParticleStream::LIFETIME_STREAM_BIT, 4, ParticleStream::LIFETIME_BASE_STREAM_BIT, 5};
411 for(auto i = 0u; i < expectedValues.size(); i += 2)
413 auto index = particleList.GetDefaultStreamIndex(expectedValues[i]);
414 DALI_TEST_EQUALS(index, expectedValues[i + 1], TEST_LOCATION);
417 // test status again (domain is optional);
418 ready = emitter.GetStatus();
420 // Emitter should return status incomplete
421 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
426 int UtcDaliParticleSystemEmitterModifierStack(void)
428 // create particle emitter
429 auto emitter = ParticleEmitter::New();
431 bool result = (emitter != nullptr);
432 DALI_TEST_EQUALS(result, true, TEST_LOCATION);
434 // Create test source
435 auto source = ParticleSource::New<TestSource>(&emitter);
437 // Create test renderer
438 auto renderer = ParticleRenderer::New();
441 auto modifier0 = ParticleModifier::New<TestModifier>();
442 auto modifier1 = ParticleModifier::New<TestModifier>();
443 auto modifier2 = ParticleModifier::New<TestModifier>();
446 auto domain = ParticleDomain::New();
448 // Test emitter readiness
449 auto ready = emitter.GetStatus();
451 // Emitter should return status incomplete
452 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::INCOMPLETE, TEST_LOCATION);
454 // Attach all components to the emitter
455 emitter.SetSource(source);
456 emitter.SetRenderer(renderer);
457 emitter.AddModifier(modifier0);
458 emitter.AddModifier(modifier1);
459 emitter.AddModifier(modifier2);
461 emitter.SetDomain(domain);
463 // test status again (domain is optional);
464 ready = emitter.GetStatus();
466 // Emitter should return status incomplete
467 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
469 auto modifier = emitter.GetModifierAt(1);
470 DALI_TEST_EQUALS(modifier, modifier1, TEST_LOCATION);
472 emitter.RemoveModifierAt(0);
473 modifier = emitter.GetModifierAt(0);
474 DALI_TEST_EQUALS(modifier, modifier1, TEST_LOCATION);
479 int UtcDaliParticleSystemTest(void)
481 TestApplication application;
483 // Create actor to be used with emitter
484 Actor actor = Actor::New();
485 application.GetScene().Add(actor);
486 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
488 auto emitter = CreateEmitter<TestSource, TestModifier>();
490 // test status again (domain is optional);
491 auto ready = emitter.GetStatus();
493 // Emitter should return status incomplete
494 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
496 // Set initial parameters of system
497 emitter.SetInitialParticleCount(1000);
498 emitter.SetActiveParticlesLimit(5000);
501 auto initialParticleCount = emitter.GetInitialParticleCount();
502 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
504 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
505 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
507 // Attach emitter to actor
508 emitter.AttachTo(actor);
513 auto status = emitter.GetStatus();
514 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
516 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
519 sourceCallback.NewFrame();
520 application.SendNotification();
521 application.Render();
523 // First call into source callback should emit initial number of particles
524 auto emittedParticleCount = sourceCallback.mFuture.get();
525 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
527 // Run 3 more frames advancing by 1000ms which should
528 // emit particles based on emission rate
529 AdvanceTimeByMs(1000);
531 sourceCallback.NewFrame();
532 application.SendNotification();
533 application.Render();
535 AdvanceTimeByMs(1000);
537 sourceCallback.NewFrame();
538 application.SendNotification();
539 application.Render();
541 AdvanceTimeByMs(1000);
543 sourceCallback.NewFrame();
544 application.SendNotification();
545 application.Render();
550 int UtcDaliParticleSystemTestWithTextureScreen(void)
552 TestApplication application;
554 // Create actor to be used with emitter
555 Actor actor = Actor::New();
556 application.GetScene().Add(actor);
557 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
561 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
563 // Blending mode with screen
564 auto texture = CreateTexture();
565 group.renderer.SetTexture(texture);
566 group.renderer.SetBlendingMode(BlendingMode::SCREEN);
568 // test status again (domain is optional);
569 auto ready = emitter.GetStatus();
571 // Emitter should return status incomplete
572 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
574 // Set initial parameters of system
575 emitter.SetInitialParticleCount(1000);
576 emitter.SetActiveParticlesLimit(5000);
579 auto initialParticleCount = emitter.GetInitialParticleCount();
580 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
582 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
583 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
585 // Attach emitter to actor
586 emitter.AttachTo(actor);
591 auto status = emitter.GetStatus();
592 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
594 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
597 sourceCallback.NewFrame();
598 application.SendNotification();
599 application.Render();
601 // First call into source callback should emit initial number of particles
602 auto emittedParticleCount = sourceCallback.mFuture.get();
603 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
605 // Run 3 more frames advancing by 1000ms which should
606 // emit particles based on emission rate
607 AdvanceTimeByMs(1000);
609 sourceCallback.NewFrame();
610 application.SendNotification();
611 application.Render();
613 AdvanceTimeByMs(1000);
615 sourceCallback.NewFrame();
616 application.SendNotification();
617 application.Render();
619 AdvanceTimeByMs(1000);
621 sourceCallback.NewFrame();
622 application.SendNotification();
623 application.Render();
628 int UtcDaliParticleSystemTestWithTextureAdd(void)
630 TestApplication application;
632 // Create actor to be used with emitter
633 Actor actor = Actor::New();
634 application.GetScene().Add(actor);
635 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
639 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
641 // Blending mode with screen
642 auto texture = CreateTexture();
643 group.renderer.SetTexture(texture);
644 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
646 // test status again (domain is optional);
647 auto ready = emitter.GetStatus();
649 // Emitter should return status incomplete
650 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
652 // Set initial parameters of system
653 emitter.SetInitialParticleCount(1000);
654 emitter.SetActiveParticlesLimit(5000);
657 auto initialParticleCount = emitter.GetInitialParticleCount();
658 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
660 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
661 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
663 // Attach emitter to actor
664 emitter.AttachTo(actor);
669 auto status = emitter.GetStatus();
670 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
672 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
675 sourceCallback.NewFrame();
676 application.SendNotification();
677 application.Render();
679 // First call into source callback should emit initial number of particles
680 auto emittedParticleCount = sourceCallback.mFuture.get();
681 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
683 // Run 3 more frames advancing by 1000ms which should
684 // emit particles based on emission rate
685 AdvanceTimeByMs(1000);
687 sourceCallback.NewFrame();
688 application.SendNotification();
689 application.Render();
691 AdvanceTimeByMs(1000);
693 sourceCallback.NewFrame();
694 application.SendNotification();
695 application.Render();
697 AdvanceTimeByMs(1000);
699 sourceCallback.NewFrame();
700 application.SendNotification();
701 application.Render();
706 int UtcDaliParticleSystemTestInitialSetup(void)
708 TestApplication application;
710 // Create actor to be used with emitter
711 Actor actor = Actor::New();
712 application.GetScene().Add(actor);
713 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
717 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
719 emitter.SetEmissionRate(1000);
720 emitter.SetInitialParticleCount(1000);
721 emitter.SetActiveParticlesLimit(10000);
723 auto emissionRate = emitter.GetEmissionRate();
724 auto initialCount = emitter.GetInitialParticleCount();
725 auto activeCount = emitter.GetActiveParticlesLimit();
727 DALI_TEST_EQUALS(emissionRate, 1000, TEST_LOCATION);
728 DALI_TEST_EQUALS(initialCount, 1000, TEST_LOCATION);
729 DALI_TEST_EQUALS(activeCount, 10000, TEST_LOCATION);
731 // Blending mode with screen
732 auto texture = CreateTexture();
733 group.renderer.SetTexture(texture);
734 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
736 // test status again (domain is optional);
737 auto ready = emitter.GetStatus();
739 // Emitter should return status incomplete
740 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
742 // Set initial parameters of system
743 emitter.SetInitialParticleCount(1000);
744 emitter.SetActiveParticlesLimit(5000);
747 auto initialParticleCount = emitter.GetInitialParticleCount();
748 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
750 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
751 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
753 // Attach emitter to actor
754 emitter.AttachTo(actor);
759 auto status = emitter.GetStatus();
760 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
762 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
765 sourceCallback.NewFrame();
766 application.SendNotification();
767 application.Render();
769 // First call into source callback should emit initial number of particles
770 auto emittedParticleCount = sourceCallback.mFuture.get();
771 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
773 // Run 3 more frames advancing by 1000ms which should
774 // emit particles based on emission rate
775 AdvanceTimeByMs(1000);
777 sourceCallback.NewFrame();
778 application.SendNotification();
779 application.Render();
781 AdvanceTimeByMs(1000);
783 sourceCallback.NewFrame();
784 application.SendNotification();
785 application.Render();
787 AdvanceTimeByMs(1000);
789 sourceCallback.NewFrame();
790 application.SendNotification();
791 application.Render();
796 int UtcDaliParticleSystemTestMT(void)
798 TestApplication application;
800 // Create actor to be used with emitter
801 Actor actor = Actor::New();
802 application.GetScene().Add(actor);
803 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
807 auto emitter = CreateEmitter<TestSource, TestModifierMT>(&group);
809 emitter.SetEmissionRate(10000);
810 emitter.SetInitialParticleCount(10000);
811 emitter.SetActiveParticlesLimit(20000);
812 emitter.SetParticleCount(300000);
814 auto emissionRate = emitter.GetEmissionRate();
815 auto initialCount = emitter.GetInitialParticleCount();
816 auto activeCount = emitter.GetActiveParticlesLimit();
818 DALI_TEST_EQUALS(emissionRate, 10000, TEST_LOCATION);
819 DALI_TEST_EQUALS(initialCount, 10000, TEST_LOCATION);
820 DALI_TEST_EQUALS(activeCount, 20000, TEST_LOCATION);
822 emitter.EnableParallelProcessing(true);
824 auto mtEnabled = emitter.IsParallelProcessingEnabled();
825 DALI_TEST_EQUALS(mtEnabled, true, TEST_LOCATION);
827 // Blending mode with screen
828 auto texture = CreateTexture();
829 group.renderer.SetTexture(texture);
830 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
832 // test status again (domain is optional);
833 auto ready = emitter.GetStatus();
835 // Emitter should return status incomplete
836 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
838 // Attach emitter to actor
839 emitter.AttachTo(actor);
844 auto status = emitter.GetStatus();
845 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
847 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
850 sourceCallback.NewFrame();
851 application.SendNotification();
852 application.Render();
854 // First call into source callback should emit initial number of particles
855 auto emittedParticleCount = sourceCallback.mFuture.get();
856 DALI_TEST_EQUALS(emittedParticleCount, 10000, TEST_LOCATION);
858 // Run 3 more frames advancing by 1000ms which should
859 // emit particles based on emission rate
860 AdvanceTimeByMs(1000);
862 sourceCallback.NewFrame();
863 application.SendNotification();
864 application.Render();
866 AdvanceTimeByMs(1000);
868 sourceCallback.NewFrame();
869 application.SendNotification();
870 application.Render();
872 AdvanceTimeByMs(1000);
874 sourceCallback.NewFrame();
875 application.SendNotification();
876 application.Render();
881 int UtcDaliParticleSystemTestParticleSource(void)
883 TestApplication application;
885 // Create actor to be used with emitter
886 Actor actor = Actor::New();
887 application.GetScene().Add(actor);
888 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
892 auto emitter = CreateEmitter<TestSource2, TestModifier>(&group);
894 emitter.SetEmissionRate(1000);
895 emitter.SetInitialParticleCount(1000);
896 emitter.SetActiveParticlesLimit(10000);
898 auto emissionRate = emitter.GetEmissionRate();
899 auto initialCount = emitter.GetInitialParticleCount();
900 auto activeCount = emitter.GetActiveParticlesLimit();
902 DALI_TEST_EQUALS(emissionRate, 1000, TEST_LOCATION);
903 DALI_TEST_EQUALS(initialCount, 1000, TEST_LOCATION);
904 DALI_TEST_EQUALS(activeCount, 10000, TEST_LOCATION);
906 emitter.EnableParallelProcessing(true);
908 // Blending mode with screen
909 auto texture = CreateTexture();
910 group.renderer.SetTexture(texture);
911 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
913 // test status again (domain is optional);
914 auto ready = emitter.GetStatus();
916 // Emitter should return status incomplete
917 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
919 // Set initial parameters of system
920 emitter.SetInitialParticleCount(1000);
921 emitter.SetActiveParticlesLimit(5000);
924 auto initialParticleCount = emitter.GetInitialParticleCount();
925 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
927 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
928 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
930 // Attach emitter to actor
931 emitter.AttachTo(actor);
936 auto status = emitter.GetStatus();
937 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
939 auto& sourceCallback = static_cast<TestSource2&>(emitter.GetSource().GetSourceCallback());
942 sourceCallback.NewFrame();
943 application.SendNotification();
944 application.Render();
946 // First call into source callback should emit initial number of particles
947 auto emittedParticleCount = sourceCallback.mFuture.get();
948 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
950 // Run 3 more frames advancing by 1000ms which should
951 // emit particles based on emission rate
952 AdvanceTimeByMs(1000);
954 sourceCallback.NewFrame();
955 application.SendNotification();
956 application.Render();
958 AdvanceTimeByMs(1000);
960 sourceCallback.NewFrame();
961 application.SendNotification();
962 application.Render();
964 AdvanceTimeByMs(1000);
966 sourceCallback.NewFrame();
967 application.SendNotification();
968 application.Render();
973 sourceCallback.NewFrame();
974 application.SendNotification();
975 application.Render();
980 int UtcDaliParticleSystemReplaceEmitter(void)
982 TestApplication application;
984 // Create actor to be used with emitter
985 Actor actor = Actor::New();
986 application.GetScene().Add(actor);
987 actor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
991 auto emitter = CreateEmitter<TestSource, TestModifier>(&group);
993 // Blending mode with screen
994 auto texture = CreateTexture();
995 group.renderer.SetTexture(texture);
996 group.renderer.SetBlendingMode(BlendingMode::DEFAULT);
998 // test status again (domain is optional);
999 auto ready = emitter.GetStatus();
1001 // Emitter should return status incomplete
1002 DALI_TEST_EQUALS(ready, ParticleEmitter::Status::READY, TEST_LOCATION);
1004 // Set initial parameters of system
1005 emitter.SetInitialParticleCount(1000);
1006 emitter.SetActiveParticlesLimit(5000);
1009 auto initialParticleCount = emitter.GetInitialParticleCount();
1010 auto activeParticlesLimit = emitter.GetActiveParticlesLimit();
1012 DALI_TEST_EQUALS(initialParticleCount, 1000, TEST_LOCATION);
1013 DALI_TEST_EQUALS(activeParticlesLimit, 5000, TEST_LOCATION);
1015 // Attach emitter to actor
1016 emitter.AttachTo(actor);
1021 auto status = emitter.GetStatus();
1022 DALI_TEST_EQUALS(status, ParticleEmitter::Status::STARTED, TEST_LOCATION);
1024 auto& sourceCallback = dynamic_cast<TestSource&>(emitter.GetSource().GetSourceCallback());
1027 sourceCallback.NewFrame();
1028 application.SendNotification();
1029 application.Render();
1031 // First call into source callback should emit initial number of particles
1032 auto emittedParticleCount = sourceCallback.mFuture.get();
1033 DALI_TEST_EQUALS(emittedParticleCount, 1000, TEST_LOCATION);
1035 // Run 3 more frames advancing by 1000ms which should
1036 // emit particles based on emission rate
1037 AdvanceTimeByMs(1000);
1039 sourceCallback.NewFrame();
1040 application.SendNotification();
1041 application.Render();
1043 AdvanceTimeByMs(1000);
1045 sourceCallback.NewFrame();
1046 application.SendNotification();
1047 application.Render();
1049 AdvanceTimeByMs(1000);
1051 sourceCallback.NewFrame();
1052 application.SendNotification();
1053 application.Render();
1056 auto oldEmitter = emitter.GetObjectPtr(); // store old emitter
1057 [[maybe_unused]] auto i = oldEmitter->ReferenceCount();
1061 emitter = CreateEmitter<TestSource, TestModifier>(&group);
1062 DALI_TEST_EQUALS(bool(emitter.GetObjectPtr() != oldEmitter), true, TEST_LOCATION);