/*---------------------------------------------------------------------------* Project: NintendoWare File: lyt_Animation.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #include #include #include #include #include const f32 R_SAME_TOLERANCE = 1.0e-5F; const f32 R_FRAME_TOLERANCE = 0.001F; namespace nw { namespace lyt { namespace { /*---------------------------------------------------------------------------* @brief f32 型の値を許容値付きで比較します。 @param a 比較する値です。 @param b 比較する値です。 @param tolerance 許容値です。 @return 2つの値の差の絶対値が許容値未満なら true を返します。 *---------------------------------------------------------------------------*/ inline bool RIsSame( const f32 a, const f32 b, const f32 tolerance = R_SAME_TOLERANCE ) { f32 c = a - b; return (-tolerance < c && c < tolerance); } /*---------------------------------------------------------------------------* @brief ステップ形式カーブの特定フレームでの値を取得します。 @param frame 値を取得するフレームです。 @param keyArray ステップ形式キーの配列です。 @param keySize キー数です。 @return 値です。 *---------------------------------------------------------------------------*/ u16 GetStepCurveValue( f32 frame, const res::StepKey* keyArray, u32 keySize ) { NW_ASSERT(keySize > 0); if (keySize == 1 || frame <= keyArray[0].frame) { return keyArray[0].value; } else if (frame >= keyArray[keySize - 1].frame) { return keyArray[keySize - 1].value; } int ikeyL = 0; int ikeyR = (int)keySize - 1; while (ikeyL != ikeyR - 1 && ikeyL != ikeyR) { int ikeyCenter = (ikeyL + ikeyR) / 2; const res::StepKey& centerKey = keyArray[ikeyCenter]; if (frame < centerKey.frame) { ikeyR = ikeyCenter; } else { ikeyL = ikeyCenter; } } if (RIsSame(frame, keyArray[ikeyR].frame, R_FRAME_TOLERANCE)) { return keyArray[ikeyR].value; } else { return keyArray[ikeyL].value; } } /*---------------------------------------------------------------------------* @brief エルミート形式カーブの特定フレームでの値を取得します。 @param frame 値を取得するフレームです。 @param keyArray エルミート形式キーの配列です。 @param keySize キー数です。 @return 値です。 *---------------------------------------------------------------------------*/ f32 GetHermiteCurveValue( f32 frame, const res::HermiteKey* keyArray, u32 keySize ) { NW_ASSERT(keySize > 0); // outside of curve if (keySize == 1 || frame <= keyArray[0].frame) { return keyArray[0].value; } else if (frame >= keyArray[keySize - 1].frame) { return keyArray[keySize - 1].value; } // find 2 keys u32 ikeyL = 0; u32 ikeyR = keySize - 1; while (ikeyL != ikeyR - 1 && ikeyL != ikeyR) { int ikeyCenter = (ikeyL + ikeyR) / 2; if (frame <= keyArray[ikeyCenter].frame) { ikeyR = ikeyCenter; } else { ikeyL = ikeyCenter; } } // calculate hermite interpolation const res::HermiteKey& key0 = keyArray[ikeyL]; const res::HermiteKey& key1 = keyArray[ikeyR]; if (RIsSame(frame, key1.frame, R_FRAME_TOLERANCE)) { if (ikeyR < keySize - 1 && key1.frame == keyArray[ikeyR + 1].frame) { // 同一フレームに値の異なるキーがある場合 return keyArray[ikeyR + 1].value; } else { return key1.value; } } f32 t1 = frame - key0.frame; f32 t2 = 1.0F / (key1.frame - key0.frame); f32 v0 = key0.value; f32 v1 = key1.value; f32 s0 = key0.slope; f32 s1 = key1.slope; f32 t1t1t2 = t1 * t1 * t2; f32 t1t1t2t2 = t1t1t2 * t2; f32 t1t1t1t2t2 = t1 * t1t1t2t2; f32 t1t1t1t2t2t2 = t1t1t1t2t2 * t2; return v0 * (2.0F * t1t1t1t2t2t2 - 3.0F * t1t1t2t2 + 1.0F) + v1 * (-2.0F * t1t1t1t2t2t2 + 3.0F * t1t1t2t2) + s0 * (t1t1t1t2t2 - 2.0F * t1t1t2 + t1) + s1 * (t1t1t1t2t2 - t1t1t2); } void AnimatePaneSRT( Pane* pPane, const res::AnimationInfo* pAnimInfo, const u32* animTargetOffsets, f32 frame ) { for (int i = 0; i < pAnimInfo->num; ++i) { const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); NW_ASSERT(pAnimTarget->target < ANIMTARGET_PANE_MAX); NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ const res::HermiteKey* keys = internal::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keysOffset); pPane->SetSRTElement(pAnimTarget->target, GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum)); } } void AnimateVisibility( Pane* pPane, const res::AnimationInfo* pAnimInfo, const u32* animTargetOffsets, f32 frame ) { for (int i = 0; i < pAnimInfo->num; ++i) { const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); NW_ASSERT(pAnimTarget->target < ANIMTARGET_PANE_MAX); NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_STEP); const res::StepKey* keys = internal::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keysOffset); pPane->SetVisible(0 != GetStepCurveValue(frame, keys, pAnimTarget->keyNum)); } } void AnimateVertexColor( Pane* pPane, const res::AnimationInfo* pAnimInfo, const u32* animTargetOffsets, f32 frame ) { for (int i = 0; i < pAnimInfo->num; ++i) { const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); NW_ASSERT(pAnimTarget->target < ANIMTARGET_PANE_COLOR_MAX); NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ const res::HermiteKey* keys = internal::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keysOffset); f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum); value += 0.5f; u8 u8Val = static_cast(value); pPane->SetColorElement(pAnimTarget->target, u8Val); } } void AnimateMaterialColor( Material* pMaterial, const res::AnimationInfo* pAnimInfo, const u32* animTargetOffsets, f32 frame ) { for (int i = 0; i < pAnimInfo->num; ++i) { const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); NW_ASSERT(pAnimTarget->target < ANIMTARGET_MATCOLOR_MAX); NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ const res::HermiteKey* keys = internal::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keysOffset); f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum); value += 0.5f; u8 val = static_cast(ut::Min(ut::Max(value, 0.f), 255.f)); pMaterial->SetColorElement(pAnimTarget->target, val); } } void AnimateTextureSRT( Material* pMaterial, const res::AnimationInfo* pAnimInfo, const u32* animTargetOffsets, f32 frame ) { for (int i = 0; i < pAnimInfo->num; ++i) { const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); NW_ASSERT(pAnimTarget->id < TexMapMax); if (pAnimTarget->id < pMaterial->GetTexSRTCap()) { NW_ASSERT(pAnimTarget->target < ANIMTARGET_TEXSRT_MAX); NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ const res::HermiteKey* keys = internal::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keysOffset); pMaterial->SetTexSRTElement(pAnimTarget->id, pAnimTarget->target, GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum)); } } } void AnimateTexturePattern( Material* pMaterial, const res::AnimationInfo* pAnimInfo, const u32* animTargetOffsets, f32 frame, const TextureInfo* texInfos ) { for (int j = 0; j < pAnimInfo->num; ++j) { const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[j]); if (pAnimTarget->id < pMaterial->GetTexMapNum()) { NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_STEP); // 現時点ではSTEPのみ NW_ASSERT(pAnimTarget->target == ANIMTARGET_TEXPATTURN_IMAGE); // 現状ではimageのみ const res::StepKey* keys = internal::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keysOffset); const u16 fileIdx = GetStepCurveValue(frame, keys, pAnimTarget->keyNum); if (texInfos[fileIdx].IsValid()) { pMaterial->SetTexMap(pAnimTarget->id, texInfos[fileIdx]); } } } } inline bool IsBindAnimation( Pane* pPane, AnimTransform* pAnimTrans ) { #if defined(NW_RELEASE) NW_UNUSED_VARIABLE(pPane) NW_UNUSED_VARIABLE(pAnimTrans) #else if (pPane->FindAnimationLinkSelf(pAnimTrans)) { NW_WARNING(false, "already bind animation."); return true; } #endif // #if !defined(NW_RELEASE) return false; } inline bool IsBindAnimation( Material* pMaterial, AnimTransform* pAnimTrans ) { #if defined(NW_RELEASE) NW_UNUSED_VARIABLE(pMaterial) NW_UNUSED_VARIABLE(pAnimTrans) #else if (pMaterial->FindAnimationLink(pAnimTrans)) { NW_WARNING(false, "already bind animation."); return true; } #endif // #if !defined(NW_RELEASE) return false; } } // namespace nw::lyt::{no-name} AnimTransform::AnimTransform() : m_pRes(0), m_Frame(0) { } AnimTransform::~AnimTransform() { } u16 AnimTransform::GetFrameSize() const { return m_pRes->frameSize; } bool AnimTransform::IsLoopData() const { return m_pRes->loop != 0; } AnimTransformBasic::AnimTransformBasic() : m_pTexAry(0), m_pAnimLinkAry(0), m_AnimLinkNum(0) { } AnimTransformBasic::~AnimTransformBasic() { Layout::DeleteArray(m_pAnimLinkAry, m_AnimLinkNum); Layout::DeletePrimArray(m_pTexAry); } void AnimTransformBasic::SetResource( const res::AnimationBlock* pRes, ResourceAccessor* pResAccessor ) { NW_NULL_ASSERT(pRes); SetResource(pRes, pResAccessor, pRes->animContNum); } void AnimTransformBasic::SetResource( const res::AnimationBlock* pRes, ResourceAccessor* pResAccessor, u16 animNum ) { NW_ASSERT(m_pTexAry == 0); NW_ASSERT(m_pAnimLinkAry == 0); NW_NULL_ASSERT(pRes); this->SetAnimResource(pRes); m_pTexAry = 0; if (pRes->fileNum > 0) { NW_NULL_ASSERT(pResAccessor); m_pTexAry = Layout::NewArray(pRes->fileNum); if (m_pTexAry) { const u32* fileNameOffsets = internal::ConvertOffsToPtr(pRes, sizeof(*pRes)); for (int i = 0; i < pRes->fileNum; ++i) { const char *const fileName = internal::GetStrTableStr(fileNameOffsets, i); // テクスチャオブジェクトをロードする。 m_pTexAry[i] = pResAccessor->GetTexture(fileName); } } } m_pAnimLinkAry = Layout::NewArray(animNum); if (m_pAnimLinkAry) { m_AnimLinkNum = animNum; } } void AnimTransformBasic::Bind( Pane* pPane, bool bRecursive, bool bDisable ) { NW_NULL_ASSERT(pPane); AnimationLink* pCrAnimLink = 0; const res::AnimationBlock* pRes = this->GetAnimResource(); const u32 *const animContOffsets = internal::ConvertOffsToPtr(pRes, pRes->animContOffsetsOffset); for (u16 i = 0; i < pRes->animContNum; ++i) { const res::AnimationContent& animCont = *internal::ConvertOffsToPtr(pRes, animContOffsets[i]); if (animCont.type == ANIMCONTENTTYPE_PANE) { if (Pane *const pFindPane = pPane->FindPaneByName(animCont.name, bRecursive)) { if (! IsBindAnimation(pFindPane, this)) { pCrAnimLink = Bind(pFindPane, pCrAnimLink, i, bDisable); if (! pCrAnimLink) { break; } } } } else { if (Material *const pFindMat = pPane->FindMaterialByName(animCont.name, bRecursive)) { if (! IsBindAnimation(pFindMat, this)) { pCrAnimLink = Bind(pFindMat, pCrAnimLink, i, bDisable); if (! pCrAnimLink) { break; } } } } } } void AnimTransformBasic::Bind( Material* pMaterial, bool bDisable ) { NW_NULL_ASSERT(pMaterial); AnimationLink* pCrAnimLink = 0; const res::AnimationBlock* pRes = this->GetAnimResource(); const u32 *const animContOffsets = internal::ConvertOffsToPtr(pRes, pRes->animContOffsetsOffset); for (u16 i = 0; i < pRes->animContNum; ++i) { const res::AnimationContent& animCont = *internal::ConvertOffsToPtr(pRes, animContOffsets[i]); if (animCont.type == ANIMCONTENTTYPE_MATERIAL) { if (internal::EqualsMaterialName(pMaterial->GetName(), animCont.name)) { if (! IsBindAnimation(pMaterial, this)) { pCrAnimLink = Bind(pMaterial, pCrAnimLink, i, bDisable); if (! pCrAnimLink) { break; } } } } } } void AnimTransformBasic::Animate(u32 idx, Pane* pPane) { NW_NULL_ASSERT(pPane); const res::AnimationBlock* pRes = this->GetAnimResource(); u32 animContOffsets = internal::ConvertOffsToPtr(pRes, pRes->animContOffsetsOffset)[idx]; const res::AnimationContent* pAnimCont = internal::ConvertOffsToPtr(pRes, animContOffsets); const u32* animInfoOffsets = internal::ConvertOffsToPtr(pAnimCont, sizeof(*pAnimCont)); for (int i = 0; i < pAnimCont->num; ++i) { const res::AnimationInfo* pAnimInfo = internal::ConvertOffsToPtr(pAnimCont, animInfoOffsets[i]); const u32* animTargetOffsets = internal::ConvertOffsToPtr(pAnimInfo, sizeof(*pAnimInfo)); switch (pAnimInfo->kind) { case res::ANIMATIONTYPE_PANESRT: AnimatePaneSRT(pPane, pAnimInfo, animTargetOffsets, this->GetFrame()); break; case res::ANIMATIONTYPE_VISIBILITY: AnimateVisibility(pPane, pAnimInfo, animTargetOffsets, this->GetFrame()); break; case res::ANIMATIONTYPE_VTXCOLOR: AnimateVertexColor(pPane, pAnimInfo, animTargetOffsets, this->GetFrame()); break; } } } void AnimTransformBasic::Animate(u32 idx, Material* pMaterial) { NW_NULL_ASSERT(pMaterial); const res::AnimationBlock* pRes = this->GetAnimResource(); if (pRes == NULL) { NW_WARNING(false, "Animation resource is not set."); return; } u32 animContOffsets = internal::ConvertOffsToPtr(pRes, pRes->animContOffsetsOffset)[idx]; const res::AnimationContent* pAnimCont = internal::ConvertOffsToPtr(pRes, animContOffsets); const u32* animInfoOffsets = internal::ConvertOffsToPtr(pAnimCont, sizeof(*pAnimCont)); for (int i = 0; i < pAnimCont->num; ++i) { const res::AnimationInfo* pAnimInfo = internal::ConvertOffsToPtr(pAnimCont, animInfoOffsets[i]); const u32* animTargetOffsets = internal::ConvertOffsToPtr(pAnimInfo, sizeof(*pAnimInfo)); switch (pAnimInfo->kind) { case res::ANIMATIONTYPE_MATCOLOR: AnimateMaterialColor(pMaterial, pAnimInfo, animTargetOffsets, this->GetFrame()); break; case res::ANIMATIONTYPE_TEXSRT: AnimateTextureSRT(pMaterial, pAnimInfo, animTargetOffsets, this->GetFrame()); break; case res::ANIMATIONTYPE_TEXPATTERN: if (m_pTexAry) { AnimateTexturePattern(pMaterial, pAnimInfo, animTargetOffsets, this->GetFrame(), m_pTexAry); } break; } } } AnimationLink* AnimTransformBasic::FindUnbindLink(AnimationLink* pLink) const { if (pLink == 0) { if (m_pAnimLinkAry == 0) { NW_WARNING(false, "Animation resource is not set."); return 0; } pLink = m_pAnimLinkAry; } while (pLink < m_pAnimLinkAry + m_AnimLinkNum) { if (pLink->GetAnimTransform() == 0) { return pLink; } ++pLink; } return 0; } AnimResource::AnimResource() { Init(); } bool AnimResource::CheckResource() const { if (!m_pResBlock) { NW_WARNING(false, "Animation resource is not set."); return false; } return true; } void AnimResource::Set(const void* anmResBuf) { NW_NULL_ASSERT(anmResBuf); Init(); const ut::BinaryFileHeader *const pFileHeader = static_cast(anmResBuf); if (!ut::IsValidBinaryFile(pFileHeader, res::FILESIGNATURE_CLAN, res::BinaryFileFormatVersion)) { NW_WARNING(false, "not valid layout animation file."); return; } m_pFileHeader = pFileHeader; const ut::BinaryBlockHeader* pDataBlockHead = internal::ConvertOffsToPtr(m_pFileHeader, m_pFileHeader->headerSize); for (int i = 0; i < m_pFileHeader->dataBlocks; ++i) { ut::SigWord kind = pDataBlockHead->kind; switch (kind) { case res::DATABLOCKKIND_PANEANIMTAG: m_pTagBlock = reinterpret_cast(pDataBlockHead); break; case res::DATABLOCKKIND_PANEANIMSHARE: m_pShareBlock = reinterpret_cast(pDataBlockHead); break; case res::DATABLOCKKIND_PANEANIMINFO: m_pResBlock = reinterpret_cast(pDataBlockHead); break; } // 次のブロック位置へ pDataBlockHead = internal::ConvertOffsToPtr(pDataBlockHead, pDataBlockHead->size); } NW_WARNING(m_pResBlock != NULL, "Animation resource is empty."); } void AnimResource::Init() { m_pFileHeader = 0; m_pResBlock = 0; m_pTagBlock = 0; m_pShareBlock = 0; } u16 AnimResource::GetTagOrder() const { if (! m_pTagBlock) { return u16(-1); } return m_pTagBlock->tagOrder; } const char* AnimResource::GetTagName() const { if (! m_pTagBlock) { return 0; } return internal::ConvertOffsToPtr(m_pTagBlock, m_pTagBlock->nameOffset); } u16 AnimResource::GetGroupNum() const { if (! m_pTagBlock) { return 0; } return m_pTagBlock->groupNum; } const AnimationGroupRef* AnimResource::GetGroupArray() const { if (! m_pTagBlock) { return 0; } const AnimationGroupRef *const groups = internal::ConvertOffsToPtr(m_pTagBlock, m_pTagBlock->groupsOffset); return groups; } bool AnimResource::IsDescendingBind() const { if (! m_pTagBlock) { return false; } return internal::TestBit(m_pTagBlock->flag, ANIMTAGFLAG_DESCENDINGBIND); } u16 AnimResource::GetAnimationShareInfoNum() const { if (! m_pShareBlock) { return 0; } return m_pShareBlock->shareNum; } const AnimationShareInfo* AnimResource::GetAnimationShareInfoArray() const { if (! m_pShareBlock) { return 0; } return internal::ConvertOffsToPtr(m_pShareBlock, m_pShareBlock->animShareInfoOffset); } u16 AnimResource::CalcAnimationNum( Pane* pPane, bool bRecursive ) const { if (! CheckResource()) { return 0; } u16 linkNum = 0; const u32 *const animContOffsets = internal::ConvertOffsToPtr(m_pResBlock, m_pResBlock->animContOffsetsOffset); for (u16 i = 0; i < m_pResBlock->animContNum; ++i) { const res::AnimationContent& animCont = *internal::ConvertOffsToPtr(m_pResBlock, animContOffsets[i]); if (animCont.type == ANIMCONTENTTYPE_PANE) { if (Pane *const pFindPane = pPane->FindPaneByName(animCont.name, bRecursive)) { ++linkNum; } } else { if (Material *const pFindMat = pPane->FindMaterialByName(animCont.name, bRecursive)) { ++linkNum; } } } return linkNum; } u16 AnimResource::CalcAnimationNum(Material* pMaterial) const { if (! CheckResource()) { return 0; } u16 linkNum = 0; const u32 *const animContOffsets = internal::ConvertOffsToPtr(m_pResBlock, m_pResBlock->animContOffsetsOffset); for (u16 i = 0; i < m_pResBlock->animContNum; ++i) { const res::AnimationContent& animCont = *internal::ConvertOffsToPtr(m_pResBlock, animContOffsets[i]); if (animCont.type == ANIMCONTENTTYPE_MATERIAL) { if (internal::EqualsMaterialName(pMaterial->GetName(), animCont.name)) { ++linkNum; break; // 同じ名前の res::AnimationContent が複数存在することはないため、 // 見つかったらすぐに抜ける。 } } } return linkNum; } u16 AnimResource::CalcAnimationNum( Group* pGroup, bool bRecursive ) const { NW_NULL_ASSERT(pGroup); u16 linkNum = 0; PaneLinkList& paneList = pGroup->GetPaneList(); for (PaneLinkList::Iterator it = paneList.GetBeginIter(); it != paneList.GetEndIter(); ++it) { linkNum += CalcAnimationNum(it->target, bRecursive); } return linkNum; } namespace internal { AnimPaneTree::AnimPaneTree() { Init(); } AnimPaneTree::AnimPaneTree( Pane* pTargetPane, const AnimResource& animRes) { Init(); Set(pTargetPane, animRes); } u16 AnimPaneTree::FindAnimContent( const res::AnimationBlock* pAnimBlock, const char* animContName, u8 animContType ) { NW_NULL_ASSERT(pAnimBlock); const u32 *const animContOffsets = ConvertOffsToPtr(pAnimBlock, pAnimBlock->animContOffsetsOffset); for (u16 i = 0; i < pAnimBlock->animContNum; ++i) { const res::AnimationContent *const pAnimCont = ConvertOffsToPtr(pAnimBlock, animContOffsets[i]); if (pAnimCont->type == animContType && internal::EqualsMaterialName(pAnimCont->name, animContName)) { return i; } } return NOBIND; } void AnimPaneTree::Init() { m_LinkNum = 0; m_AnimPaneIdx = 0; m_AnimMatCnt = 0; for (u8 i = 0; i < MATERIAL_NUM_MAX; ++i) { m_AnimMatIdxs[i] = 0; } } void AnimPaneTree::Set( Pane* pTargetPane, const AnimResource& animRes ) { NW_NULL_ASSERT(pTargetPane); u16 linkNum = 0; const res::AnimationBlock* pAnimBlock = animRes.GetResourceBlock(); const u16 animContIdx = FindAnimContent(pAnimBlock, pTargetPane->GetName(), ANIMCONTENTTYPE_PANE); if (animContIdx != NOBIND) { ++linkNum; } // マテリアルの処理 const u8 animMatCnt = pTargetPane->GetMaterialNum(); NW_ASSERT(animMatCnt <= MATERIAL_NUM_MAX); u16 animMatIdxs[MATERIAL_NUM_MAX]; for (u8 i = 0; i < animMatCnt; ++i) { animMatIdxs[i] = FindAnimContent(pAnimBlock, pTargetPane->GetMaterial(i)->GetName(), ANIMCONTENTTYPE_MATERIAL); if (animMatIdxs[i] != NOBIND) { ++linkNum; } } // アニメーション対象がひとつも無い if (linkNum == 0) { return; } m_AnimRes = animRes; m_AnimPaneIdx = animContIdx; m_AnimMatCnt = animMatCnt; for (u8 i = 0; i < animMatCnt; ++i) { m_AnimMatIdxs[i] = animMatIdxs[i]; } m_LinkNum = linkNum; } AnimTransform* AnimPaneTree::Bind( Layout* pLayout, Pane* pTargetPane, ResourceAccessor* pResAccessor ) const { NW_NULL_ASSERT(pLayout); NW_NULL_ASSERT(pTargetPane); AnimTransformBasic *const pAnimTrans = static_cast(pLayout->CreateAnimTransform()); pAnimTrans->SetResource(m_AnimRes.GetResourceBlock(), pResAccessor, m_LinkNum); AnimationLink* pCrAnimLink = 0; // ペインのアニメのバインド if (m_AnimPaneIdx != NOBIND) { pCrAnimLink = pAnimTrans->Bind(pTargetPane, pCrAnimLink, m_AnimPaneIdx, true/*bDisable*/); } // マテリアルアニメのバインド // ※マテリアルの個数が共有元ペインと等しいとは限りません。 const u32 animMatMax = ut::Min(m_AnimMatCnt, pTargetPane->GetMaterialNum()); for (u32 i = 0; i < animMatMax; ++i) { if (m_AnimMatIdxs[i] != NOBIND) { Material *const pMaterial = pTargetPane->GetMaterial(i); NW_NULL_ASSERT(pMaterial); pCrAnimLink = pAnimTrans->Bind(pMaterial, pCrAnimLink, m_AnimMatIdxs[i], true/*bDisable*/); } } return pAnimTrans; } AnimationLink* FindAnimationLink( AnimationList* pAnimList, AnimTransform* pAnimTrans ) { NW_NULL_ASSERT(pAnimList); NW_NULL_ASSERT(pAnimTrans); for (AnimationList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter(); ++it) { if (pAnimTrans == it->GetAnimTransform()) { return &(*it); } } return 0; } AnimationLink* FindAnimationLink( AnimationList* pAnimList, const AnimResource& animRes ) { NW_NULL_ASSERT(pAnimList); for (AnimationList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter(); ++it) { if (animRes.GetResourceBlock() == it->GetAnimTransform()->GetAnimResource()) { return &(*it); } } return 0; } void UnbindAnimationLink( AnimationList* pAnimList, AnimTransform* pAnimTrans ) { NW_NULL_ASSERT(pAnimList); for (AnimationList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter();) { AnimationList::Iterator currIt = it++; if (! pAnimTrans || currIt->GetAnimTransform() == pAnimTrans) { pAnimList->Erase(currIt); currIt->Reset(); } } } } // namespace nw::lyt::internal } // namespace nw::lyt } // namespace nw