#include "Runtime/Character/CAnimTreeTransition.hpp" namespace metaforce { std::string CAnimTreeTransition::CreatePrimitiveName(const std::weak_ptr&, const std::weak_ptr&, float) { return {}; } CAnimTreeTransition::CAnimTreeTransition(bool b1, const std::weak_ptr& a, const std::weak_ptr& b, const CCharAnimTime& transDur, const CCharAnimTime& timeInTrans, bool runA, bool loopA, int flags, std::string_view name, bool initialized) : CAnimTreeTweenBase(b1, a, b, flags, name) , x24_transDur(transDur) , x2c_timeInTrans(timeInTrans) , x34_runA(runA) , x35_loopA(loopA) , x36_initialized(initialized) {} CAnimTreeTransition::CAnimTreeTransition(bool b1, const std::weak_ptr& a, const std::weak_ptr& b, const CCharAnimTime& transDur, bool runA, int flags, std::string_view name) : CAnimTreeTweenBase(b1, a, b, flags, name) , x24_transDur(transDur) , x34_runA(runA) , x35_loopA(a.lock()->VGetBoolPOIState("Loop")) {} std::shared_ptr CAnimTreeTransition::VGetBestUnblendedChild() const { std::shared_ptr child = x18_b->GetBestUnblendedChild(); return (child ? child : x18_b); } CCharAnimTime CAnimTreeTransition::VGetTimeRemaining() const { CCharAnimTime transTimeRem = x24_transDur - x2c_timeInTrans; CCharAnimTime rightTimeRem = x18_b->VGetTimeRemaining(); return (rightTimeRem < transTimeRem) ? transTimeRem : rightTimeRem; } CSteadyStateAnimInfo CAnimTreeTransition::VGetSteadyStateAnimInfo() const { CSteadyStateAnimInfo bInfo = x18_b->VGetSteadyStateAnimInfo(); if (x24_transDur < bInfo.GetDuration()) return CSteadyStateAnimInfo(bInfo.IsLooping(), bInfo.GetDuration(), bInfo.GetOffset()); return CSteadyStateAnimInfo(bInfo.IsLooping(), x24_transDur, bInfo.GetOffset()); } std::unique_ptr CAnimTreeTransition::VClone() const { return std::make_unique( x20_24_b1, std::static_pointer_cast(std::shared_ptr(x14_a->Clone())), std::static_pointer_cast(std::shared_ptr(x18_b->Clone())), x24_transDur, x2c_timeInTrans, x34_runA, x35_loopA, x1c_flags, x4_name, x36_initialized); } std::optional> CAnimTreeTransition::VSimplified() { if (zeus::close_enough(GetBlendingWeight(), 1.f)) { if (auto simp = x18_b->Simplified()) return simp; return {x18_b->Clone()}; } return CAnimTreeTweenBase::VSimplified(); } std::optional> CAnimTreeTransition::VReverseSimplified() { if (zeus::close_enough(GetBlendingWeight(), 0.f)) return {x14_a->Clone()}; return CAnimTreeTweenBase::VReverseSimplified(); } SAdvancementResults CAnimTreeTransition::AdvanceViewForTransitionalPeriod(const CCharAnimTime& time) { IncAdvancementDepth(); CDoubleChildAdvancementResult res = AdvanceViewBothChildren(time, x34_runA, x35_loopA); DecAdvancementDepth(); if (res.GetTrueAdvancement().EqualsZero()) return {}; float oldWeight = GetBlendingWeight(); x2c_timeInTrans += res.GetTrueAdvancement(); float newWeight = GetBlendingWeight(); if (ShouldCullTree()) { if (newWeight < 0.5f) x20_25_cullSelector = 1; else x20_25_cullSelector = 2; } if (x1c_flags & 0x1) { return {res.GetTrueAdvancement(), SAdvancementDeltas::Interpolate(res.GetLeftAdvancementDeltas(), res.GetRightAdvancementDeltas(), oldWeight, newWeight)}; } return {res.GetTrueAdvancement(), res.GetRightAdvancementDeltas()}; } SAdvancementResults CAnimTreeTransition::VAdvanceView(const CCharAnimTime& time) { if (time.EqualsZero()) { IncAdvancementDepth(); x18_b->VAdvanceView(time); if (x34_runA) x14_a->VAdvanceView(time); DecAdvancementDepth(); if (ShouldCullTree()) x20_25_cullSelector = 1; return {}; } if (!x36_initialized) x36_initialized = true; if (x2c_timeInTrans + time < x24_transDur) { SAdvancementResults res = AdvanceViewForTransitionalPeriod(time); res.x0_remTime = time - res.x0_remTime; return res; } CCharAnimTime transTimeRem = x24_transDur - x2c_timeInTrans; SAdvancementResults res; if (transTimeRem.GreaterThanZero()) { res = AdvanceViewForTransitionalPeriod(transTimeRem); if (res.x0_remTime != transTimeRem) return res; // NOTE: URDE can hit an infinite loop if transTimeRem // becomes negative (floating point inaccuracy). // This line was moved into this branch as a workaround. res.x0_remTime = time - transTimeRem; } return res; } void CAnimTreeTransition::SetBlendingWeight(float w) { std::static_pointer_cast(x18_b)->SetBlendingWeight(w); } float CAnimTreeTransition::VGetBlendingWeight() const { if (x24_transDur.GreaterThanZero()) return x2c_timeInTrans.GetSeconds() / x24_transDur.GetSeconds(); return 0.f; } } // namespace metaforce