1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneNode.h
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: 28677 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_GFX_SCENENODE_H_
17 #define NW_GFX_SCENENODE_H_
18 
19 #include <nw/gfx/gfx_SceneObject.h>
20 #include <nw/gfx/gfx_AnimObject.h>
21 #include <nw/gfx/gfx_CalculatedTransform.h>
22 
23 #include <nw/ut/ut_Children.h>
24 #include <nw/ut/ut_Foreach.h>
25 #include <nw/ut/ut_Signal.h>
26 
27 namespace nw
28 {
29 namespace gfx
30 {
31 
32 class ISceneVisitor;
33 class SceneContext;
34 class WorldMatrixUpdater;
35 
36 //---------------------------------------------------------------------------
37 //! @brief        シーンツリーを構成するための節となるクラスです。
38 //!               複数の子を持つことができます。
39 //---------------------------------------------------------------------------
40 class SceneNode : public SceneObject
41 {
42 private:
43     NW_DISALLOW_COPY_AND_ASSIGN(SceneNode);
44     NW_CHILD_DECLARE_PARENT(SceneNode);
45 
46     static const size_t CHILDREN_MEMORY_ALIGNMENT = os::IAllocator::CACHE_LINE_ALIGNMENT;
47 
48 public:
49     NW_UT_RUNTIME_TYPEINFO;
50 
51     //! @brief  トラバースの結果を表すビットフラグの定義です。
52     enum TraversalResults
53     {
54         //! @details :private
55         FLAG_IS_VISIBLE_SHIFT = 0,
56         //! @details :private
57         FLAG_IS_DIRTY_SHIFT                           = 1,
58 
59         //! 描画を行うのであれば、1になります。
60         FLAG_IS_VISIBLE                               = 0x1 << FLAG_IS_VISIBLE_SHIFT,
61 
62         //! ワールドマトリクスの計算処理を行うのであれば、1になります。
63         FLAG_IS_DIRTY                                 = 0x1 << FLAG_IS_DIRTY_SHIFT,
64 
65         //! トラバースの結果の初期値です。
66         FLAG_DEFAULT = FLAG_IS_VISIBLE | FLAG_IS_DIRTY
67     };
68 
69     //! @brief 更新時に呼ばれるコールバック用シグナルの定義です。
70     //!
71     //! @sa PreUpdateSignal
72     typedef ut::Signal2<void, SceneNode*, SceneContext*> UpdateSignal;
73 
74     //! @brief 更新時に呼ばれるコールバック用スロットの定義です。
75     typedef UpdateSignal::SlotType UpdateSlot;
76 
77     //! @brief 設定内容です。
78     struct Description
79     {
80         bool isFixedSizeMemory; //!< 最初に固定サイズのメモリを確保するフラグです。
81         bool isAnimationEnabled; //!< アニメーション可能かのフラグです。
82         s32 maxCallbacks;       //!< 管理できるコールバックの最大数です。
83         s32 maxChildren;        //!< 子の最大数です。
84         s32 maxAnimObjectsPerGroup; //!< AnimBindingが持つ、AnimGroupごとのAnimObjectの最大数です。
85 
86         //! @brief コンストラクタです。
DescriptionDescription87         Description()
88          : isFixedSizeMemory(true),
89            isAnimationEnabled(true),
90            maxCallbacks(DEFAULT_MAX_CALLBACKS),
91            maxChildren(DEFAULT_MAX_CHILDREN),
92            maxAnimObjectsPerGroup(DEFAULT_MAX_ANIMOBJECTS)
93         {}
94     };
95 
96     //----------------------------------------
97     //! @name 作成/破棄
98     //@{
99 
100     //! @brief シーンノードを動的に構築するためのクラスです。
101     //!
102     //! IsFixedSizeMemory の初期値は true です。false に変更すると、各種最大数の設定は一部を除いて無視されます。
103     class DynamicBuilder
104     {
105     public:
106         //! コンストラクタです。
DynamicBuilder()107         DynamicBuilder() {}
108         //! デストラクタです。
~DynamicBuilder()109         ~DynamicBuilder() {}
110 
111         //! @brief 生成時以外にもメモリを確保するかどうかのフラグを設定します。
112         //!
113         //!        true を指定すると、生成時のみ固定サイズのメモリ確保を行います。
114         //!
115         //!        false を指定すると、生成時以外にも必要に応じて動的にメモリ確保が行われます。
IsFixedSizeMemory(bool isFixedSizeMemory)116         DynamicBuilder& IsFixedSizeMemory(bool isFixedSizeMemory)
117         {
118             m_Description.isFixedSizeMemory = isFixedSizeMemory;
119             return *this;
120         }
121 
122         //! 子の最大数を設定します。
MaxChildren(int maxChildren)123         DynamicBuilder& MaxChildren(int maxChildren)
124         {
125             m_Description.maxChildren = maxChildren;
126             return *this;
127         }
128 
129         //! 管理できるコールバックの最大数を設定します。
MaxCallbacks(int maxCallbacks)130         DynamicBuilder& MaxCallbacks(int maxCallbacks)
131         {
132             m_Description.maxCallbacks = maxCallbacks;
133             return *this;
134         }
135 
136         //! @brief AnimBindingが持てるAnimGroupごとのAnimObjectの最大数を設定します。
137         //!
138         //!        IsFixedSizeMemory に false を指定しても、この最大数は有効です。
MaxAnimObjectsPerGroup(s32 maxAnimObjects)139         DynamicBuilder& MaxAnimObjectsPerGroup(s32 maxAnimObjects)
140         {
141             m_Description.maxAnimObjectsPerGroup = maxAnimObjects;
142             return *this;
143         }
144 
145         //! @brief アニメーション可能かを設定します。
146         //!
147         //!        false を指定すると AnimBinding の生成を行いません。
148         //!        そのためアニメーションのバインドができなくなりますが、
149         //!        アニメーション更新の処理が行われなくなるため、
150         //!        シーンアップデートのパフォーマンスが向上します。
IsAnimationEnabled(bool isAnimationEnabled)151         DynamicBuilder& IsAnimationEnabled(bool isAnimationEnabled)
152         {
153             m_Description.isAnimationEnabled = isAnimationEnabled;
154             return *this;
155         }
156 
157         //! @brief        シーンノードを生成します。
158         //!
159         //! @param[in]    allocator アロケータです。
160         //!
161         //! @return       生成したシーンノードを返します。
162         //!
163         SceneNode* Create(os::IAllocator* allocator);
164 
165         //! @brief 生成時に必要なメモリサイズを取得します。
166         //!
167         //! メモリサイズは Builder の設定によって変化します。
168         //! すべての設定が終わった後にこの関数を呼び出してください。
169         //!
170         //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
171         size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
172         {
173             os::MemorySizeCalculator size(alignment);
174 
175             size += sizeof(SceneNode);
176             GetMemorySizeForInitialize(&size, ResSceneNode(), m_Description);
177 
178             return size.GetSizeWithPadding(alignment);
179         }
180 
181     private:
182         SceneNode::Description m_Description;
183     };
184 
185     //! @brief        シーンノードを生成します。
186     //!
187     //! @param[in]    parent 親のノードです。
188     //! @param[in]    resource リソースです。
189     //! @param[in]    description 設定内容です。
190     //! @param[in]    allocator アロケータです。
191     //!
192     //! @return       生成されたシーンノードです。
193     //!
194     static SceneNode* Create(
195         SceneNode* parent,
196         ResSceneObject resource,
197         const SceneNode::Description& description,
198         os::IAllocator* allocator);
199 
200     //! @brief        生成時に必要なメモリサイズを取得します。
201     //!
202     //! @param[in]    resSceneNode リソースです。
203     //! @param[in]    description 設定内容です。
204     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
205     static size_t GetMemorySize(
206         ResSceneNode resSceneNode,
207         Description description,
208         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
209     {
210         os::MemorySizeCalculator size(alignment);
211 
212         GetMemorySizeInternal(&size, resSceneNode, description);
213 
214         return size.GetSizeWithPadding(alignment);
215     }
216 
217     //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResSceneNode resSceneNode,Description description)218     static void GetMemorySizeInternal(
219         os::MemorySizeCalculator* pSize,
220         ResSceneNode resSceneNode,
221         Description description)
222     {
223         os::MemorySizeCalculator& size = *pSize;
224 
225         size += sizeof(SceneNode);
226         GetMemorySizeForInitialize(pSize, resSceneNode, description);
227     }
228 
229     //! @brief 自ノードを含むブランチ以下のノードを全て破棄します。
DestroyBranch()230     void DestroyBranch()
231     {
232         SceneNodeChildren::iterator end = this->m_Children.end();
233         for (SceneNodeChildren::iterator child = this->m_Children.begin(); child != end; ++child)
234         {
235             if (*child)
236             {
237                 (*child)->SetParent(NULL);
238                 (*child)->DestroyBranch();
239                 *child = NULL;
240             }
241         }
242         this->Destroy();
243     }
244 
245     //! @brief        生成時に必要なデバイスメモリサイズを取得します。
246     //!
247     //! @param[in]    resource リソースです。
248     //! @param[in]    description 設定内容です。
249     //!
250     //! @details :private
251     static size_t GetDeviceMemorySize(
252         ResSceneObject,
253         Description,
254         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
255     {
256         NW_UNUSED_VARIABLE(alignment);
257 
258         return 0;
259     }
260 
261     //! @details :private
GetDeviceMemorySizeInternal(os::MemorySizeCalculator *,ResSceneObject,Description)262     static void GetDeviceMemorySizeInternal(
263         os::MemorySizeCalculator*,
264         ResSceneObject,
265         Description)
266     {
267     }
268 
269     //@}
270 
271     //----------------------------------------
272     //! @name リソース
273     //@{
274 
275     //! @brief シーンノードのリソースを取得します。
GetResSceneNode()276     ResSceneNode GetResSceneNode()
277     {
278         return ResStaticCast<ResSceneNode>( this->GetResSceneObject() );
279     }
280 
281     //! @brief シーンノードのリソースを取得します。
GetResSceneNode()282     const ResSceneNode GetResSceneNode() const
283     {
284         return ResStaticCast<ResSceneNode>( this->GetResSceneObject() );
285     }
286 
287     //@}
288 
289     //----------------------------------------
290     //! @name トランスフォーム
291     //@{
292 
293     //! @brief        変換情報に関する更新を行います。
294     //!
295     //! @param[in]    worldMatrixUpdater ワールドマトリクス更新クラスです。
296     //! @param[in]    sceneContext シーンコンテキストです。
297     //!
UpdateTransform(WorldMatrixUpdater * worldMatrixUpdater,SceneContext * sceneContext)298     virtual void UpdateTransform(
299         WorldMatrixUpdater* worldMatrixUpdater,
300         SceneContext* sceneContext)
301     {
302         NW_UNUSED_VARIABLE(worldMatrixUpdater);
303         NW_UNUSED_VARIABLE(sceneContext);
304     }
305 
306     //@}
307 
308     //----------------------------------------
309     //! @name シーンツリー
310     //@{
311 
312     //! @brief        子を取り付けます。
313     //!
314     //! @param[in] child   子となるシーンノードです。
315     //!
316     //! @return       追加できなかった場合は、false が返ります。
317     //!
AttachChild(SceneNode * child)318     bool AttachChild(SceneNode* child)
319     {
320         if (IsCircularReference(child))
321         {
322             return false;
323         }
324 
325         return m_Children.Attach(child);
326     }
327 
328     //! @brief        子を取り外します。
329     //!
330     //! @param[in] child   子となるシーンノードです。
331     //!
DetachChild(SceneNode * child)332     void DetachChild(SceneNode* child)
333     {
334         NW_NULL_ASSERT(child);
335         NW_ASSERT(child->GetParent() == this);
336 
337         m_Children.Detach(child);
338     }
339 
340     //! @brief 子の先頭を取得します。
GetChildBegin()341     SceneNodeChildren::iterator GetChildBegin() { return m_Children.begin(); }
342 
343     //! @brief 子の先頭を取得します。
GetChildBegin()344     SceneNodeChildren::const_iterator GetChildBegin() const { return m_Children.begin(); }
345 
346     //! @brief 子の末尾を取得します。
GetChildEnd()347     SceneNodeChildren::iterator GetChildEnd() { return m_Children.end(); }
348 
349     //! @brief 子の末尾を取得します。
GetChildEnd()350     SceneNodeChildren::const_iterator GetChildEnd() const { return m_Children.end(); }
351 
352     //! @brief 全ての子を取り外します。
DetachAllChildren()353     void DetachAllChildren() { m_Children.clear(); }
354 
355     //! @brief        ビジターを受け付けます。
356     //!
357     //! @param[in]    visitor ビジターです。
358     //!
359     virtual void Accept(ISceneVisitor* visitor);
360 
361     //! @brief 親ノードをたどりワールドマトリクスを取得します。
TrackbackWorldMatrix()362     virtual const math::MTX34& TrackbackWorldMatrix() const
363     {
364         const SceneNode* parent = this->GetParent();
365         if (parent == NULL)
366         {
367             return nw::math::MTX34::Identity();
368         }
369 
370         return parent->TrackbackWorldMatrix();
371     }
372 
373     //! @brief 親ノードをたどりワールドトランスフォームを取得します。
TrackbackWorldTransform()374     virtual const CalculatedTransform& TrackbackWorldTransform() const
375     {
376         const SceneNode* parent = this->GetParent();
377         if (parent == NULL)
378         {
379             return CalculatedTransform::Identity();
380         }
381 
382         return parent->TrackbackWorldTransform();
383     }
384 
385     //! @brief 親ノードをたどりローカルトランスフォームを取得します。
TrackbackLocalTransform()386     virtual const CalculatedTransform& TrackbackLocalTransform() const
387     {
388         const SceneNode* parent = this->GetParent();
389         if (parent == NULL)
390         {
391             return CalculatedTransform::Identity();
392         }
393 
394         return parent->TrackbackLocalTransform();
395     }
396 
397     //@}
398 
399     //----------------------------------------
400     //! @name コールバック
401     //@{
402 
403     //! @brief シーンノード更新前のシグナルを取得します。
404     //!
405     //! TransformNode クラスまたはそのサブクラスでは、ノードのワールドマトリクス計算前の
406     //! シグナルとなります。
407     //!
408     //! @sa UpdateSignal
PreUpdateSignal()409     UpdateSignal& PreUpdateSignal() { return *m_PreUpdateSignal; }
410 
411     //! @brief シーンノード更新前のシグナルを取得します。
412     //!
413     //! TransformNode クラスまたはそのサブクラスでは、ノードのワールドマトリクス計算前の
414     //! シグナルとなります。
415     //!
416     //! @sa UpdateSignal
PreUpdateSignal()417     const UpdateSignal& PreUpdateSignal() const { return *m_PreUpdateSignal; }
418 
419     //@}
420 
421     //----------------------------------------
422     //! @name アニメーション
423     //@{
424 
425     //! @brief アニメーションバインディングを取得します。
GetAnimBinding()426     const AnimBinding* GetAnimBinding() const { return m_AnimBinding.Get(); }
427 
428     //! @brief アニメーションバインディングを取得します。
GetAnimBinding()429     AnimBinding* GetAnimBinding() { return m_AnimBinding.Get(); }
430 
431     //! @brief アニメーションバインディングを設定します。
SetAnimBinding(AnimBinding * animBinding)432     void SetAnimBinding(AnimBinding* animBinding) { m_AnimBinding = GfxPtr<AnimBinding>(animBinding); }
433 
434     //! @brief 設定されたすべてのアニメーションオブジェクトのフレームを更新します。
UpdateFrame()435     void UpdateFrame()
436     {
437         AnimBinding* animBinding = GetAnimBinding();
438         if (animBinding != NULL)
439         {
440             animBinding->UpdateFrame();
441         }
442     }
443 
444     //@}
445 
446     //----------------------------------------
447     //! @name トラバース
448     //@{
449 
450     //! @brief トラバースの結果を取得します。
GetTraversalResults()451     bit32 GetTraversalResults() const
452     {
453         return this->m_TraversalResults;
454     }
455 
456     //! @brief トラバースの結果を設定します。
SetTraversalResults(bit32 results)457     void SetTraversalResults(bit32 results)
458     {
459         this->m_TraversalResults = results;
460     }
461 
462     //! @brief 任意のトラバースの結果が有効であるか取得します。
IsEnabledResults(bit32 results)463     bool IsEnabledResults(bit32 results) const
464     {
465         return ut::CheckFlag(m_TraversalResults, results);
466     }
467 
468     //! @brief トラバースの結果を有効にします。
EnableTraversalResults(bit32 results)469     void EnableTraversalResults(bit32 results)
470     {
471         this->m_TraversalResults = ut::EnableFlag(this->m_TraversalResults, results);
472     }
473 
474     //! @brief トラバースの結果を無効にします。
DisableTraversalResults(bit32 results)475     void DisableTraversalResults(bit32 results)
476     {
477         this->m_TraversalResults = ut::DisableFlag(this->m_TraversalResults, results);
478     }
479 
480     //! @brief ノードからトラバースの結果をコピーします。
ResetTraversalResults()481     void ResetTraversalResults()
482     {
483         this->m_TraversalResults = FLAG_DEFAULT;
484     }
485 
486     //! @brief ノードからトラバースの結果をコピーします。
CopyTraversalResults(const SceneNode * node)487     void CopyTraversalResults(const SceneNode* node)
488     {
489         if (node != NULL)
490         {
491             this->m_TraversalResults = node->GetTraversalResults();
492         }
493     }
494 
495     //! @brief 親ノードからの変換情報を継承します。
496     NW_INLINE virtual void InheritTraversalResults();
497 
498     //! @brief ノード以下で描画を行うためのフラグを設定します。
499     //!
500     //! falseにするとノード以下の描画が無効になります。
501     //!
502     //! @param[in] isBranchVisible ノード以下で描画を行うためのフラグです。
503     //!
SetBranchVisible(bool isBranchVisible)504     void SetBranchVisible(bool isBranchVisible)
505     {
506         m_BranchVisible = isBranchVisible;
507     }
508 
509     //! @brief ノード以下で描画を行うためのフラグを取得します。
510     //!
511     //! @return ノード以下で描画を行うためのフラグです。
512     //!
IsBranchVisible()513     bool IsBranchVisible() const
514     {
515         return m_BranchVisible;
516     }
517     //@}
518 
519     //! @brief   Initialize() の実行に必要なメモリサイズを取得します。
520     //!
521     //! @details :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,ResSceneNode resSceneNode,Description description)522     static void GetMemorySizeForInitialize(
523         os::MemorySizeCalculator* pSize,
524         ResSceneNode resSceneNode,
525         Description description)
526     {
527         NW_ASSERT(description.isFixedSizeMemory);
528 
529         // SceneNode::Initialize
530         os::MemorySizeCalculator& size = *pSize;
531 
532         // SceneNode::CreateChildren
533         size.Add(sizeof(SceneNode*) * description.maxChildren, CHILDREN_MEMORY_ALIGNMENT);
534 
535         // SceneNode::CreateCallbacks
536         if (description.maxCallbacks == 0)
537         {
538             UpdateSignal::GetMemorySizeForInvalidateSignalInternal(pSize);
539         }
540         else
541         {
542             UpdateSignal::GetMemorySizeForFixedSizedSignalInternal(pSize, description.maxCallbacks);
543         }
544 
545         // SceneNode::CreateAnimBinding
546         if (description.isAnimationEnabled && resSceneNode.IsValid())
547         {
548             const int animGroupCount = resSceneNode.GetAnimGroupsCount();
549             if (animGroupCount)
550             {
551                 AnimBinding::Builder()
552                     .MaxAnimGroups(animGroupCount)
553                     .MaxAnimObjectsPerGroup(description.maxAnimObjectsPerGroup)
554                     .GetMemorySizeInternal(pSize);
555             }
556         }
557     }
558 
559 protected:
560     //----------------------------------------
561     //! @name コンストラクタ/デストラクタ
562     //@{
563 
564     //! @brief コンストラクタです。
SceneNode(os::IAllocator * allocator,ResSceneNode resObj,const SceneNode::Description & description)565     SceneNode(
566         os::IAllocator* allocator,
567         ResSceneNode resObj,
568         const SceneNode::Description& description)
569     : SceneObject(allocator, resObj),
570       m_BranchVisible(true),
571       m_PreUpdateSignal(NULL),
572       m_TraversalResults(FLAG_DEFAULT),
573       m_Description(description)
574     {
575         this->SetParent(NULL);
576         if (resObj.IsValid())
577         {
578             m_BranchVisible = resObj.IsBranchVisible();
579         }
580     }
581 
582     //! @brief デストラクタです。
~SceneNode()583     virtual ~SceneNode()
584     {
585         SceneNode* parent = this->GetParent();
586         if (parent)
587         {
588             parent->DetachChild(this);
589         }
590 
591         SafeDestroy(m_PreUpdateSignal);
592     }
593 
594     //@}
595 
596     //! @brief        循環参照ならば true を返します。
597     //!
598     //! @param[in]    child 対象となる子です。
599     //!
IsCircularReference(const SceneNode * child)600     bool IsCircularReference(const SceneNode* child) const
601     {
602         const SceneNode* parent = this->GetParent();
603         if (parent == 0)
604         {
605             return false;
606         }
607 
608         if (parent != child)
609         {
610             return parent->IsCircularReference(child);
611         }
612 
613         return true;
614     }
615 
616     //! @brief        全ての子にビジターを受け付けさせます。
617     //!
618     //! @param[in]    visitor ビジターです。
619     //!
AcceptChildren(ISceneVisitor * visitor)620     void AcceptChildren(ISceneVisitor* visitor)
621     {
622         NW_FOREACH(SceneNode* child, m_Children)
623         {
624             child->Accept(visitor);
625         }
626     }
627 
628     //! @brief メンバのメモリ確保と初期化を行います。
629     //!
630     //! コンストラクタではメモリの確保を行わず、こちらでメモリ確保を行います。
631     //! メモリ確保に失敗した場合は Result でエラーコードが返りますので、Destroy を呼び出してクラスを削除します。
632     virtual Result Initialize(os::IAllocator* allocator);
633 
634     //! @brief 子のノードです。
635     SceneNodeChildren m_Children;
636     //! @brief アニメーションとの関連付けです。
637     GfxPtr<AnimBinding> m_AnimBinding;
638     //! @brief ブランチ以下のビジビリティです。
639     bool m_BranchVisible;
640 
641 private:
642     //! 子を作成します。
643     Result CreateChildren(os::IAllocator* allocator);
644 
645     //! コールバック関数を生成します。
646     Result CreateCallbacks(os::IAllocator* allocator);
647 
648     //! アニメーションバインディングを生成します。
649     Result CreateAnimBinding(os::IAllocator* allocator);
650 
651     //!< 標準のAnimBindingの持つGroupに対するAnimObjectsの最大数です。
652     static const int DEFAULT_MAX_ANIMOBJECTS = 1;
653 
654     UpdateSignal* m_PreUpdateSignal;
655     bit32 m_TraversalResults;
656     Description m_Description;
657 };
658 
659 //---------------------------------------------------------------------------
660 //! @brief        ブランチ以下を削除後に0を設定するためのインライン関数です。
661 //!
662 //! @tparam       TNode 削除するオブジェクトの型です。
663 //!
664 //! @param[in]    node 削除するオブジェクトです。
665 //---------------------------------------------------------------------------
666 template<typename TNode>
667 NW_INLINE void
SafeDestroyBranch(TNode * & node)668 SafeDestroyBranch(
669     TNode*& node
670 )
671 {
672     if (node == NULL) { return; }
673     node->DestroyBranch();
674     node = NULL;
675 }
676 
677 //---------------------------------------------------------------------------
678 //! @brief        SafeDestroyBranch でオブジェクトを破棄するための関数オブジェクトです。
679 //!
680 //! @tparam       TObject 削除するオブジェクトの型です。
681 //---------------------------------------------------------------------------
682 template<typename TNode>
683 struct SafeBranchDestroyer : public std::unary_function<TNode&, void>
684 {
685     //! @brief オブジェクトを破棄します。
operatorSafeBranchDestroyer686     void operator()(TNode& node) const
687     {
688         SafeDestroyBranch(node);
689     }
690 };
691 
692 //---------------------------------------------------------------------------
693 //! @brief        SafeBranchDestroy でコンテナ要素の全てのオブジェクトを破棄するための関数です。
694 //!
695 //! @tparam       TArray 削除するオブジェクトの型です。
696 //!
697 //! @param[in]    nodes 削除するオブジェクトの配列です。
698 //---------------------------------------------------------------------------
699 template<typename TArray>
700 NW_INLINE void
SafeDestroyBranchAll(TArray & nodes)701 SafeDestroyBranchAll(
702     TArray& nodes
703 )
704 {
705     std::for_each(nodes.begin(), nodes.end(), SafeBranchDestroyer<typename TArray::value_type>());
706     nodes.clear();
707 }
708 
709 //----------------------------------------
710 NW_INLINE void
InheritTraversalResults()711 SceneNode::InheritTraversalResults()
712 {
713     bit32 results = this->GetTraversalResults();
714     SceneNode* parent = this->GetParent();
715 
716     bool isVisible = this->IsBranchVisible();
717 
718     if (parent != NULL && !(parent->IsEnabledResults(SceneNode::FLAG_IS_VISIBLE)))
719     {
720         isVisible = false;
721     }
722 
723     if (isVisible)
724     {
725         results = ut::EnableFlag(results, SceneNode::FLAG_IS_VISIBLE);
726     }
727     else
728     {
729         results = ut::DisableFlag(results, SceneNode::FLAG_IS_VISIBLE);
730     }
731 
732     this->SetTraversalResults(results);
733 }
734 
735 
736 } // namespace gfx
737 } // namespace nw
738 
739 #endif // NW_GFX_SCENENODE_H_
740