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