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#ifndef META_SRC_ANIMATION_STATE_H
178bf80f4bSopenharmony_ci#define META_SRC_ANIMATION_STATE_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <optional>
208bf80f4bSopenharmony_ci
218bf80f4bSopenharmony_ci#include <meta/api/container/find_cache.h>
228bf80f4bSopenharmony_ci#include <meta/ext/implementation_macros.h>
238bf80f4bSopenharmony_ci#include <meta/interface/animation/intf_animation.h>
248bf80f4bSopenharmony_ci#include <meta/interface/animation/intf_animation_modifier.h>
258bf80f4bSopenharmony_ci#include <meta/interface/intf_any.h>
268bf80f4bSopenharmony_ci#include <meta/interface/intf_attachment.h>
278bf80f4bSopenharmony_ci#include <meta/interface/intf_container.h>
288bf80f4bSopenharmony_ci#include <meta/interface/intf_manual_clock.h>
298bf80f4bSopenharmony_ci#include <meta/interface/property/property_events.h>
308bf80f4bSopenharmony_ci
318bf80f4bSopenharmony_ci#include "intf_animation_internal.h"
328bf80f4bSopenharmony_ci
338bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_cinamespace Internal {
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_ci/**
388bf80f4bSopenharmony_ci * @brief Base animation state implementation, handles animation state, evaluation.
398bf80f4bSopenharmony_ci */
408bf80f4bSopenharmony_ciclass AnimationState {
418bf80f4bSopenharmony_cipublic:
428bf80f4bSopenharmony_ci    AnimationState() = default;
438bf80f4bSopenharmony_ci    ~AnimationState() = default;
448bf80f4bSopenharmony_ci    META_NO_COPY_MOVE(AnimationState)
458bf80f4bSopenharmony_ci
468bf80f4bSopenharmony_cipublic:
478bf80f4bSopenharmony_ci    struct AnimationStateParams {
488bf80f4bSopenharmony_ci        /** Owning animation */
498bf80f4bSopenharmony_ci        IAnimation::WeakPtr owner;
508bf80f4bSopenharmony_ci        /** Writeable IAnimation::Running property */
518bf80f4bSopenharmony_ci        Property<bool> runningProperty;
528bf80f4bSopenharmony_ci        /** Writeable IAnimation::Progress property */
538bf80f4bSopenharmony_ci        Property<float> progressProperty;
548bf80f4bSopenharmony_ci        /** Writeable IAnimation::TotalDuration property */
558bf80f4bSopenharmony_ci        Property<TimeSpan> totalDuration;
568bf80f4bSopenharmony_ci    };
578bf80f4bSopenharmony_ci
588bf80f4bSopenharmony_ci    /**
598bf80f4bSopenharmony_ci     * @brief Initialize AnimationState.
608bf80f4bSopenharmony_ci     * @param owner Owning animation for AnimationState.
618bf80f4bSopenharmony_ci     */
628bf80f4bSopenharmony_ci    virtual bool Initialize(AnimationStateParams&& params);
638bf80f4bSopenharmony_ci    /**
648bf80f4bSopenharmony_ci     * @brief Uninitializes the state object.
658bf80f4bSopenharmony_ci     */
668bf80f4bSopenharmony_ci    virtual void Uninitialize();
678bf80f4bSopenharmony_ci    /** Result of a step operation */
688bf80f4bSopenharmony_ci    struct StepStatus {
698bf80f4bSopenharmony_ci        IAnimationInternal::AnimationTargetState state { IAnimationInternal::AnimationTargetState::UNDEFINED };
708bf80f4bSopenharmony_ci        float progress {};
718bf80f4bSopenharmony_ci        bool changed {};
728bf80f4bSopenharmony_ci
738bf80f4bSopenharmony_ci        constexpr bool StatusChanged() const noexcept
748bf80f4bSopenharmony_ci        {
758bf80f4bSopenharmony_ci            return changed;
768bf80f4bSopenharmony_ci        }
778bf80f4bSopenharmony_ci    };
788bf80f4bSopenharmony_ci    /**
798bf80f4bSopenharmony_ci     * @brief Step the state based on clock.
808bf80f4bSopenharmony_ci     * @param clock Clock containing the step time.
818bf80f4bSopenharmony_ci     */
828bf80f4bSopenharmony_ci    virtual StepStatus Step(const IClock::ConstPtr& clock);
838bf80f4bSopenharmony_ci    /**
848bf80f4bSopenharmony_ci     * @brief Seeks the animation state to given position [0,1]
858bf80f4bSopenharmony_ci     */
868bf80f4bSopenharmony_ci    virtual void Seek(float position);
878bf80f4bSopenharmony_ci    /**
888bf80f4bSopenharmony_ci     * @brief Pauses the animation. Returns true if state changed.
898bf80f4bSopenharmony_ci     */
908bf80f4bSopenharmony_ci    virtual bool Pause();
918bf80f4bSopenharmony_ci    /**
928bf80f4bSopenharmony_ci     * @brief Starts the animation. Returns true if state changed.
938bf80f4bSopenharmony_ci     */
948bf80f4bSopenharmony_ci    virtual bool Start();
958bf80f4bSopenharmony_ci    /**
968bf80f4bSopenharmony_ci     * @brief Stops the animation. Returns true if state changed.
978bf80f4bSopenharmony_ci     */
988bf80f4bSopenharmony_ci    virtual bool Stop();
998bf80f4bSopenharmony_ci    /**
1008bf80f4bSopenharmony_ci     * @brief Restarts the animation. Returns true if state changed.
1018bf80f4bSopenharmony_ci     */
1028bf80f4bSopenharmony_ci    virtual bool Restart();
1038bf80f4bSopenharmony_ci    /**
1048bf80f4bSopenharmony_ci     * @brief Finishes the animation. Returns true if state changed.
1058bf80f4bSopenharmony_ci     */
1068bf80f4bSopenharmony_ci    virtual bool Finish();
1078bf80f4bSopenharmony_ci    /**
1088bf80f4bSopenharmony_ci     * @brief Returns true if the animation is running.
1098bf80f4bSopenharmony_ci     */
1108bf80f4bSopenharmony_ci    bool IsRunning() const noexcept;
1118bf80f4bSopenharmony_ci    /**
1128bf80f4bSopenharmony_ci     * @brief REturns true if the animation is paused.
1138bf80f4bSopenharmony_ci     */
1148bf80f4bSopenharmony_ci    bool IsPaused() const noexcept;
1158bf80f4bSopenharmony_ci    /**
1168bf80f4bSopenharmony_ci     * @brief Returns the current progress of the animation.
1178bf80f4bSopenharmony_ci     */
1188bf80f4bSopenharmony_ci    float GetProgress() const noexcept;
1198bf80f4bSopenharmony_ci    /**
1208bf80f4bSopenharmony_ci     * @brief Move the animation to a requested step position
1218bf80f4bSopenharmony_ci     * @param step
1228bf80f4bSopenharmony_ci     * @param state
1238bf80f4bSopenharmony_ci     * @return
1248bf80f4bSopenharmony_ci     */
1258bf80f4bSopenharmony_ci    StepStatus Move(const IAnimationInternal::MoveParams& move);
1268bf80f4bSopenharmony_ci    /**
1278bf80f4bSopenharmony_ci     * @brief Resets to the animation clock to initial state, even if the animation is running.
1288bf80f4bSopenharmony_ci     */
1298bf80f4bSopenharmony_ci    void ResetClock();
1308bf80f4bSopenharmony_ci
1318bf80f4bSopenharmony_cipublic:
1328bf80f4bSopenharmony_ci    BASE_NS::vector<IAnimationModifier::Ptr> GetModifiers() const;
1338bf80f4bSopenharmony_ci    bool Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext);
1348bf80f4bSopenharmony_ci    bool Detach(const IObject::Ptr& attachment);
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_ci    virtual void UpdateTotalDuration();
1378bf80f4bSopenharmony_ci
1388bf80f4bSopenharmony_ciprotected:
1398bf80f4bSopenharmony_ci    virtual TimeSpan GetAnimationBaseDuration() const;
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ciprotected:
1428bf80f4bSopenharmony_ci    AnimationStateParams& GetParams()
1438bf80f4bSopenharmony_ci    {
1448bf80f4bSopenharmony_ci        return params_;
1458bf80f4bSopenharmony_ci    }
1468bf80f4bSopenharmony_ci
1478bf80f4bSopenharmony_ci    constexpr IAnimationInternal::AnimationTargetState GetAnimationTargetState() const noexcept
1488bf80f4bSopenharmony_ci    {
1498bf80f4bSopenharmony_ci        return state_.animationState_;
1508bf80f4bSopenharmony_ci    }
1518bf80f4bSopenharmony_ci
1528bf80f4bSopenharmony_ci    /** Return the owning animation of this state object */
1538bf80f4bSopenharmony_ci    IAnimation::Ptr GetOwner() const noexcept;
1548bf80f4bSopenharmony_ci    /** Returns a duration with all modifiers applied */
1558bf80f4bSopenharmony_ci    IAnimationModifier::DurationData ApplyDurationModifiers(TimeSpan duration) const;
1568bf80f4bSopenharmony_ci    /** Returns step data with all modifiers applied */
1578bf80f4bSopenharmony_ci    IAnimationModifier::StepData ApplyStepModifiers(float progress) const;
1588bf80f4bSopenharmony_ci
1598bf80f4bSopenharmony_ciprivate:
1608bf80f4bSopenharmony_ci    void NotifyEvaluationNeeded() const;
1618bf80f4bSopenharmony_ci    void NotifyStateChanged(const IAnimationInternal::AnimationStateChangedInfo& info) const;
1628bf80f4bSopenharmony_ci    void UpdateController();
1638bf80f4bSopenharmony_ci    bool SetState(IAnimationInternal::AnimationTargetState state);
1648bf80f4bSopenharmony_ci    void SetRunning(bool running) noexcept;
1658bf80f4bSopenharmony_ci    void SetProgress(float progress) noexcept;
1668bf80f4bSopenharmony_ci
1678bf80f4bSopenharmony_ciprivate:
1688bf80f4bSopenharmony_ci    IAnimationController::WeakPtr controller_;         // Animation's controller
1698bf80f4bSopenharmony_ci    IOnChanged::InterfaceTypePtr updateTotalDuration_; // Callback function for total duration update
1708bf80f4bSopenharmony_ci    AnimationStateParams params_;                      // Animation parameters
1718bf80f4bSopenharmony_ci    struct StateData {
1728bf80f4bSopenharmony_ci        int32_t loops { 1 };
1738bf80f4bSopenharmony_ci        TimeSpan totalDuration;
1748bf80f4bSopenharmony_ci        IAnimationModifier::DurationData duration;
1758bf80f4bSopenharmony_ci        bool shouldInit_ { false };
1768bf80f4bSopenharmony_ci        IManualClock::Ptr clock_;
1778bf80f4bSopenharmony_ci        std::optional<META_NS::TimeSpan> lastTick_;
1788bf80f4bSopenharmony_ci        IAnimationInternal::AnimationTargetState animationState_ { IAnimationInternal::AnimationTargetState::STOPPED };
1798bf80f4bSopenharmony_ci
1808bf80f4bSopenharmony_ci        void ResetLastTick() noexcept
1818bf80f4bSopenharmony_ci        {
1828bf80f4bSopenharmony_ci            lastTick_.reset();
1838bf80f4bSopenharmony_ci        }
1848bf80f4bSopenharmony_ci        void SetTime(const TimeSpan& time)
1858bf80f4bSopenharmony_ci        {
1868bf80f4bSopenharmony_ci            clock_->SetTime(time);
1878bf80f4bSopenharmony_ci        }
1888bf80f4bSopenharmony_ci        TimeSpan Tick(const TimeSpan& time)
1898bf80f4bSopenharmony_ci        {
1908bf80f4bSopenharmony_ci            clock_->IncrementTime(GetElapsed(time));
1918bf80f4bSopenharmony_ci            lastTick_ = time;
1928bf80f4bSopenharmony_ci            return clock_->GetTime();
1938bf80f4bSopenharmony_ci        }
1948bf80f4bSopenharmony_ci        TimeSpan GetCurrentTime() const
1958bf80f4bSopenharmony_ci        {
1968bf80f4bSopenharmony_ci            return clock_->GetTime();
1978bf80f4bSopenharmony_ci        }
1988bf80f4bSopenharmony_ci        constexpr TimeSpan GetElapsed(const TimeSpan& time) const noexcept
1998bf80f4bSopenharmony_ci        {
2008bf80f4bSopenharmony_ci            return lastTick_ ? time - *lastTick_ : TimeSpan::Zero();
2018bf80f4bSopenharmony_ci        }
2028bf80f4bSopenharmony_ci        constexpr TimeSpan GetBaseDuration() const noexcept
2038bf80f4bSopenharmony_ci        {
2048bf80f4bSopenharmony_ci            return duration.duration;
2058bf80f4bSopenharmony_ci        }
2068bf80f4bSopenharmony_ci
2078bf80f4bSopenharmony_ci    } state_;                                             // State data
2088bf80f4bSopenharmony_ci    mutable FindCache<IAnimationModifier> modifierCache_; // Cached modifier query
2098bf80f4bSopenharmony_ci};
2108bf80f4bSopenharmony_ci
2118bf80f4bSopenharmony_ci/**
2128bf80f4bSopenharmony_ci * @brief State class implementation for animation targeting a single property.
2138bf80f4bSopenharmony_ci */
2148bf80f4bSopenharmony_ciclass PropertyAnimationState : public AnimationState {
2158bf80f4bSopenharmony_ci    using Super = AnimationState;
2168bf80f4bSopenharmony_ci
2178bf80f4bSopenharmony_cipublic:
2188bf80f4bSopenharmony_ci    PropertyAnimationState() = default;
2198bf80f4bSopenharmony_ci    ~PropertyAnimationState() = default;
2208bf80f4bSopenharmony_ci
2218bf80f4bSopenharmony_ci    /**
2228bf80f4bSopenharmony_ci     * @brief Data needed for evaluating an animation state.
2238bf80f4bSopenharmony_ci     */
2248bf80f4bSopenharmony_ci    struct EvaluationData {
2258bf80f4bSopenharmony_ci        /** Target value */
2268bf80f4bSopenharmony_ci        const IAny::Ptr target;
2278bf80f4bSopenharmony_ci        /** Start of interpolation range */
2288bf80f4bSopenharmony_ci        const IAny::Ptr from;
2298bf80f4bSopenharmony_ci        /** End of interpolation range */
2308bf80f4bSopenharmony_ci        const IAny::Ptr to;
2318bf80f4bSopenharmony_ci        /** Linear animation progress [0,1] */
2328bf80f4bSopenharmony_ci        float progress;
2338bf80f4bSopenharmony_ci        /** The (optional) curve to use for transforming the progress value */
2348bf80f4bSopenharmony_ci        const ICurve1D::Ptr curve;
2358bf80f4bSopenharmony_ci        /** Returns true if the data is valid */
2368bf80f4bSopenharmony_ci        inline bool IsValid() const noexcept
2378bf80f4bSopenharmony_ci        {
2388bf80f4bSopenharmony_ci            return target && from && to;
2398bf80f4bSopenharmony_ci        }
2408bf80f4bSopenharmony_ci    };
2418bf80f4bSopenharmony_ci    /**
2428bf80f4bSopenharmony_ci     * @brief Initialize state object's internal interpolator to support given type id.
2438bf80f4bSopenharmony_ci     */
2448bf80f4bSopenharmony_ci    bool SetInterpolator(const TypeId& id);
2458bf80f4bSopenharmony_ci    /**
2468bf80f4bSopenharmony_ci     * @brief Return the interpolator initialized with SetInterpolator.
2478bf80f4bSopenharmony_ci     */
2488bf80f4bSopenharmony_ci    IInterpolator::Ptr GetInterpolator() const;
2498bf80f4bSopenharmony_ci    /**
2508bf80f4bSopenharmony_ci     * @brief Evaluates target value between [from,to] based on state.
2518bf80f4bSopenharmony_ci     * @param data Evaluation data.
2528bf80f4bSopenharmony_ci     */
2538bf80f4bSopenharmony_ci    AnyReturnValue EvaluateValue(const EvaluationData& data) const;
2548bf80f4bSopenharmony_ci
2558bf80f4bSopenharmony_ciprivate:
2568bf80f4bSopenharmony_ci    IInterpolator::Ptr interpolator_;
2578bf80f4bSopenharmony_ci};
2588bf80f4bSopenharmony_ci
2598bf80f4bSopenharmony_ci} // namespace Internal
2608bf80f4bSopenharmony_ci
2618bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
2628bf80f4bSopenharmony_ci
2638bf80f4bSopenharmony_ci#endif // META_SRC_ANIMATION_STATE_H
264