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