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 "track_animation.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <meta/ext/serialization/serializer.h> 198bf80f4bSopenharmony_ci 208bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 218bf80f4bSopenharmony_ci 228bf80f4bSopenharmony_cinamespace Internal { 238bf80f4bSopenharmony_ci 248bf80f4bSopenharmony_ciAnimationState::AnimationStateParams TrackAnimation::GetParams() 258bf80f4bSopenharmony_ci{ 268bf80f4bSopenharmony_ci AnimationState::AnimationStateParams params; 278bf80f4bSopenharmony_ci params.owner = GetSelf<IAnimation>(); 288bf80f4bSopenharmony_ci params.runningProperty = META_ACCESS_PROPERTY(Running); 298bf80f4bSopenharmony_ci params.progressProperty = META_ACCESS_PROPERTY(Progress); 308bf80f4bSopenharmony_ci params.totalDuration = META_ACCESS_PROPERTY(TotalDuration); 318bf80f4bSopenharmony_ci return params; 328bf80f4bSopenharmony_ci} 338bf80f4bSopenharmony_ci 348bf80f4bSopenharmony_cibool TrackAnimation::Build(const IMetadata::Ptr& data) 358bf80f4bSopenharmony_ci{ 368bf80f4bSopenharmony_ci if (Super::Build(data)) { 378bf80f4bSopenharmony_ci TrackAnimationState::TrackDataParams params { META_ACCESS_PROPERTY(Timestamps) }; 388bf80f4bSopenharmony_ci GetState().SetTrackDataParams(BASE_NS::move(params)); 398bf80f4bSopenharmony_ci 408bf80f4bSopenharmony_ci auto updateKf = MakeCallback<IOnChanged>(this, &TrackAnimation::UpdateKeyframes); 418bf80f4bSopenharmony_ci 428bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Timestamps)->OnChanged()->AddHandler(updateKf); 438bf80f4bSopenharmony_ci constexpr BASE_NS::string_view name = "Keyframes"; 448bf80f4bSopenharmony_ci keyframes_ = GetObjectRegistry().GetPropertyRegister().Create(ClassId::StackProperty, name); 458bf80f4bSopenharmony_ci if (keyframes_) { 468bf80f4bSopenharmony_ci keyframes_->OnChanged()->AddHandler(updateKf); 478bf80f4bSopenharmony_ci AddProperty(keyframes_); 488bf80f4bSopenharmony_ci } 498bf80f4bSopenharmony_ci UpdateKeyframes(); 508bf80f4bSopenharmony_ci return keyframes_ != nullptr; 518bf80f4bSopenharmony_ci } 528bf80f4bSopenharmony_ci return false; 538bf80f4bSopenharmony_ci} 548bf80f4bSopenharmony_ci 558bf80f4bSopenharmony_civoid TrackAnimation::Initialize() 568bf80f4bSopenharmony_ci{ 578bf80f4bSopenharmony_ci ResetTrack(); 588bf80f4bSopenharmony_ci} 598bf80f4bSopenharmony_ci 608bf80f4bSopenharmony_civoid TrackAnimation::OnAnimationStateChanged(const IAnimationInternal::AnimationStateChangedInfo& info) 618bf80f4bSopenharmony_ci{ 628bf80f4bSopenharmony_ci using AnimationTargetState = IAnimationInternal::AnimationTargetState; 638bf80f4bSopenharmony_ci if (auto p = GetTargetProperty()) { 648bf80f4bSopenharmony_ci switch (info.state) { 658bf80f4bSopenharmony_ci case AnimationTargetState::FINISHED: 668bf80f4bSopenharmony_ci [[fallthrough]]; 678bf80f4bSopenharmony_ci case AnimationTargetState::STOPPED: 688bf80f4bSopenharmony_ci // Evaluate current value 698bf80f4bSopenharmony_ci Evaluate(); 708bf80f4bSopenharmony_ci // Remove ourselves from the target property's stack 718bf80f4bSopenharmony_ci RemoveModifier(p.stack); 728bf80f4bSopenharmony_ci // Then set the correct keyframe value to the underlying property 738bf80f4bSopenharmony_ci if (auto value = GetState().GetCurrentValue()) { 748bf80f4bSopenharmony_ci p.property->SetValue(*value); 758bf80f4bSopenharmony_ci } 768bf80f4bSopenharmony_ci break; 778bf80f4bSopenharmony_ci case AnimationTargetState::RUNNING: 788bf80f4bSopenharmony_ci // Evaluate current value 798bf80f4bSopenharmony_ci Evaluate(); 808bf80f4bSopenharmony_ci // Add ourselves to the target property's stack 818bf80f4bSopenharmony_ci p.stack->AddModifier(GetSelf<IModifier>()); 828bf80f4bSopenharmony_ci break; 838bf80f4bSopenharmony_ci default: 848bf80f4bSopenharmony_ci break; 858bf80f4bSopenharmony_ci } 868bf80f4bSopenharmony_ci } 878bf80f4bSopenharmony_ci} 888bf80f4bSopenharmony_ci 898bf80f4bSopenharmony_ciEvaluationResult TrackAnimation::ProcessOnGet(IAny& value) 908bf80f4bSopenharmony_ci{ 918bf80f4bSopenharmony_ci if (auto& currentValue = GetState().GetCurrentValue()) { 928bf80f4bSopenharmony_ci if (auto result = value.CopyFrom(*currentValue)) { 938bf80f4bSopenharmony_ci return result == AnyReturn::NOTHING_TO_DO ? EvaluationResult::EVAL_CONTINUE 948bf80f4bSopenharmony_ci : EvaluationResult::EVAL_VALUE_CHANGED; 958bf80f4bSopenharmony_ci } 968bf80f4bSopenharmony_ci } 978bf80f4bSopenharmony_ci return EvaluationResult::EVAL_CONTINUE; 988bf80f4bSopenharmony_ci} 998bf80f4bSopenharmony_ci 1008bf80f4bSopenharmony_civoid TrackAnimation::Start() 1018bf80f4bSopenharmony_ci{ 1028bf80f4bSopenharmony_ci GetState().Start(); 1038bf80f4bSopenharmony_ci} 1048bf80f4bSopenharmony_ci 1058bf80f4bSopenharmony_civoid TrackAnimation::Stop() 1068bf80f4bSopenharmony_ci{ 1078bf80f4bSopenharmony_ci GetState().Stop(); 1088bf80f4bSopenharmony_ci} 1098bf80f4bSopenharmony_ci 1108bf80f4bSopenharmony_civoid TrackAnimation::Pause() 1118bf80f4bSopenharmony_ci{ 1128bf80f4bSopenharmony_ci GetState().Pause(); 1138bf80f4bSopenharmony_ci} 1148bf80f4bSopenharmony_ci 1158bf80f4bSopenharmony_civoid TrackAnimation::Restart() 1168bf80f4bSopenharmony_ci{ 1178bf80f4bSopenharmony_ci GetState().Restart(); 1188bf80f4bSopenharmony_ci} 1198bf80f4bSopenharmony_ci 1208bf80f4bSopenharmony_civoid TrackAnimation::Finish() 1218bf80f4bSopenharmony_ci{ 1228bf80f4bSopenharmony_ci GetState().Finish(); 1238bf80f4bSopenharmony_ci} 1248bf80f4bSopenharmony_ci 1258bf80f4bSopenharmony_civoid TrackAnimation::Seek(float position) 1268bf80f4bSopenharmony_ci{ 1278bf80f4bSopenharmony_ci GetState().Seek(position); 1288bf80f4bSopenharmony_ci} 1298bf80f4bSopenharmony_ci 1308bf80f4bSopenharmony_civoid TrackAnimation::Step(const IClock::ConstPtr& clock) 1318bf80f4bSopenharmony_ci{ 1328bf80f4bSopenharmony_ci GetState().Step(clock); 1338bf80f4bSopenharmony_ci} 1348bf80f4bSopenharmony_ci 1358bf80f4bSopenharmony_civoid TrackAnimation::Evaluate() 1368bf80f4bSopenharmony_ci{ 1378bf80f4bSopenharmony_ci float progress = META_ACCESS_PROPERTY_VALUE(Progress); 1388bf80f4bSopenharmony_ci if (auto curve = META_ACCESS_PROPERTY_VALUE(Curve)) { 1398bf80f4bSopenharmony_ci progress = curve->Transform(progress); 1408bf80f4bSopenharmony_ci } 1418bf80f4bSopenharmony_ci const auto trackState = GetState().UpdateIndex(progress); 1428bf80f4bSopenharmony_ci const PropertyAnimationState::EvaluationData data { GetState().GetCurrentValue(), GetState().GetCurrentTrackStart(), 1438bf80f4bSopenharmony_ci GetState().GetCurrentTrackEnd(), trackState.second, 1448bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(KeyframeCurves)->GetValueAt(trackState.first) }; 1458bf80f4bSopenharmony_ci const auto status = GetState().EvaluateValue(data); 1468bf80f4bSopenharmony_ci UpdateCurrentTrack(trackState.first); 1478bf80f4bSopenharmony_ci if (status == AnyReturn::SUCCESS) { 1488bf80f4bSopenharmony_ci NotifyChanged(); 1498bf80f4bSopenharmony_ci } 1508bf80f4bSopenharmony_ci} 1518bf80f4bSopenharmony_ci 1528bf80f4bSopenharmony_civoid TrackAnimation::RemoveModifier(const IStackProperty::Ptr& stack) 1538bf80f4bSopenharmony_ci{ 1548bf80f4bSopenharmony_ci if (stack) { 1558bf80f4bSopenharmony_ci stack->RemoveModifier(GetSelf<IModifier>()); 1568bf80f4bSopenharmony_ci } 1578bf80f4bSopenharmony_ci} 1588bf80f4bSopenharmony_ci 1598bf80f4bSopenharmony_civoid TrackAnimation::OnPropertyChanged(const TargetProperty& property, const IStackProperty::Ptr& previous) 1608bf80f4bSopenharmony_ci{ 1618bf80f4bSopenharmony_ci if (previous && GetState().IsRunning()) { 1628bf80f4bSopenharmony_ci // Property changed while running, clean up previous property's stack 1638bf80f4bSopenharmony_ci RemoveModifier(previous); 1648bf80f4bSopenharmony_ci if (auto p = interface_cast<IProperty>(previous)) { 1658bf80f4bSopenharmony_ci p->SetValue(*GetState().GetCurrentValue()); 1668bf80f4bSopenharmony_ci } 1678bf80f4bSopenharmony_ci } 1688bf80f4bSopenharmony_ci 1698bf80f4bSopenharmony_ci Initialize(); 1708bf80f4bSopenharmony_ci 1718bf80f4bSopenharmony_ci if (auto p = GetTargetProperty()) { 1728bf80f4bSopenharmony_ci auto& property = p.property; 1738bf80f4bSopenharmony_ci auto& value = property->GetValue(); 1748bf80f4bSopenharmony_ci bool alreadyCompatible = value.GetTypeId() == GetState().GetKeyframeItemTypeId(); 1758bf80f4bSopenharmony_ci if (!alreadyCompatible) { 1768bf80f4bSopenharmony_ci IAny::Ptr array {}; 1778bf80f4bSopenharmony_ci if (!value.IsArray()) { 1788bf80f4bSopenharmony_ci // Clone the target property's value to an array of the value's underlying type 1798bf80f4bSopenharmony_ci array = value.Clone(AnyCloneOptions { CloneValueType::DEFAULT_VALUE, TypeIdRole::ARRAY }); 1808bf80f4bSopenharmony_ci } else { 1818bf80f4bSopenharmony_ci CORE_LOG_E("TrackAnimation: Cannot animate array types"); 1828bf80f4bSopenharmony_ci } 1838bf80f4bSopenharmony_ci if (!array) { 1848bf80f4bSopenharmony_ci CORE_LOG_E("TrackAnimation: Failed to create an array of target property type"); 1858bf80f4bSopenharmony_ci } 1868bf80f4bSopenharmony_ci if (auto kf = interface_pointer_cast<IArrayAny>(array)) { 1878bf80f4bSopenharmony_ci keyframes_->SetValue(*kf); 1888bf80f4bSopenharmony_ci } else { 1898bf80f4bSopenharmony_ci keyframes_->ResetValue(); 1908bf80f4bSopenharmony_ci } 1918bf80f4bSopenharmony_ci } 1928bf80f4bSopenharmony_ci } 1938bf80f4bSopenharmony_ci 1948bf80f4bSopenharmony_ci UpdateValid(); 1958bf80f4bSopenharmony_ci} 1968bf80f4bSopenharmony_ci 1978bf80f4bSopenharmony_cisize_t TrackAnimation::AddKeyframe(float timestamp, const IAny::ConstPtr& value) 1988bf80f4bSopenharmony_ci{ 1998bf80f4bSopenharmony_ci auto index = GetState().AddKeyframe(timestamp, value); 2008bf80f4bSopenharmony_ci if (index != ITrackAnimation::INVALID_INDEX) { 2018bf80f4bSopenharmony_ci keyframes_->NotifyChange(); 2028bf80f4bSopenharmony_ci } 2038bf80f4bSopenharmony_ci return index; 2048bf80f4bSopenharmony_ci} 2058bf80f4bSopenharmony_ci 2068bf80f4bSopenharmony_cibool TrackAnimation::RemoveKeyframe(size_t index) 2078bf80f4bSopenharmony_ci{ 2088bf80f4bSopenharmony_ci bool success = false; 2098bf80f4bSopenharmony_ci if (GetState().RemoveKeyframe(index)) { 2108bf80f4bSopenharmony_ci keyframes_->NotifyChange(); 2118bf80f4bSopenharmony_ci success = true; 2128bf80f4bSopenharmony_ci } else { 2138bf80f4bSopenharmony_ci CORE_LOG_E("TrackAnimation: Cannot remove keyframe from index %u.", static_cast<uint32_t>(index)); 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci return success; 2168bf80f4bSopenharmony_ci} 2178bf80f4bSopenharmony_ci 2188bf80f4bSopenharmony_civoid TrackAnimation::RemoveAllKeyframes() 2198bf80f4bSopenharmony_ci{ 2208bf80f4bSopenharmony_ci Stop(); 2218bf80f4bSopenharmony_ci META_ACCESS_PROPERTY(Timestamps)->Reset(); 2228bf80f4bSopenharmony_ci keyframes_->ResetValue(); 2238bf80f4bSopenharmony_ci UpdateValid(); 2248bf80f4bSopenharmony_ci} 2258bf80f4bSopenharmony_ci 2268bf80f4bSopenharmony_civoid TrackAnimation::UpdateKeyframes() 2278bf80f4bSopenharmony_ci{ 2288bf80f4bSopenharmony_ci IArrayAny::Ptr kfArray; 2298bf80f4bSopenharmony_ci if (auto stack = interface_cast<IStackProperty>(keyframes_)) { 2308bf80f4bSopenharmony_ci // Get the topmost IArrayAny value, that should be our keyframe array 2318bf80f4bSopenharmony_ci auto values = stack->GetValues({}, true); 2328bf80f4bSopenharmony_ci for (auto it = values.rbegin(); it != values.rend(); ++it) { 2338bf80f4bSopenharmony_ci if (auto arr = interface_pointer_cast<IArrayAny>(*it)) { 2348bf80f4bSopenharmony_ci kfArray = arr; 2358bf80f4bSopenharmony_ci break; 2368bf80f4bSopenharmony_ci } 2378bf80f4bSopenharmony_ci } 2388bf80f4bSopenharmony_ci } 2398bf80f4bSopenharmony_ci GetState().SetKeyframes(kfArray); 2408bf80f4bSopenharmony_ci UpdateValid(); 2418bf80f4bSopenharmony_ci} 2428bf80f4bSopenharmony_ci 2438bf80f4bSopenharmony_civoid TrackAnimation::UpdateValid() 2448bf80f4bSopenharmony_ci{ 2458bf80f4bSopenharmony_ci bool valid = false; 2468bf80f4bSopenharmony_ci auto& timestamps = META_ACCESS_PROPERTY(Timestamps); 2478bf80f4bSopenharmony_ci 2488bf80f4bSopenharmony_ci if (const auto p = GetTargetProperty(); p && timestamps) { 2498bf80f4bSopenharmony_ci valid = GetState().UpdateValid(); 2508bf80f4bSopenharmony_ci } 2518bf80f4bSopenharmony_ci 2528bf80f4bSopenharmony_ci if (valid != META_ACCESS_PROPERTY_VALUE(Valid)) { 2538bf80f4bSopenharmony_ci if (!valid) { 2548bf80f4bSopenharmony_ci Stop(); 2558bf80f4bSopenharmony_ci ResetTrack(); 2568bf80f4bSopenharmony_ci } 2578bf80f4bSopenharmony_ci SetValue(META_ACCESS_PROPERTY(Valid), valid); 2588bf80f4bSopenharmony_ci } 2598bf80f4bSopenharmony_ci 2608bf80f4bSopenharmony_ci GetState().ResetCurrentTrack(); 2618bf80f4bSopenharmony_ci} 2628bf80f4bSopenharmony_ci 2638bf80f4bSopenharmony_civoid TrackAnimation::ResetTrack() 2648bf80f4bSopenharmony_ci{ 2658bf80f4bSopenharmony_ci GetState().ResetCurrentTrack(); 2668bf80f4bSopenharmony_ci SetValue(META_ACCESS_PROPERTY(CurrentKeyframeIndex), -1); 2678bf80f4bSopenharmony_ci} 2688bf80f4bSopenharmony_ci 2698bf80f4bSopenharmony_civoid TrackAnimation::UpdateCurrentTrack(uint32_t index) 2708bf80f4bSopenharmony_ci{ 2718bf80f4bSopenharmony_ci auto currentIndex = META_ACCESS_PROPERTY_VALUE(CurrentKeyframeIndex); 2728bf80f4bSopenharmony_ci if (currentIndex != index) { 2738bf80f4bSopenharmony_ci SetValue(META_ACCESS_PROPERTY(CurrentKeyframeIndex), index); 2748bf80f4bSopenharmony_ci if (auto f = META_ACCESS_PROPERTY(KeyframeHandlers)->GetValueAt(index)) { 2758bf80f4bSopenharmony_ci CallMetaFunction<void>(f); 2768bf80f4bSopenharmony_ci } 2778bf80f4bSopenharmony_ci } 2788bf80f4bSopenharmony_ci} 2798bf80f4bSopenharmony_ci 2808bf80f4bSopenharmony_ciReturnError TrackAnimation::Export(IExportContext& c) const 2818bf80f4bSopenharmony_ci{ 2828bf80f4bSopenharmony_ci return Serializer(c) & AutoSerialize() & NamedValue("Keyframes", keyframes_); 2838bf80f4bSopenharmony_ci} 2848bf80f4bSopenharmony_ciReturnError TrackAnimation::Import(IImportContext& c) 2858bf80f4bSopenharmony_ci{ 2868bf80f4bSopenharmony_ci return Serializer(c) & AutoSerialize() & NamedValue("Keyframes", keyframes_); 2878bf80f4bSopenharmony_ci} 2888bf80f4bSopenharmony_ciReturnError TrackAnimation::Finalize(IImportFunctions& f) 2898bf80f4bSopenharmony_ci{ 2908bf80f4bSopenharmony_ci auto res = Super::Finalize(f); 2918bf80f4bSopenharmony_ci if (res) { 2928bf80f4bSopenharmony_ci UpdateKeyframes(); 2938bf80f4bSopenharmony_ci } 2948bf80f4bSopenharmony_ci return res; 2958bf80f4bSopenharmony_ci} 2968bf80f4bSopenharmony_ci} // namespace Internal 2978bf80f4bSopenharmony_ci 2988bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 299