1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "animation/rs_render_particle_animation.h"
17 
18 #include <memory>
19 
20 #include "rs_profiler.h"
21 
22 #include "animation/rs_value_estimator.h"
23 #include "command/rs_animation_command.h"
24 #include "common/rs_optional_trace.h"
25 #include "platform/common/rs_log.h"
26 #include "transaction/rs_marshalling_helper.h"
27 
28 namespace OHOS {
29 namespace Rosen {
RSRenderParticleAnimation(AnimationId id,const PropertyId & propertyId,const std::vector<std::shared_ptr<ParticleRenderParams>> & particlesRenderParams)30 RSRenderParticleAnimation::RSRenderParticleAnimation(AnimationId id, const PropertyId& propertyId,
31     const std::vector<std::shared_ptr<ParticleRenderParams>>& particlesRenderParams)
32     : RSRenderPropertyAnimation(id, propertyId), particlesRenderParams_(particlesRenderParams),
33       particleSystem_(std::make_shared<RSRenderParticleSystem>(particlesRenderParams_))
34 {}
35 
DumpAnimationType(std::string & out) const36 void RSRenderParticleAnimation::DumpAnimationType(std::string& out) const
37 {
38     out += "Type:RSRenderParticleAnimation";
39 }
40 
Animate(int64_t time)41 bool RSRenderParticleAnimation::Animate(int64_t time)
42 {
43     RS_OPTIONAL_TRACE_NAME("RSRenderParticleAnimation::Animate");
44     auto target = GetTarget();
45     if (!target) {
46         return true;
47     } else if (!target->GetRenderProperties().GetVisible()) {
48         target->RemoveModifier(property_->GetId());
49         return true;
50     }
51 
52     int64_t deltaTime = time - animationFraction_.GetLastFrameTime();
53     animationFraction_.SetLastFrameTime(time);
54     if (particleSystem_ != nullptr) {
55         particleSystem_->Emit(
56             deltaTime, renderParticleVector_.renderParticleVector_, renderParticleVector_.imageVector_);
57         particleSystem_->UpdateParticle(deltaTime, renderParticleVector_.renderParticleVector_);
58     }
59     auto property = std::static_pointer_cast<RSRenderProperty<RSRenderParticleVector>>(property_);
60     if (property) {
61         property->Set(renderParticleVector_);
62     }
63 
64     if (particleSystem_ == nullptr || particleSystem_->IsFinish(renderParticleVector_.renderParticleVector_)) {
65         if (target) {
66             target->RemoveModifier(property_->GetId());
67         }
68         return true;
69     }
70     return false;
71 }
72 
UpdateEmitter(const std::vector<std::shared_ptr<EmitterUpdater>> & emitterUpdaters)73 void RSRenderParticleAnimation::UpdateEmitter(const std::vector<std::shared_ptr<EmitterUpdater>>& emitterUpdaters)
74 {
75     if (emitterUpdaters.empty()) {
76         return;
77     }
78     for (auto emitterUpdater : emitterUpdaters) {
79         if (emitterUpdater) {
80             uint32_t index = emitterUpdater->emitterIndex_;
81             if (index >= particlesRenderParams_.size()) {
82                 continue;
83             }
84             if (particlesRenderParams_[index] == nullptr) {
85                 continue;
86             }
87             if (emitterUpdater->position_.has_value() &&
88                 emitterUpdater->position_.value() != particlesRenderParams_[index]->emitterConfig_.position_) {
89                 particlesRenderParams_[index]->emitterConfig_.position_ = emitterUpdater->position_.value();
90             }
91             if (emitterUpdater->emitSize_.has_value() &&
92                 emitterUpdater->emitSize_.value() != particlesRenderParams_[index]->emitterConfig_.emitSize_) {
93                 particlesRenderParams_[index]->emitterConfig_.emitSize_ = emitterUpdater->emitSize_.value();
94             }
95             if (emitterUpdater->emitRate_.has_value() &&
96                 emitterUpdater->emitRate_.value() != particlesRenderParams_[index]->emitterConfig_.emitRate_) {
97                 particlesRenderParams_[index]->emitterConfig_.emitRate_ = emitterUpdater->emitRate_.value();
98             }
99         }
100     }
101     if (particleSystem_) {
102         particleSystem_->UpdateEmitter(particlesRenderParams_);
103     } else {
104         particleSystem_ = std::make_shared<RSRenderParticleSystem>(particlesRenderParams_);
105     }
106 }
107 
UpdateNoiseField(const std::shared_ptr<ParticleNoiseFields> & particleNoiseFields)108 void RSRenderParticleAnimation::UpdateNoiseField(const std::shared_ptr<ParticleNoiseFields>& particleNoiseFields)
109 {
110     if (particleNoiseFields == nullptr) {
111         return;
112     } else if (particleNoiseFields_ != nullptr && *particleNoiseFields_ == *particleNoiseFields) {
113         return;
114     }
115     particleNoiseFields_ = particleNoiseFields;
116     if (particleSystem_) {
117         particleSystem_->UpdateNoiseField(particleNoiseFields);
118     }
119 }
120 
OnAttach()121 void RSRenderParticleAnimation::OnAttach()
122 {
123     auto target = GetTarget();
124     if (target == nullptr) {
125         ROSEN_LOGE("RSRenderParticleAnimation::OnAttach, target is nullptr");
126         return;
127     }
128     auto particleAnimations = target->GetAnimationManager().GetParticleAnimations();
129     if (!particleAnimations.empty()) {
130         for (const auto& pair : particleAnimations) {
131             target->RemoveModifier(pair.first);
132             target->GetAnimationManager().RemoveAnimation(pair.second);
133             target->GetAnimationManager().UnregisterParticleAnimation(pair.first, pair.second);
134         }
135     }
136     target->GetAnimationManager().RegisterParticleAnimation(GetPropertyId(), GetAnimationId());
137 }
138 
OnDetach()139 void RSRenderParticleAnimation::OnDetach()
140 {
141     auto target = GetTarget();
142     if (target == nullptr) {
143         ROSEN_LOGE("RSRenderParticleAnimation::OnDetach, target is nullptr");
144         return;
145     }
146     if (particleSystem_ != nullptr) {
147         particleSystem_->ClearEmitter();
148         particleSystem_.reset();
149     }
150     auto propertyId = GetPropertyId();
151     auto id = GetAnimationId();
152     target->GetAnimationManager().UnregisterParticleAnimation(propertyId, id);
153 }
154 
Marshalling(Parcel & parcel) const155 bool RSRenderParticleAnimation::Marshalling(Parcel& parcel) const
156 {
157     auto id = GetAnimationId();
158     if (!(parcel.WriteUint64(id))) {
159         ROSEN_LOGE("RSRenderParticleAnimation::Marshalling, write id failed");
160         return false;
161     }
162     if (!parcel.WriteUint64(propertyId_)) {
163         ROSEN_LOGE("RSRenderParticleAnimation::Marshalling, write PropertyId failed");
164         return false;
165     }
166     if (!RSMarshallingHelper::Marshalling(parcel, particlesRenderParams_)) {
167         ROSEN_LOGE("RSRenderParticleAnimation::Marshalling, write particlesRenderParams failed");
168         return false;
169     }
170     return true;
171 }
172 
Unmarshalling(Parcel & parcel)173 RSRenderParticleAnimation* RSRenderParticleAnimation::Unmarshalling(Parcel& parcel)
174 {
175     RSRenderParticleAnimation* renderParticleAnimation = new RSRenderParticleAnimation();
176     if (!renderParticleAnimation->ParseParam(parcel)) {
177         ROSEN_LOGE("RSRenderParticleAnimation::Unmarshalling, failed");
178         delete renderParticleAnimation;
179         return nullptr;
180     }
181     return renderParticleAnimation;
182 }
183 
ParseParam(Parcel & parcel)184 bool RSRenderParticleAnimation::ParseParam(Parcel& parcel)
185 {
186     AnimationId id = 0;
187     if (!parcel.ReadUint64(id)) {
188         ROSEN_LOGE("RSRenderParticleAnimation::ParseParam, Unmarshalling animationId failed");
189         return false;
190     }
191     RS_PROFILER_PATCH_NODE_ID(parcel, id);
192     SetAnimationId(id);
193     if (!(parcel.ReadUint64(propertyId_) && RSMarshallingHelper::Unmarshalling(parcel, particlesRenderParams_))) {
194         ROSEN_LOGE("RSRenderParticleAnimation::ParseParam, Unmarshalling failed");
195         return false;
196     }
197     RS_PROFILER_PATCH_NODE_ID(parcel, propertyId_);
198     particleSystem_ = std::make_shared<RSRenderParticleSystem>(particlesRenderParams_);
199     return true;
200 }
201 
202 } // namespace Rosen
203 } // namespace OHOS
204