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