1 /*
2 * Copyright (c) 2024 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_controller.h"
17
18 #include <meta/api/make_callback.h>
19 #include <meta/ext/serialization/serializer.h>
20 #include <meta/interface/property/property_events.h>
21
META_BEGIN_NAMESPACE()22 META_BEGIN_NAMESPACE()
23
24 bool AnimationController::Build(const IMetadata::Ptr& data)
25 {
26 updateCallback_ = MakeCallback<IOnChanged>(this, &AnimationController::UpdateAnimations);
27 return true;
28 }
29
AttachTo(const META_NS::IAttach::Ptr & target,const META_NS::IObject::Ptr & dataContext)30 bool AnimationController::AttachTo(const META_NS::IAttach::Ptr& target, const META_NS::IObject::Ptr& dataContext)
31 {
32 return true;
33 }
34
DetachFrom(const META_NS::IAttach::Ptr & target)35 bool AnimationController::DetachFrom(const META_NS::IAttach::Ptr& target)
36 {
37 return true;
38 }
39
UpdateAnimations()40 void AnimationController::UpdateAnimations()
41 {
42 uint32_t count = 0;
43 uint32_t running = 0;
44 {
45 std::unique_lock lock(mutex_);
46 auto it = animations_.begin();
47 running_.clear();
48 while (it != animations_.end()) {
49 auto& weak = *it;
50 if (auto animation = weak.lock()) {
51 // Assuming here that getting the running property value cannot cause a recursive call back
52 // to the animation controller
53 if (GetValue(animation->Running())) {
54 running_.push_back(weak);
55 }
56 it++;
57 } else {
58 // Animation has died, clean up weak_ptr from our list
59 it = animations_.erase(it);
60 }
61 }
62 count = animations_.size();
63 running = running_.size();
64 }
65
66 SetValue(META_ACCESS_PROPERTY(Count), count);
67 SetValue(META_ACCESS_PROPERTY(RunningCount), running);
68 }
69
UpdateRunningHandler(const IAnimation::Ptr & animation,bool addHandler)70 void AnimationController::UpdateRunningHandler(const IAnimation::Ptr& animation, bool addHandler)
71 {
72 if (!animation) {
73 return;
74 }
75 if (auto running = animation->Running()) {
76 if (addHandler) {
77 running->OnChanged()->AddHandler(updateCallback_, uintptr_t(this));
78 } else {
79 running->OnChanged()->RemoveHandler(uintptr_t(this));
80 }
81 }
82 }
83
AddAnimation(const META_NS::IAnimation::Ptr & animation)84 bool AnimationController::AddAnimation(const META_NS::IAnimation::Ptr& animation)
85 {
86 if (!animation) {
87 return false;
88 }
89 {
90 std::unique_lock lock(mutex_);
91 for (auto& weak : animations_) {
92 if (weak.lock() == animation) {
93 // Already there
94 return true;
95 }
96 }
97 animations_.emplace_back(animation);
98 }
99
100 UpdateRunningHandler(animation, true);
101 SetValue(animation->Controller(), GetSelf<IAnimationController>());
102 UpdateAnimations();
103 return true;
104 }
105
RemoveAnimation(const META_NS::IAnimation::Ptr & animation)106 bool AnimationController::RemoveAnimation(const META_NS::IAnimation::Ptr& animation)
107 {
108 bool removed = false;
109 if (animation) {
110 std::unique_lock lock(mutex_);
111 for (auto it = animations_.begin(); it != animations_.end(); it++) {
112 if ((*it).lock() == animation) {
113 animations_.erase(it);
114 removed = true;
115 break;
116 }
117 }
118 }
119 if (removed) {
120 UpdateRunningHandler(animation, false);
121 UpdateAnimations();
122 }
123 return removed;
124 }
125
Clear()126 void AnimationController::Clear()
127 {
128 {
129 BASE_NS::vector<IAnimation::WeakPtr> all;
130 {
131 std::unique_lock lock(mutex_);
132 all.swap(animations_);
133 running_.clear();
134 }
135 for (auto& weak : all) {
136 UpdateRunningHandler(weak.lock(), false);
137 }
138 }
139 UpdateAnimations();
140 }
141
Step(const IClock::ConstPtr & clock)142 IAnimationController::StepInfo AnimationController::Step(const IClock::ConstPtr& clock)
143 {
144 StepInfo info { 0, 0 };
145
146 for (auto& anim : GetRunning()) {
147 if (auto animation = anim.lock()) {
148 animation->Step(clock);
149 info.stepped_++;
150 }
151 }
152
153 // Step may end up starting/stopping some animations
154 std::shared_lock lock(mutex_);
155 info.running_ = running_.size();
156 return info;
157 }
158
GetAnimations() const159 BASE_NS::vector<IAnimation::WeakPtr> AnimationController::GetAnimations() const
160 {
161 std::shared_lock lock(mutex_);
162 return animations_;
163 }
164
GetRunning() const165 BASE_NS::vector<IAnimation::WeakPtr> AnimationController::GetRunning() const
166 {
167 std::shared_lock lock(mutex_);
168 return running_;
169 }
170
Export(IExportContext & c) const171 ReturnError AnimationController::Export(IExportContext& c) const
172 {
173 return Serializer(c) & NamedValue("__animations", animations_);
174 }
Import(IImportContext & c)175 ReturnError AnimationController::Import(IImportContext& c)
176 {
177 return Serializer(c) & NamedValue("__animations", animations_);
178 }
Finalize(IImportFunctions &)179 ReturnError AnimationController::Finalize(IImportFunctions&)
180 {
181 // take the animations out and re-add by setting the animation controller
182 BASE_NS::vector<IAnimation::WeakPtr> vec = BASE_NS::move(animations_);
183 for (auto&& anim : vec) {
184 if (auto p = anim.lock()) {
185 p->Controller()->SetValue(GetSelf<IAnimationController>());
186 }
187 }
188 return GenericError::SUCCESS;
189 }
190
191 META_END_NAMESPACE()
192