18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "animation_controller.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <meta/api/make_callback.h>
198bf80f4bSopenharmony_ci#include <meta/ext/serialization/serializer.h>
208bf80f4bSopenharmony_ci#include <meta/interface/property/property_events.h>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
238bf80f4bSopenharmony_ci
248bf80f4bSopenharmony_cibool AnimationController::Build(const IMetadata::Ptr& data)
258bf80f4bSopenharmony_ci{
268bf80f4bSopenharmony_ci    updateCallback_ = MakeCallback<IOnChanged>(this, &AnimationController::UpdateAnimations);
278bf80f4bSopenharmony_ci    return true;
288bf80f4bSopenharmony_ci}
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_cibool AnimationController::AttachTo(const META_NS::IAttach::Ptr& target, const META_NS::IObject::Ptr& dataContext)
318bf80f4bSopenharmony_ci{
328bf80f4bSopenharmony_ci    return true;
338bf80f4bSopenharmony_ci}
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_cibool AnimationController::DetachFrom(const META_NS::IAttach::Ptr& target)
368bf80f4bSopenharmony_ci{
378bf80f4bSopenharmony_ci    return true;
388bf80f4bSopenharmony_ci}
398bf80f4bSopenharmony_ci
408bf80f4bSopenharmony_civoid AnimationController::UpdateAnimations()
418bf80f4bSopenharmony_ci{
428bf80f4bSopenharmony_ci    uint32_t count = 0;
438bf80f4bSopenharmony_ci    uint32_t running = 0;
448bf80f4bSopenharmony_ci    {
458bf80f4bSopenharmony_ci        std::unique_lock lock(mutex_);
468bf80f4bSopenharmony_ci        auto it = animations_.begin();
478bf80f4bSopenharmony_ci        running_.clear();
488bf80f4bSopenharmony_ci        while (it != animations_.end()) {
498bf80f4bSopenharmony_ci            auto& weak = *it;
508bf80f4bSopenharmony_ci            if (auto animation = weak.lock()) {
518bf80f4bSopenharmony_ci                // Assuming here that getting the running property value cannot cause a recursive call back
528bf80f4bSopenharmony_ci                // to the animation controller
538bf80f4bSopenharmony_ci                if (GetValue(animation->Running())) {
548bf80f4bSopenharmony_ci                    running_.push_back(weak);
558bf80f4bSopenharmony_ci                }
568bf80f4bSopenharmony_ci                it++;
578bf80f4bSopenharmony_ci            } else {
588bf80f4bSopenharmony_ci                // Animation has died, clean up weak_ptr from our list
598bf80f4bSopenharmony_ci                it = animations_.erase(it);
608bf80f4bSopenharmony_ci            }
618bf80f4bSopenharmony_ci        }
628bf80f4bSopenharmony_ci        count = animations_.size();
638bf80f4bSopenharmony_ci        running = running_.size();
648bf80f4bSopenharmony_ci    }
658bf80f4bSopenharmony_ci
668bf80f4bSopenharmony_ci    SetValue(META_ACCESS_PROPERTY(Count), count);
678bf80f4bSopenharmony_ci    SetValue(META_ACCESS_PROPERTY(RunningCount), running);
688bf80f4bSopenharmony_ci}
698bf80f4bSopenharmony_ci
708bf80f4bSopenharmony_civoid AnimationController::UpdateRunningHandler(const IAnimation::Ptr& animation, bool addHandler)
718bf80f4bSopenharmony_ci{
728bf80f4bSopenharmony_ci    if (!animation) {
738bf80f4bSopenharmony_ci        return;
748bf80f4bSopenharmony_ci    }
758bf80f4bSopenharmony_ci    if (auto running = animation->Running()) {
768bf80f4bSopenharmony_ci        if (addHandler) {
778bf80f4bSopenharmony_ci            running->OnChanged()->AddHandler(updateCallback_, uintptr_t(this));
788bf80f4bSopenharmony_ci        } else {
798bf80f4bSopenharmony_ci            running->OnChanged()->RemoveHandler(uintptr_t(this));
808bf80f4bSopenharmony_ci        }
818bf80f4bSopenharmony_ci    }
828bf80f4bSopenharmony_ci}
838bf80f4bSopenharmony_ci
848bf80f4bSopenharmony_cibool AnimationController::AddAnimation(const META_NS::IAnimation::Ptr& animation)
858bf80f4bSopenharmony_ci{
868bf80f4bSopenharmony_ci    if (!animation) {
878bf80f4bSopenharmony_ci        return false;
888bf80f4bSopenharmony_ci    }
898bf80f4bSopenharmony_ci    {
908bf80f4bSopenharmony_ci        std::unique_lock lock(mutex_);
918bf80f4bSopenharmony_ci        for (auto& weak : animations_) {
928bf80f4bSopenharmony_ci            if (weak.lock() == animation) {
938bf80f4bSopenharmony_ci                // Already there
948bf80f4bSopenharmony_ci                return true;
958bf80f4bSopenharmony_ci            }
968bf80f4bSopenharmony_ci        }
978bf80f4bSopenharmony_ci        animations_.emplace_back(animation);
988bf80f4bSopenharmony_ci    }
998bf80f4bSopenharmony_ci
1008bf80f4bSopenharmony_ci    UpdateRunningHandler(animation, true);
1018bf80f4bSopenharmony_ci    SetValue(animation->Controller(), GetSelf<IAnimationController>());
1028bf80f4bSopenharmony_ci    UpdateAnimations();
1038bf80f4bSopenharmony_ci    return true;
1048bf80f4bSopenharmony_ci}
1058bf80f4bSopenharmony_ci
1068bf80f4bSopenharmony_cibool AnimationController::RemoveAnimation(const META_NS::IAnimation::Ptr& animation)
1078bf80f4bSopenharmony_ci{
1088bf80f4bSopenharmony_ci    bool removed = false;
1098bf80f4bSopenharmony_ci    if (animation) {
1108bf80f4bSopenharmony_ci        std::unique_lock lock(mutex_);
1118bf80f4bSopenharmony_ci        for (auto it = animations_.begin(); it != animations_.end(); it++) {
1128bf80f4bSopenharmony_ci            if ((*it).lock() == animation) {
1138bf80f4bSopenharmony_ci                animations_.erase(it);
1148bf80f4bSopenharmony_ci                removed = true;
1158bf80f4bSopenharmony_ci                break;
1168bf80f4bSopenharmony_ci            }
1178bf80f4bSopenharmony_ci        }
1188bf80f4bSopenharmony_ci    }
1198bf80f4bSopenharmony_ci    if (removed) {
1208bf80f4bSopenharmony_ci        UpdateRunningHandler(animation, false);
1218bf80f4bSopenharmony_ci        UpdateAnimations();
1228bf80f4bSopenharmony_ci    }
1238bf80f4bSopenharmony_ci    return removed;
1248bf80f4bSopenharmony_ci}
1258bf80f4bSopenharmony_ci
1268bf80f4bSopenharmony_civoid AnimationController::Clear()
1278bf80f4bSopenharmony_ci{
1288bf80f4bSopenharmony_ci    {
1298bf80f4bSopenharmony_ci        BASE_NS::vector<IAnimation::WeakPtr> all;
1308bf80f4bSopenharmony_ci        {
1318bf80f4bSopenharmony_ci            std::unique_lock lock(mutex_);
1328bf80f4bSopenharmony_ci            all.swap(animations_);
1338bf80f4bSopenharmony_ci            running_.clear();
1348bf80f4bSopenharmony_ci        }
1358bf80f4bSopenharmony_ci        for (auto& weak : all) {
1368bf80f4bSopenharmony_ci            UpdateRunningHandler(weak.lock(), false);
1378bf80f4bSopenharmony_ci        }
1388bf80f4bSopenharmony_ci    }
1398bf80f4bSopenharmony_ci    UpdateAnimations();
1408bf80f4bSopenharmony_ci}
1418bf80f4bSopenharmony_ci
1428bf80f4bSopenharmony_ciIAnimationController::StepInfo AnimationController::Step(const IClock::ConstPtr& clock)
1438bf80f4bSopenharmony_ci{
1448bf80f4bSopenharmony_ci    StepInfo info { 0, 0 };
1458bf80f4bSopenharmony_ci
1468bf80f4bSopenharmony_ci    for (auto& anim : GetRunning()) {
1478bf80f4bSopenharmony_ci        if (auto animation = anim.lock()) {
1488bf80f4bSopenharmony_ci            animation->Step(clock);
1498bf80f4bSopenharmony_ci            info.stepped_++;
1508bf80f4bSopenharmony_ci        }
1518bf80f4bSopenharmony_ci    }
1528bf80f4bSopenharmony_ci
1538bf80f4bSopenharmony_ci    // Step may end up starting/stopping some animations
1548bf80f4bSopenharmony_ci    std::shared_lock lock(mutex_);
1558bf80f4bSopenharmony_ci    info.running_ = running_.size();
1568bf80f4bSopenharmony_ci    return info;
1578bf80f4bSopenharmony_ci}
1588bf80f4bSopenharmony_ci
1598bf80f4bSopenharmony_ciBASE_NS::vector<IAnimation::WeakPtr> AnimationController::GetAnimations() const
1608bf80f4bSopenharmony_ci{
1618bf80f4bSopenharmony_ci    std::shared_lock lock(mutex_);
1628bf80f4bSopenharmony_ci    return animations_;
1638bf80f4bSopenharmony_ci}
1648bf80f4bSopenharmony_ci
1658bf80f4bSopenharmony_ciBASE_NS::vector<IAnimation::WeakPtr> AnimationController::GetRunning() const
1668bf80f4bSopenharmony_ci{
1678bf80f4bSopenharmony_ci    std::shared_lock lock(mutex_);
1688bf80f4bSopenharmony_ci    return running_;
1698bf80f4bSopenharmony_ci}
1708bf80f4bSopenharmony_ci
1718bf80f4bSopenharmony_ciReturnError AnimationController::Export(IExportContext& c) const
1728bf80f4bSopenharmony_ci{
1738bf80f4bSopenharmony_ci    return Serializer(c) & NamedValue("__animations", animations_);
1748bf80f4bSopenharmony_ci}
1758bf80f4bSopenharmony_ciReturnError AnimationController::Import(IImportContext& c)
1768bf80f4bSopenharmony_ci{
1778bf80f4bSopenharmony_ci    return Serializer(c) & NamedValue("__animations", animations_);
1788bf80f4bSopenharmony_ci}
1798bf80f4bSopenharmony_ciReturnError AnimationController::Finalize(IImportFunctions&)
1808bf80f4bSopenharmony_ci{
1818bf80f4bSopenharmony_ci    // take the animations out and re-add by setting the animation controller
1828bf80f4bSopenharmony_ci    BASE_NS::vector<IAnimation::WeakPtr> vec = BASE_NS::move(animations_);
1838bf80f4bSopenharmony_ci    for (auto&& anim : vec) {
1848bf80f4bSopenharmony_ci        if (auto p = anim.lock()) {
1858bf80f4bSopenharmony_ci            p->Controller()->SetValue(GetSelf<IAnimationController>());
1868bf80f4bSopenharmony_ci        }
1878bf80f4bSopenharmony_ci    }
1888bf80f4bSopenharmony_ci    return GenericError::SUCCESS;
1898bf80f4bSopenharmony_ci}
1908bf80f4bSopenharmony_ci
1918bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
192