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