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