Fix BGE bug #7532: TrackTo Actuator does not work correctly if it has a Vertex Parent...
[blender.git] / source / gameengine / SceneGraph / SG_Node.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "SG_Node.h"
30 #include "SG_ParentRelation.h"
31 #include <algorithm>
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 using namespace std;
38
39
40 SG_Node::SG_Node(
41         void* clientobj,
42         void* clientinfo,
43         SG_Callbacks callbacks
44
45 )
46         : SG_Spatial(clientobj,clientinfo,callbacks),
47         m_SGparent(NULL)
48 {
49 }
50
51 SG_Node::SG_Node(
52         const SG_Node & other
53 ) :
54         SG_Spatial(other),
55         m_children(other.m_children),
56         m_SGparent(other.m_SGparent)
57 {
58         // nothing to do
59 }
60
61 SG_Node::~SG_Node()
62 {
63 }
64
65
66 SG_Node* SG_Node::GetSGReplica()
67 {
68         SG_Node* replica = new SG_Node(*this);
69         if (replica == NULL) return NULL;
70
71         ProcessSGReplica(replica);
72         
73         return replica;
74 }
75
76         void 
77 SG_Node::
78 ProcessSGReplica(
79         SG_Node* replica
80 ){
81         // Apply the replication call back function.
82         ActivateReplicationCallback(replica);
83
84         // clear the replica node of it's parent.
85         static_cast<SG_Node*>(replica)->m_SGparent = NULL;
86
87         if (m_children.begin() != m_children.end())
88         {
89                 // if this node has children, the replica has too, so clear and clone children
90                 replica->ClearSGChildren();
91         
92                 NodeList::iterator childit;
93                 for (childit = m_children.begin();childit!=m_children.end();++childit)
94                 {
95                         replica->AddChild((*childit)->GetSGReplica());
96                 }
97         }
98 }
99
100
101         void 
102 SG_Node::
103 Destruct()
104 {
105         // Not entirely sure what Destruct() expects to happen.
106         // I think it probably means just to call the DestructionCallback
107         // in the right order on all the children - rather than free any memory
108         
109         // We'll delete m_parent_relation now anyway.
110         
111         delete(m_parent_relation);
112         m_parent_relation = NULL;               
113
114         if (m_children.begin() != m_children.end())
115         {
116                 NodeList::iterator childit;
117                 for (childit = m_children.begin();childit!=m_children.end();++childit)
118                 {
119                         // call the SG_Node destruct method on each of our children }-)
120                         (*childit)->Destruct();
121                 }
122         }
123
124         ActivateDestructionCallback();
125 }
126
127
128         SG_Node*                        
129 SG_Node::
130 GetSGParent(
131 ) const { 
132         return m_SGparent;
133 }
134
135         void                            
136 SG_Node::
137 SetSGParent(
138         SG_Node* parent
139 ){
140         m_SGparent = parent;
141 }
142
143 const 
144         SG_Node*        
145 SG_Node::
146 GetRootSGParent(
147 ) const {
148         return (m_SGparent ? (const SG_Node*) m_SGparent->GetRootSGParent() : (const SG_Node*) this);
149 }
150
151         bool
152 SG_Node::
153 IsVertexParent()
154 {
155         if (m_parent_relation)
156         {
157                 return m_parent_relation->IsVertexRelation();
158         }
159         return false;
160 }
161
162         void 
163 SG_Node::
164 DisconnectFromParent(
165 ){
166         if (m_SGparent)
167         {
168                 m_SGparent->RemoveChild(this);
169                 m_SGparent = NULL;
170         }
171
172 }
173
174
175
176 void SG_Node::AddChild(SG_Node* child)
177 {
178         m_children.push_back(child);
179         child->SetSGParent(this); // this way ?
180 }
181
182 void SG_Node::RemoveChild(SG_Node* child)
183 {
184         NodeList::iterator childfound = find(m_children.begin(),m_children.end(),child);
185
186         if (childfound != m_children.end())
187         {
188                 m_children.erase(childfound);
189         }
190 }
191
192
193
194 void SG_Node::UpdateWorldData(double time)
195 {
196         //if (!GetSGParent())
197         //      return;
198
199         if (UpdateSpatialData(GetSGParent(),time))
200                 ActivateUpdateTransformCallback();
201
202         // update children's worlddata
203         for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
204         {
205                 (*it)->UpdateWorldData(time);
206         }
207 }
208
209
210 NodeList& SG_Node::GetSGChildren()
211 {
212         return this->m_children;
213 }
214
215
216 const NodeList& SG_Node::GetSGChildren() const
217 {
218         return this->m_children;
219 }
220
221
222 void SG_Node::ClearSGChildren()
223 {
224         m_children.clear();
225 }
226
227
228
229 void SG_Node::SetSimulatedTime(double time,bool recurse)
230 {
231
232         // update the controllers of this node.
233         SetControllerTime(time);
234
235         // update children's simulate time.
236         if (recurse)
237         {
238                 for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it)
239                 {
240                         (*it)->SetSimulatedTime(time,recurse);
241                 }
242         }
243 }
244
245
246