4c9c31e49342b3d3686c12a3ff0b5cd6a28419e1
[blender-staging.git] / source / gameengine / SceneGraph / SG_IObject.h
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29 #ifndef __SG_IOBJECT
30 #define __SG_IOBJECT
31
32 #include "SG_QList.h"
33 #include <vector>
34
35 // used for debugging: stage of the game engine main loop at which a Scenegraph modification is done
36 enum SG_Stage
37 {
38         SG_STAGE_UNKNOWN = 0,
39         SG_STAGE_NETWORK,
40         SG_STAGE_NETWORK_UPDATE,
41         SG_STAGE_PHYSICS1,
42         SG_STAGE_PHYSICS1_UPDATE,
43         SG_STAGE_CONTROLLER,
44         SG_STAGE_CONTROLLER_UPDATE,
45         SG_STAGE_ACTUATOR,
46         SG_STAGE_ACTUATOR_UPDATE,
47         SG_STAGE_PHYSICS2,
48         SG_STAGE_PHYSICS2_UPDATE,
49         SG_STAGE_SCENE,
50         SG_STAGE_RENDER,
51         SG_STAGE_CONVERTER,
52         SG_STAGE_CULLING,
53         SG_STAGE_MAX
54 };
55
56 extern SG_Stage gSG_Stage;
57
58 inline void SG_SetActiveStage(SG_Stage stage)
59 {
60         gSG_Stage = stage;
61 }
62         
63
64
65 class SG_Controller;
66 class SG_IObject;
67
68 typedef std::vector<SG_Controller*> SGControllerList;
69
70 typedef void* (*SG_ReplicationNewCallback)(
71         SG_IObject* sgobject,
72         void*   clientobj,
73         void*   clientinfo
74 );
75
76 typedef void* (*SG_DestructionNewCallback)(
77         SG_IObject* sgobject,
78         void*   clientobj,
79         void*   clientinfo
80 );
81
82 typedef void  (*SG_UpdateTransformCallback)(
83         SG_IObject* sgobject,
84         void*   clientobj,
85         void*   clientinfo
86 );
87
88 typedef bool  (*SG_ScheduleUpdateCallback)(
89         SG_IObject* sgobject,
90         void*   clientobj,
91         void*   clientinfo
92 );
93
94 typedef bool  (*SG_RescheduleUpdateCallback)(
95         SG_IObject* sgobject,
96         void*   clientobj,
97         void*   clientinfo
98 );
99
100
101 /**
102  * SG_Callbacks hold 2 call backs to the outside world.
103  * The first is meant to be called when objects are replicated.
104  * And allows the outside world to syncronise external objects
105  * with replicated nodes and their children.
106  * The second is called when a node is detroyed and again
107  * is their for synconisation purposes
108  * These callbacks may both be NULL. 
109  * The efficacy of this approach has not been proved some 
110  * alternatives might be to perform all replication and destruction
111  * externally. 
112  * To define a class interface rather than a simple function
113  * call back so that replication information can be transmitted from 
114  * parent->child. 
115  */
116 struct  SG_Callbacks
117 {
118         SG_Callbacks(
119         ):
120                 m_replicafunc(NULL),
121                 m_destructionfunc(NULL),
122                 m_updatefunc(NULL),
123                 m_schedulefunc(NULL),
124                 m_reschedulefunc(NULL)
125         {
126         };
127                 
128         SG_Callbacks(
129                 SG_ReplicationNewCallback repfunc,
130                 SG_DestructionNewCallback destructfunc,
131                 SG_UpdateTransformCallback updatefunc,
132                 SG_ScheduleUpdateCallback schedulefunc,
133                 SG_RescheduleUpdateCallback reschedulefunc
134         ): 
135                 m_replicafunc(repfunc),
136                 m_destructionfunc(destructfunc),
137                 m_updatefunc(updatefunc),
138                 m_schedulefunc(schedulefunc),
139                 m_reschedulefunc(reschedulefunc)
140         {
141         };
142
143         SG_ReplicationNewCallback       m_replicafunc;
144         SG_DestructionNewCallback       m_destructionfunc;
145         SG_UpdateTransformCallback      m_updatefunc;
146         SG_ScheduleUpdateCallback       m_schedulefunc;
147         SG_RescheduleUpdateCallback m_reschedulefunc;
148 };
149
150 /**
151 base object that can be part of the scenegraph.
152 */
153 class SG_IObject : public SG_QList
154 {
155 private :
156
157         void*   m_SGclientObject;
158         void*   m_SGclientInfo;
159         SG_Callbacks m_callbacks;
160         SGControllerList        m_SGcontrollers;
161
162 public:
163         virtual ~SG_IObject();
164
165
166         /**
167          * Add a pointer to a controller allocated on the heap, to 
168          * this node. This memory for this controller becomes the 
169          * responsibility of this class. It will be deleted when
170          * this object is deleted.
171          */
172         
173                 void                            
174         AddSGController(
175                 SG_Controller* cont
176         );
177
178         /** 
179          * Clear the array of pointers to controllers associated with 
180          * this node. This does not delete the controllers themselves!
181      * This should be used very carefully to avoid memory
182          * leaks.
183          */
184         
185                 void                            
186         RemoveAllControllers(
187         ); 
188
189         /// Needed for replication
190
191         /** 
192          * Return a reference to this node's controller list. 
193          * Whilst we don't wish to expose full control of the container
194          * to the user we do allow them to call non_const methods
195          * on pointers in the container. C++ topic: how to do this in
196          * using STL? 
197          */
198
199         SGControllerList& GetSGControllerList()
200         { 
201                 return m_SGcontrollers; 
202         }
203
204         /**
205          * 
206          */
207         SG_Callbacks& GetCallBackFunctions()
208         {
209                 return m_callbacks;
210         }
211         
212         /**
213          * Get the client object associated with this
214          * node. This interface allows you to associate
215          * arbitray external objects with this node. They are
216          * passed to the callback functions when they are 
217          * activated so you can syncronise these external objects
218          * upon replication and destruction
219          * This may be NULL.
220          */
221
222         inline const void* GetSGClientObject() const    
223         {
224                 return m_SGclientObject;
225         }
226
227         inline void* GetSGClientObject()
228         { 
229                 return m_SGclientObject;
230         }
231
232         /**
233          * Set the client object for this node. This is just a 
234          * pointer to an object allocated that should exist for 
235          * the duration of the lifetime of this object, or untill
236          * this function is called again.
237          */
238         
239         void SetSGClientObject(void* clientObject)
240         {
241                 m_SGclientObject = clientObject;
242         }
243
244
245         /* needed for scene switching */
246         inline const void* GetSGClientInfo() const
247         {
248                 return m_SGclientInfo;
249         }
250         inline void* GetSGClientInfo()
251         {
252                 return m_SGclientInfo;
253         }
254         void SetSGClientInfo(void* clientInfo)
255         {
256                 m_SGclientInfo = clientInfo;
257         }
258
259
260         /** 
261          * Set the current simulation time for this node.
262          * The implementation of this function runs through
263          * the nodes list of controllers and calls their SetSimulatedTime methods
264          */
265  
266         void SetControllerTime(double time);
267         
268         virtual 
269                 void            
270         Destruct(
271         ) = 0;
272
273 protected :
274
275                 bool
276         ActivateReplicationCallback(
277                 SG_IObject *replica
278         )
279         {
280                 if (m_callbacks.m_replicafunc)
281                 {
282                         // Call client provided replication func
283                         if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL)
284                                 return false;
285                 }
286                 return true;
287         }
288
289
290                 void
291         ActivateDestructionCallback(
292         )
293         {
294                 if (m_callbacks.m_destructionfunc)
295                 {
296                         // Call client provided destruction function on this!
297                         m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo);
298                 }
299                 else
300                 {
301                         // no callback but must still destroy the node to avoid memory leak
302                         delete this;
303                 }
304         }
305         
306                 void
307         ActivateUpdateTransformCallback(
308         )
309         {
310                 if (m_callbacks.m_updatefunc)
311                 {
312                         // Call client provided update func.
313                         m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo);
314                 }
315         }
316
317                 bool
318         ActivateScheduleUpdateCallback(
319         )
320         {
321                 // HACK, this check assumes that the scheduled nodes are put on a DList (see SG_Node.h)
322                 // The early check on Empty() allows up to avoid calling the callback function
323                 // when the node is already scheduled for update.
324                 if (Empty() && m_callbacks.m_schedulefunc)
325                 {
326                         // Call client provided update func.
327                         return m_callbacks.m_schedulefunc(this, m_SGclientObject, m_SGclientInfo);
328                 }
329                 return false;
330         }
331
332                 void
333         ActivateRecheduleUpdateCallback(
334         )
335         {
336                 if (m_callbacks.m_reschedulefunc)
337                 {
338                         // Call client provided update func.
339                         m_callbacks.m_reschedulefunc(this, m_SGclientObject, m_SGclientInfo);
340                 }
341         }
342
343
344         SG_IObject(
345                 void* clientobj,
346                 void* clientinfo,
347                 SG_Callbacks& callbacks
348         );
349
350         SG_IObject(
351                 const SG_IObject &other
352         );
353
354
355 #ifdef WITH_CXX_GUARDEDALLOC
356 public:
357         void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:SG_IObject"); }
358         void operator delete( void *mem ) { MEM_freeN(mem); }
359 #endif
360 };
361
362 #endif //__SG_IOBJECT
363