/*---------------------------------------------------------------------------* Project: NintendoWare File: anim_ResUtil.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. 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. $Revision: 28032 $ *---------------------------------------------------------------------------*/ #include "../precompiled.h" #include #include namespace { //--------------------------------------------------------------------------- //! @brief テクスチャパターンアニメのリソースの複製を作成します。 //! //! アニメーションカーブ、テクスチャのパスは、クローン元のアドレスを参照します。 //! ひとつのテクスチャパターンアニメを共有する際に使用することを想定しています。 //! //! @return 複製したリソースを返します。 //--------------------------------------------------------------------------- nw::anim::ResTextureAnim CloneTextureAnimMember( nw::os::IAllocator* allocator, const nw::anim::ResTextureAnim& src ) { const int texturesCount = src.GetTexturesCount(); void* texturesTableMemory = allocator->Alloc(sizeof(nw::ut::Offset) * texturesCount); nw::ut::Offset* texturesTable = reinterpret_cast(texturesTableMemory); void* texturesMemory = allocator->Alloc(sizeof(nw::gfx::ResReferenceTextureData) * texturesCount); nw::gfx::ResReferenceTextureData* textures = reinterpret_cast(texturesMemory); for (int i = 0; i < texturesCount; ++i) { nw::gfx::ResReferenceTextureData& texture = textures[i]; const nw::gfx::ResReferenceTextureData* srcTexture = src.GetTextures(i).ptr(); // ResSceneObject texture.typeInfo = srcTexture->typeInfo; texture.m_Header.signature = srcTexture->m_Header.signature; texture.m_Header.revision = srcTexture->m_Header.signature; texture.toName.set_ptr(srcTexture->toName.to_ptr()); texture.m_UserDataDicCount = srcTexture->m_UserDataDicCount; texture.toUserDataDic.set_ptr(srcTexture->toUserDataDic.to_ptr()); // ResTextureは空 // ResReferenveTexture texture.toPath.set_ptr(srcTexture->toPath.to_ptr()); texture.toTargetTexture.set_ptr(NULL); // ここはsetupで解決される texturesTable[i].set_ptr(&texture); } void* animMemory = allocator->Alloc(sizeof(nw::anim::ResTextureAnimData)); nw::anim::ResTextureAnimData* anim = new(animMemory) nw::anim::ResTextureAnimData; anim->toCurve.set_ptr(src.ptr()->toCurve.to_ptr()); anim->m_TexturesTableCount = texturesCount; anim->toTexturesTable.set_ptr(texturesTable); return nw::anim::ResTextureAnim(anim); } void DestroyTextureAnimMember( nw::os::IAllocator* allocator, nw::anim::ResTextureAnim anim ) { const int texturesCount = anim.GetTexturesCount(); // メモリ確保時には先頭のポインタでサイズ分確保しているので、先頭を解放 allocator->Free(anim.GetTextures(0).ptr()); allocator->Free(anim.ptr()->toTexturesTable.to_ptr()); allocator->Free(anim.ptr()); } } namespace nw { namespace anim { namespace res { //---------------------------------------- ResAnim CloneTextureAnim(os::IAllocator* allocator, const ResAnim& src) { // MaterialAnimationでなければならない NW_ASSERT(strcmp(src.GetTargetAnimGroupName(), "MaterialAnimation") == 0); // NOTE: // シーケンシャルなメモリ配置になっていません。 // 問題が起こるならば対処の必要があります。 // ResAnimをクローンします。 void* animMemory = allocator->Alloc(sizeof(ResAnimData)); ResAnimData* animData = reinterpret_cast(animMemory); animData->m_Header.revision = src.ptr()->m_Header.revision; animData->m_Header.signature = src.ptr()->m_Header.signature; animData->toName.set_ptr(src.ptr()->toName.to_ptr()); animData->toTargetAnimGroupName.set_ptr(src.ptr()->toTargetAnimGroupName.to_ptr()); animData->m_LoopMode = src.ptr()->m_LoopMode; animData->m_FrameSize = src.ptr()->m_FrameSize; animData->m_MemberAnimSetDicCount = src.ptr()->m_MemberAnimSetDicCount; //animData->toMemberAnimSetDic には後でクローンした辞書を登録します animData->m_UserDataDicCount = src.ptr()->m_UserDataDicCount; animData->toUserDataDic.set_ptr(src.ptr()->toUserDataDic.to_ptr()); // MemberAnimSetをクローンします。 const int memberCount = src.ptr()->m_MemberAnimSetDicCount; const size_t size = sizeof(ut::ResDicPatriciaData) + (sizeof(ut::ResDicPatriciaData::ResDicNodeData) * memberCount); void* memberMemory = allocator->Alloc(size); memcpy(memberMemory, src.ptr()->toMemberAnimSetDic.to_ptr(), size); ut::ResDicPatriciaData* memberDic = reinterpret_cast(memberMemory); const ut::ResDicPatriciaData* origDic = reinterpret_cast(src.ptr()->toMemberAnimSetDic.to_ptr()); for (int i = 0; i < memberCount; ++i) { // dictionary->data[0]はルートノードが入っている(ResDicPatriciaの実装参照) // なので、変更を行うdataテーブルのindexは[i+1]が正しい値になる const int idx = i+1; // memcpyでResU32やResU16の値はオリジナルと同じ値がコピーされるが、 // Dictionary内のOffsetは関係ないポインタを指してしまう。 // (Offsetの値がコピーされても、その基準になるポインタがずれるため。) // なので、オリジナルと同じポインタへのオフセットになるように修正が必要。 memberDic->data[idx].ofsString.set_ptr( origDic->data[idx].ofsString.to_ptr() ); memberDic->data[idx].ofsData.set_ptr( origDic->data[idx].ofsData.to_ptr() ); // Textureのアニメの場合のみ、ofsDataに独自にクローンしたデータを登録する if (src.GetMemberAnimSet(i).GetPrimitiveType() == ResMemberAnim::PRIMITIVETYPE_TEXTURE) { ResTextureAnim dup = CloneTextureAnimMember(allocator, src.GetMemberAnimSet(i)); memberDic->data[idx].ofsData.set_ptr(dup.ptr()); } } animData->toMemberAnimSetDic.set_ptr(memberDic); return ResAnim(animData); } //---------------------------------------- void DestroyClonedTextureAnim(os::IAllocator* allocator, ResAnim anim) { if (!anim.IsValid()) { return; } // 渡されたanimがCloneの結果である時しか考慮しない。 // 複製したmemberAnim(ResTextureAnim)を破棄する。 for (int i = 0; i < anim.GetMemberAnimSetCount(); ++i) { if (anim.GetMemberAnimSet(i).GetPrimitiveType() == ResMemberAnim::PRIMITIVETYPE_TEXTURE) { DestroyTextureAnimMember(allocator, anim.GetMemberAnimSet(i)); } } // MemberAnimSetを破棄する。 allocator->Free(anim.ptr()->toMemberAnimSetDic.to_ptr()); // ResAnim本体を破棄する。 // 個別に解放した箇所以外はoriginalへのポインタを保持するのみなので、解放しない。 allocator->Free(anim.ptr()); } } /* namespace res */ } /* namespace anim */ } /* namespace nw */