1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_AnimGroup.h
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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_GFX_ANIMGROUP_H_
19 #define NW_GFX_ANIMGROUP_H_
20 
21 #include <nw/anim/res/anim_ResAnimGroup.h>
22 #include <nw/gfx/gfx_Common.h>
23 #include <nw/gfx/gfx_GfxObject.h>
24 #include <nw/ut/ut_MoveArray.h>
25 
26 namespace nw {
27 
28 namespace anim {
29 
30 class AnimBlendOp;
31 
32 }
33 
34 namespace gfx {
35 
36 class SceneNode;
37 
38 //---------------------------------------------------------------------------
39 //! @brief アニメーション対象を抽象化するクラスです。
40 //!
41 //! アニメーション対象メンバへのポインタを保持します。
42 //! 対象メンバとはボーンのトランスフォーム、マテリアルのディフューズカラーといった単位です。
43 //!
44 //! また、対象メンバのオリジナル値(インスタンス生成時の値)を保存しています。
45 //---------------------------------------------------------------------------
46 class AnimGroup : public GfxObject
47 {
48 public:
49     //! @brief 評価前コールバック関数の定義です。
50     //! 対象オブジェクトの評価が必要なら true を返します。
51     typedef bool (*PreEvaluateCallback)(AnimGroup* animGroup, int targetObjIdx);
52 
53     //----------------------------------------
54     //! @name 作成
55     //@{
56 
57     //! アニメーショングループを構築するクラスです。
58     class Builder
59     {
60     public:
61         //! コンストラクタです。
Builder()62         Builder()
63         : m_SceneNode(NULL),
64           m_UseOriginalValue(false) {}
65 
66         //! アニメーショングループリソースを設定します。
ResAnimGroup(anim::ResAnimGroup resAnimGroup)67         Builder& ResAnimGroup(anim::ResAnimGroup resAnimGroup)
68         {
69             m_ResAnimGroup = resAnimGroup;
70             return *this;
71         }
72 
73         //! 対象となるシーンノードを設定します。
SetSceneNode(SceneNode * sceneNode)74         Builder& SetSceneNode(SceneNode* sceneNode) { m_SceneNode = sceneNode; return *this; }
75 
76         //! オリジナル値を使用するかどうかを設定します。
UseOriginalValue(bool use)77         Builder& UseOriginalValue(bool use) { m_UseOriginalValue = use; return *this; }
78 
79         //! @brief 生成時に必要なメモリサイズを取得します。
80         //!
81         //! メモリサイズは Builder の設定によって変化します。
82         //! すべての設定が終わった後にこの関数を呼び出してください。
83         //!
84         //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
85         size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
86         {
87             os::MemorySizeCalculator size(alignment);
88 
89             GetMemorySizeInternal(&size);
90 
91             return size.GetSizeWithPadding(alignment);
92         }
93 
94         //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)95         void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
96         {
97             os::MemorySizeCalculator& size = *pSize;
98 
99             size += sizeof(AnimGroup);
100             AnimGroup::GetMemorySizeForInitialize(pSize, m_ResAnimGroup, m_UseOriginalValue);
101         }
102 
103         //! @brief アニメーショングループを生成します。
104         //!
105         //! @param[in] allocator アロケータです。
106         //!
107         //! @return 生成されたアニメーショングループです。
108         //!
Create(os::IAllocator * allocator)109         AnimGroup* Create(os::IAllocator* allocator)
110         {
111             void* buf = allocator->Alloc(sizeof(AnimGroup));
112 
113             if (buf == NULL)
114             {
115                 return NULL;
116             }
117 
118             AnimGroup* animGroup = new(buf) AnimGroup(m_ResAnimGroup, m_SceneNode, allocator);
119 
120             Result result = animGroup->Initialize(m_UseOriginalValue);
121 
122             if (result.IsSuccess())
123             {
124                 return animGroup;
125             }
126             else
127             {
128                 SafeDestroy(animGroup);
129                 return NULL;
130             }
131         }
132 
133     private:
134         SceneNode* m_SceneNode;
135         anim::ResAnimGroup m_ResAnimGroup;
136         bool m_UseOriginalValue;
137     };
138 
139     //@}
140 
141     //----------------------------------------
142     //! @name 取得/設定
143     //@{
144 
145     //! アニメーショングループリソースを取得します。
GetResAnimGroup()146     anim::ResAnimGroup GetResAnimGroup() const { return m_ResAnimGroup; }
147 
148     //! グラフィックスアニメーショングループリソースを取得します。
GetResGraphicsAnimGroup()149     anim::ResGraphicsAnimGroup GetResGraphicsAnimGroup() const
150     {
151         return *reinterpret_cast<const anim::ResGraphicsAnimGroup*>(&m_ResAnimGroup);
152     }
153 
154     //! アニメーショングループメンバリソースを取得します。
GetResAnimGroupMember(int memberIdx)155     anim::ResAnimGroupMember GetResAnimGroupMember(int memberIdx) const { return m_ResAnimGroup.GetMemberInfoSet(memberIdx); }
156 
157     //! アニメーショングループメンバリソースを取得します。
GetResAnimGroupMember(const char * key)158     anim::ResAnimGroupMember GetResAnimGroupMember(const char* key) const { return m_ResAnimGroup.GetMemberInfoSet(key); }
159 
160     //! アニメーショングループメンバリソースのインデックスを取得します。
GetResAnimGroupMemberIndex(const char * key)161     int GetResAnimGroupMemberIndex(const char* key) const { return m_ResAnimGroup.GetMemberInfoSetIndex(key); }
162 
163     //! 名前を取得します。
GetName()164     const char* GetName() const { return m_ResAnimGroup.GetName(); }
165 
166     //! アニメーショングループメンバ数を取得します。
GetMemberCount()167     s32 GetMemberCount() const { return m_ResAnimGroup.GetMemberInfoSetCount(); }
168 
169     //! アニメーショングループ内のブレンドオペレーションを取得します。
GetBlendOperationInGroup(int blendOpIdx)170     const anim::AnimBlendOp* GetBlendOperationInGroup(int blendOpIdx) const
171     {
172         NW_MINMAXLT_ASSERT(blendOpIdx, 0, m_BlendOperations.Size());
173         return m_BlendOperations[blendOpIdx];
174     }
175 
176     //! アニメーショングループ内のブレンドオペレーションを設定します。
SetBlendOperationInGroup(int blendOpIdx,anim::AnimBlendOp * blendOp)177     void SetBlendOperationInGroup(int blendOpIdx, anim::AnimBlendOp* blendOp)
178     {
179         NW_MINMAXLT_ASSERT(blendOpIdx, 0, m_BlendOperations.Size());
180         m_BlendOperations[blendOpIdx] = blendOp;
181     }
182 
183     //! メンバに対するブレンドオペレーションを取得します。
GetBlendOperation(int memberIdx)184     const anim::AnimBlendOp* GetBlendOperation(int memberIdx) const
185     {
186         return GetBlendOperationInGroup(
187             GetResAnimGroupMember(memberIdx).GetBlendOperationIndex());
188     }
189 
190     //! 対象オブジェクトが属するシーンノードを取得します。
GetSceneNode()191     SceneNode* GetSceneNode() const { return m_SceneNode; }
192 
193     //! 対象オブジェクトのインデックスを取得します。
GetTargetObjectIndex(int memberIdx)194     int GetTargetObjectIndex(int memberIdx) const
195     {
196         NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjectIndicies.Size());
197         return m_TargetObjectIndicies[memberIdx];
198     }
199 
200     //! 対象オブジェクトのインデックスを設定します。
SetTargetObjectIndex(int memberIdx,const int targetObjIdx)201     void SetTargetObjectIndex(int memberIdx, const int targetObjIdx)
202     {
203         NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjectIndicies.Size());
204         m_TargetObjectIndicies[memberIdx] = targetObjIdx;
205     }
206 
207     //! 対象オブジェクトのポインタを取得します。
GetTargetObject(int memberIdx)208     void* GetTargetObject(int memberIdx) const
209     {
210         NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjects.Size());
211         return m_TargetObjects[memberIdx];
212     }
213 
214     //! 対象オブジェクトのポインタを設定します。
SetTargetObject(int memberIdx,void * object)215     void SetTargetObject(int memberIdx, void* object)
216     {
217         NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjects.Size());
218         m_TargetObjects[memberIdx] = object;
219     }
220 
221     //! 対象メンバのポインタを取得します。
GetTargetPtr(int memberIdx)222     void* GetTargetPtr(int memberIdx) const
223     {
224         NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetPtrs.Size());
225         return m_TargetPtrs[memberIdx];
226     }
227 
228     //! 対象メンバのポインタを設定します。
SetTargetPtr(int memberIdx,void * target)229     void SetTargetPtr(int memberIdx, void* target)
230     {
231         NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetPtrs.Size());
232         m_TargetPtrs[memberIdx] = target;
233     }
234 
235     //! メンバのオリジナル値を持っているかどうかを取得します。
HasOriginalValue()236     bool HasOriginalValue() const { return m_OriginalValues.Size() != 0; }
237 
238     //! メンバのオリジナル値を取得します。
GetOriginalValue(int memberIdx)239     const void* GetOriginalValue(int memberIdx) const
240     {
241         NW_MINMAXLT_ASSERT(memberIdx, 0, m_OriginalValues.Size());
242         return m_OriginalValues[memberIdx];
243     }
244 
245     //! メンバのオリジナル値を設定します。
SetOriginalValue(int memberIdx,const void * value)246     void SetOriginalValue(int memberIdx, const void* value)
247     {
248         NW_MINMAXLT_ASSERT(memberIdx, 0, m_OriginalValues.Size());
249         m_OriginalValues[memberIdx] = value;
250     }
251 
252     //! 評価前コールバック関数を取得します。
GetPreEvaluateCallback()253     PreEvaluateCallback GetPreEvaluateCallback() const { return m_PreEvaluateCallback; }
254 
255     //! 評価前コールバック関数を設定します。
SetPreEvaluateCallback(PreEvaluateCallback function)256     void SetPreEvaluateCallback(PreEvaluateCallback function) { m_PreEvaluateCallback = function; }
257 
258     //! フルベイクアニメーションを使用するかを取得します。
259     //!
260     //! :private
GetFullBakedAnimEnabled()261     bool GetFullBakedAnimEnabled() const { return m_FullBakedAnimEnabled; }
262 
263     //! フルベイクアニメーションを使用するかを設定します。
264     //!
265     //! :private
SetFullBakedAnimEnabled(bool enable)266     void SetFullBakedAnimEnabled(bool enable) { m_FullBakedAnimEnabled = enable; }
267 
268     //! @brief すべてのメンバをオリジナル値にリセットします。
269     void Reset();
270 
271     //@}
272 
273 protected:
274     //----------------------------------------
275     //! @name コンストラクタ/デストラクタ
276     //@{
277 
278     //! コンストラクタです。
279     //!
280     //! :private
281     AnimGroup(
282         anim::ResAnimGroup resAnimGroup,
283         SceneNode* sceneNode,
284         os::IAllocator* allocator);
285 
286     //! デストラクタです。
287     //!
288     //! :private
~AnimGroup()289     virtual ~AnimGroup() {}
290 
291     //@}
292 
293     //! Initialize() の実行に必要なメモリサイズを取得します。
294     //!
295     //! :private
296     static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, const anim::ResAnimGroup resAnimGroup, bool useOriginalValue);
297 
298     //! メンバを初期化します。
299     //!
300     //! :private
301     Result Initialize(bool useOriginalValue);
302 
303 private:
304     anim::ResAnimGroup m_ResAnimGroup; //!< アニメーショングループのリソースです。
305     ut::MoveArray<anim::AnimBlendOp*> m_BlendOperations; //!< ブレンドオペレーションです。
306 
307     SceneNode* m_SceneNode; //!< 対象オブジェクトが属するシーンノードです。
308     ut::MoveArray<int> m_TargetObjectIndicies; //!< メンバごとの対象オブジェクトのインデックスです。
309     ut::MoveArray<void*> m_TargetObjects; //!< メンバごとの対象オブジェクトのポインタです。
310     ut::MoveArray<void*> m_TargetPtrs; //!< メンバごとの対象のポインタです。
311     ut::MoveArray<const void*> m_OriginalValues; //!< メンバごとのオリジナル値です。
312 
313     PreEvaluateCallback m_PreEvaluateCallback; //!< 評価前コールバック関数です。
314 
315     bool m_FullBakedAnimEnabled; //!< フルベイクアニメを使用するかを指定します。
316 };
317 
318 } // namespace gfx
319 } // namespace nw
320 
321 #endif // NW_GFX_ANIMGROUP_H_
322