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