1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     anim_ResUtil.cpp
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 28032 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "../precompiled.h"
17 #include <string.h>
18 
19 #include <nw/anim/res/anim_ResUtil.h>
20 
21 namespace {
22 
23 //---------------------------------------------------------------------------
24 //! @brief        テクスチャパターンアニメのリソースの複製を作成します。
25 //!
26 //!               アニメーションカーブ、テクスチャのパスは、クローン元のアドレスを参照します。
27 //!               ひとつのテクスチャパターンアニメを共有する際に使用することを想定しています。
28 //!
29 //! @return       複製したリソースを返します。
30 //---------------------------------------------------------------------------
CloneTextureAnimMember(nw::os::IAllocator * allocator,const nw::anim::ResTextureAnim & src)31 nw::anim::ResTextureAnim CloneTextureAnimMember(
32     nw::os::IAllocator* allocator,
33     const nw::anim::ResTextureAnim& src
34 )
35 {
36     const int texturesCount = src.GetTexturesCount();
37     void* texturesTableMemory =
38         allocator->Alloc(sizeof(nw::ut::Offset) * texturesCount);
39     nw::ut::Offset* texturesTable =
40         reinterpret_cast<nw::ut::Offset*>(texturesTableMemory);
41 
42     void* texturesMemory =
43         allocator->Alloc(sizeof(nw::gfx::ResReferenceTextureData) * texturesCount);
44     nw::gfx::ResReferenceTextureData* textures =
45         reinterpret_cast<nw::gfx::ResReferenceTextureData*>(texturesMemory);
46 
47     for (int i = 0; i < texturesCount; ++i)
48     {
49         nw::gfx::ResReferenceTextureData& texture = textures[i];
50         const nw::gfx::ResReferenceTextureData* srcTexture = src.GetTextures(i).ptr();
51 
52         // ResSceneObject
53         texture.typeInfo = srcTexture->typeInfo;
54         texture.m_Header.signature = srcTexture->m_Header.signature;
55         texture.m_Header.revision = srcTexture->m_Header.signature;
56         texture.toName.set_ptr(srcTexture->toName.to_ptr());
57         texture.m_UserDataDicCount = srcTexture->m_UserDataDicCount;
58         texture.toUserDataDic.set_ptr(srcTexture->toUserDataDic.to_ptr());
59 
60         // ResTextureは空
61         // ResReferenveTexture
62         texture.toPath.set_ptr(srcTexture->toPath.to_ptr());
63         texture.toTargetTexture.set_ptr(NULL); // ここはsetupで解決される
64 
65         texturesTable[i].set_ptr(&texture);
66     }
67 
68     void* animMemory = allocator->Alloc(sizeof(nw::anim::ResTextureAnimData));
69     nw::anim::ResTextureAnimData* anim = new(animMemory) nw::anim::ResTextureAnimData;
70 
71     anim->toCurve.set_ptr(src.ptr()->toCurve.to_ptr());
72     anim->m_TexturesTableCount = texturesCount;
73     anim->toTexturesTable.set_ptr(texturesTable);
74 
75     return nw::anim::ResTextureAnim(anim);
76 }
77 
DestroyTextureAnimMember(nw::os::IAllocator * allocator,nw::anim::ResTextureAnim anim)78 void DestroyTextureAnimMember(
79     nw::os::IAllocator* allocator,
80     nw::anim::ResTextureAnim anim
81 )
82 {
83     const int texturesCount = anim.GetTexturesCount();
84 
85     // メモリ確保時には先頭のポインタでサイズ分確保しているので、先頭を解放
86     allocator->Free(anim.GetTextures(0).ptr());
87     allocator->Free(anim.ptr()->toTexturesTable.to_ptr());
88     allocator->Free(anim.ptr());
89 }
90 
91 }
92 
93 namespace nw {
94 namespace anim {
95 namespace res {
96 
97 //----------------------------------------
CloneTextureAnim(os::IAllocator * allocator,const ResAnim & src)98 ResAnim CloneTextureAnim(os::IAllocator* allocator, const ResAnim& src)
99 {
100     // MaterialAnimationでなければならない
101     NW_ASSERT(strcmp(src.GetTargetAnimGroupName(), "MaterialAnimation") == 0);
102 
103     // NOTE:
104     // シーケンシャルなメモリ配置になっていません。
105     // 問題が起こるならば対処の必要があります。
106 
107     // ResAnimをクローンします。
108     void* animMemory = allocator->Alloc(sizeof(ResAnimData));
109     ResAnimData* animData = reinterpret_cast<ResAnimData*>(animMemory);
110 
111     animData->m_Header.revision = src.ptr()->m_Header.revision;
112     animData->m_Header.signature = src.ptr()->m_Header.signature;
113     animData->toName.set_ptr(src.ptr()->toName.to_ptr());
114     animData->toTargetAnimGroupName.set_ptr(src.ptr()->toTargetAnimGroupName.to_ptr());
115     animData->m_LoopMode = src.ptr()->m_LoopMode;
116     animData->m_FrameSize = src.ptr()->m_FrameSize;
117     animData->m_MemberAnimSetDicCount = src.ptr()->m_MemberAnimSetDicCount;
118     //animData->toMemberAnimSetDic には後でクローンした辞書を登録します
119     animData->m_UserDataDicCount = src.ptr()->m_UserDataDicCount;
120     animData->toUserDataDic.set_ptr(src.ptr()->toUserDataDic.to_ptr());
121 
122     // MemberAnimSetをクローンします。
123     const int memberCount = src.ptr()->m_MemberAnimSetDicCount;
124     const size_t size =
125         sizeof(ut::ResDicPatriciaData) + (sizeof(ut::ResDicPatriciaData::ResDicNodeData) * memberCount);
126     void* memberMemory = allocator->Alloc(size);
127 
128     memcpy(memberMemory, src.ptr()->toMemberAnimSetDic.to_ptr(), size);
129     ut::ResDicPatriciaData* memberDic = reinterpret_cast<ut::ResDicPatriciaData*>(memberMemory);
130 
131     const ut::ResDicPatriciaData* origDic =
132         reinterpret_cast<const ut::ResDicPatriciaData*>(src.ptr()->toMemberAnimSetDic.to_ptr());
133 
134     for (int i = 0; i < memberCount; ++i)
135     {
136         // dictionary->data[0]はルートノードが入っている(ResDicPatriciaの実装参照)
137         // なので、変更を行うdataテーブルのindexは[i+1]が正しい値になる
138         const int idx = i+1;
139 
140         // memcpyでResU32やResU16の値はオリジナルと同じ値がコピーされるが、
141         // Dictionary内のOffsetは関係ないポインタを指してしまう。
142         // (Offsetの値がコピーされても、その基準になるポインタがずれるため。)
143         // なので、オリジナルと同じポインタへのオフセットになるように修正が必要。
144         memberDic->data[idx].ofsString.set_ptr( origDic->data[idx].ofsString.to_ptr() );
145         memberDic->data[idx].ofsData.set_ptr( origDic->data[idx].ofsData.to_ptr() );
146 
147         // Textureのアニメの場合のみ、ofsDataに独自にクローンしたデータを登録する
148         if (src.GetMemberAnimSet(i).GetPrimitiveType() ==
149             ResMemberAnim::PRIMITIVETYPE_TEXTURE)
150         {
151             ResTextureAnim dup = CloneTextureAnimMember(allocator, src.GetMemberAnimSet(i));
152             memberDic->data[idx].ofsData.set_ptr(dup.ptr());
153         }
154     }
155 
156     animData->toMemberAnimSetDic.set_ptr(memberDic);
157 
158     return ResAnim(animData);
159 }
160 
161 //----------------------------------------
DestroyClonedTextureAnim(os::IAllocator * allocator,ResAnim anim)162 void DestroyClonedTextureAnim(os::IAllocator* allocator, ResAnim anim)
163 {
164     if (!anim.IsValid())
165     {
166         return;
167     }
168 
169     // 渡されたanimがCloneの結果である時しか考慮しない。
170 
171     // 複製したmemberAnim(ResTextureAnim)を破棄する。
172     for (int i = 0; i < anim.GetMemberAnimSetCount(); ++i)
173     {
174         if (anim.GetMemberAnimSet(i).GetPrimitiveType() ==
175             ResMemberAnim::PRIMITIVETYPE_TEXTURE)
176         {
177             DestroyTextureAnimMember(allocator, anim.GetMemberAnimSet(i));
178         }
179     }
180 
181     // MemberAnimSetを破棄する。
182     allocator->Free(anim.ptr()->toMemberAnimSetDic.to_ptr());
183 
184     // ResAnim本体を破棄する。
185     // 個別に解放した箇所以外はoriginalへのポインタを保持するのみなので、解放しない。
186     allocator->Free(anim.ptr());
187 }
188 
189 } /* namespace res */
190 } /* namespace anim */
191 } /* namespace nw */
192