1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_SceneNode.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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 
20 #include <nw/gfx/gfx_SceneNode.h>
21 #include <nw/gfx/gfx_ISceneVisitor.h>
22 
23 #include <nw/ut/ut_ResUtil.h>
24 #include <nw/ut/ut_ResDictionary.h>
25 #include <nw/ut/ut_Foreach.h>
26 
27 namespace nw
28 {
29 namespace gfx
30 {
31 
32 NW_UT_RUNTIME_TYPEINFO_DEFINITION(SceneNode, SceneObject);
33 
34 //----------------------------------------
35 SceneNode*
Create(os::IAllocator * allocator)36 SceneNode::DynamicBuilder::Create(
37     os::IAllocator* allocator
38 )
39 {
40     NW_NULL_ASSERT(allocator);
41 
42     void* memory = allocator->Alloc(sizeof(SceneNode));
43     NW_NULL_ASSERT(memory);
44 
45     SceneNode* node = new(memory) SceneNode(
46         allocator, ResSceneNode(), m_Description);
47 
48     Result result = node->Initialize(allocator);
49 
50     NW_ASSERT(result.IsSuccess());
51 
52     return node;
53 
54 }
55 
56 //----------------------------------------
57 SceneNode*
Create(SceneNode * parent,ResSceneObject resource,const SceneNode::Description & description,os::IAllocator * allocator)58 SceneNode::Create(
59     SceneNode* parent,
60     ResSceneObject resource,
61     const SceneNode::Description& description,
62     os::IAllocator* allocator
63 )
64 {
65     NW_NULL_ASSERT(allocator);
66 
67     ResSceneNode resNode = ResStaticCast<ResSceneNode>(resource);
68 
69     void* memory = allocator->Alloc(sizeof(SceneNode));
70     NW_NULL_ASSERT(memory);
71 
72     SceneNode* node = new(memory) SceneNode(
73         allocator, resNode, description);
74 
75     Result result = node->Initialize(allocator);
76 
77     NW_ASSERT(result.IsSuccess());
78 
79     if (parent)
80     {
81         bool isAttached = parent->AttachChild(node);
82         NW_ASSERT(isAttached);
83     }
84     return node;
85 }
86 
87 //----------------------------------------
88 void
Accept(ISceneVisitor * visitor)89 SceneNode::Accept(
90     ISceneVisitor* visitor
91 )
92 {
93     visitor->VisitSceneNode(this);
94     AcceptChildren(visitor);
95 }
96 
97 //----------------------------------------
98 Result
CreateAnimBinding(os::IAllocator * allocator)99 SceneNode::CreateAnimBinding(os::IAllocator* allocator)
100 {
101     Result result = INITIALIZE_RESULT_OK;
102 
103     if (!m_Description.isAnimationEnabled)
104     {
105         return result;
106     }
107 
108     ResSceneObject resSceneObject = GetResSceneObject();
109     ResSceneNode resSceneNode = *reinterpret_cast<ResSceneNode*>(&resSceneObject);
110     if(!resSceneNode.IsValid())
111     {
112         return result;
113     }
114 
115     const int animGroupCount = resSceneNode.GetAnimGroupsCount();
116     if (animGroupCount == 0)
117     {
118         return result;
119     }
120 
121     bool hasAnimGroupMember = false;
122     for (int idx = 0; idx < animGroupCount; ++idx)
123     {
124         if (0 < resSceneNode.GetAnimGroups(idx).GetMemberInfoSetCount())
125         {
126             hasAnimGroupMember = true;
127             break;
128         }
129     }
130     if (!hasAnimGroupMember)
131     {
132         return result;
133     }
134 
135     AnimBinding* animBinding = AnimBinding::Builder()
136         .MaxAnimGroups(animGroupCount)
137         .MaxAnimObjectsPerGroup(m_Description.maxAnimObjectsPerGroup)
138         .Create(allocator);
139 
140     if (animBinding == NULL)
141     {
142         result |= Result::MASK_FAIL_BIT;
143     }
144 
145     NW_ENSURE_AND_RETURN(result);
146 
147     SetAnimBinding(animBinding);
148 
149     return result;
150 }
151 
152 //----------------------------------------
153 Result
CreateChildren(os::IAllocator * allocator)154 SceneNode::CreateChildren(os::IAllocator* allocator)
155 {
156     Result result = INITIALIZE_RESULT_OK;
157 
158     if (m_Description.isFixedSizeMemory)
159     {
160         if (m_Description.maxChildren == 0)
161         {
162             m_Children = SceneNodeChildren(NULL, NULL, 0, NULL);
163         }
164         else
165         {
166             void* memory = allocator->Alloc(
167                 sizeof(SceneNode*) * m_Description.maxChildren, CHILDREN_MEMORY_ALIGNMENT);
168 
169             if (memory == NULL)
170             {
171                 result |= Result::MASK_FAIL_BIT;
172             }
173             NW_ENSURE_AND_RETURN(result);
174 
175             m_Children = SceneNodeChildren(NULL, memory, m_Description.maxChildren, allocator);
176         }
177     }
178     else
179     {
180         m_Children = SceneNodeChildren(NULL, allocator);
181     }
182 
183     return result;
184 }
185 
186 //----------------------------------------
187 Result
CreateCallbacks(os::IAllocator * allocator)188 SceneNode::CreateCallbacks(os::IAllocator* allocator)
189 {
190     Result result = INITIALIZE_RESULT_OK;
191 
192     if (m_Description.isFixedSizeMemory)
193     {
194         if (m_Description.maxCallbacks == 0)
195         {
196             this->m_PreUpdateSignal =
197                 UpdateSignal::CreateInvalidateSignal(allocator);
198         }
199         else
200         {
201             this->m_PreUpdateSignal =
202                 UpdateSignal::CreateFixedSizedSignal(m_Description.maxCallbacks, allocator);
203         }
204     }
205     else
206     {
207         this->m_PreUpdateSignal =
208             UpdateSignal::CreateVariableSizeSignal(allocator);
209     }
210 
211     // 動的配列のメモリ確保に失敗した場合
212     if (m_PreUpdateSignal == NULL)
213     {
214         result |= Result::MASK_FAIL_BIT;
215     }
216 
217     return result;
218 }
219 
220 //----------------------------------------
221 Result
Initialize(os::IAllocator * allocator)222 SceneNode::Initialize(os::IAllocator* allocator)
223 {
224     Result result = INITIALIZE_RESULT_OK;
225 
226     result |= CreateChildren(allocator);
227     NW_ENSURE_AND_RETURN(result);
228 
229     this->m_Children.SetParent(this);
230 
231     result |= CreateCallbacks(allocator);
232     NW_ENSURE_AND_RETURN(result);
233 
234     result |= CreateAnimBinding(allocator);
235     NW_ENSURE_AND_RETURN(result);
236 
237     return result;
238 }
239 
240 } // namespace gfx
241 } // namespace nw
242