fixes for bugs submitted by BGE users, fixes by myself and Mitchell Stokes
[blender.git] / source / gameengine / Ketsji / KX_SceneActuator.cpp
1 /**
2 * Set scene/camera stuff
3 *
4 * $Id$
5 *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30 */
31
32 #include "SCA_IActuator.h"
33 #include "KX_SceneActuator.h"
34 #include <iostream>
35 #include "KX_Scene.h"
36 #include "KX_Camera.h"
37 #include "KX_KetsjiEngine.h"
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 /* ------------------------------------------------------------------------- */
44 /* Native functions                                                          */
45 /* ------------------------------------------------------------------------- */
46
47 KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj, 
48                                                                    int mode,
49                                                                    KX_Scene *scene,
50                                                                    KX_KetsjiEngine* ketsjiEngine,
51                                                                    const STR_String& nextSceneName,
52                                                                    KX_Camera* camera,
53                                                                    PyTypeObject* T)
54                                                                    : SCA_IActuator(gameobj, T)
55 {
56         m_mode = mode;
57         m_scene  = scene;
58         m_KetsjiEngine=ketsjiEngine;
59         m_camera = camera;
60         m_nextSceneName = nextSceneName;
61         if (m_camera)
62                 m_camera->RegisterActuator(this);
63 } /* End of constructor */
64
65
66
67 KX_SceneActuator::~KX_SceneActuator()
68
69         if (m_camera)
70                 m_camera->UnregisterActuator(this);
71 } /* end of destructor */
72
73
74
75 CValue* KX_SceneActuator::GetReplica()
76 {
77         KX_SceneActuator* replica = new KX_SceneActuator(*this);
78         replica->ProcessReplica();
79         return replica;
80 }
81
82 void KX_SceneActuator::ProcessReplica()
83 {
84         if (m_camera)
85                 m_camera->RegisterActuator(this);
86         SCA_IActuator::ProcessReplica();
87 }
88
89 bool KX_SceneActuator::UnlinkObject(SCA_IObject* clientobj)
90 {
91         if (clientobj == (SCA_IObject*)m_camera)
92         {
93                 // this object is being deleted, we cannot continue to track it.
94                 m_camera = NULL;
95                 return true;
96         }
97         return false;
98 }
99
100 void KX_SceneActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
101 {
102         void **h_obj = (*obj_map)[m_camera];
103         if (h_obj) {
104                 if (m_camera)
105                         m_camera->UnregisterActuator(this);
106                 m_camera = (KX_Camera*)(*h_obj);
107                 m_camera->RegisterActuator(this);
108         }
109 }
110
111
112 bool KX_SceneActuator::Update()
113 {
114         // bool result = false; /*unused*/
115         bool bNegativeEvent = IsNegativeEvent();
116         RemoveAllEvents();
117
118         if (bNegativeEvent)
119                 return false; // do nothing on negative events
120
121         switch (m_mode)
122         {
123         case KX_SCENE_RESTART:
124                 {
125                         m_KetsjiEngine->ReplaceScene(m_scene->GetName(),m_scene->GetName());
126                         break;
127                 }
128         case KX_SCENE_SET_CAMERA:
129                 if (m_camera)
130                 {
131                         m_scene->SetActiveCamera(m_camera);
132                 }
133                 else
134                 {
135                         // if no camera is set and the parent object is a camera, use it as the camera
136                         SCA_IObject* parent = GetParent();
137                         if (parent->isA(&KX_Camera::Type))
138                         {
139                                 m_scene->SetActiveCamera((KX_Camera*)parent);
140                         }
141                 }
142                 break;
143         default:
144                 break;
145         }
146         
147         if (!m_nextSceneName.Length())
148                 return false;
149         
150         switch (m_mode)
151         {
152         case KX_SCENE_SET_SCENE:
153                 {
154                         m_KetsjiEngine->ReplaceScene(m_scene->GetName(),m_nextSceneName);
155                         break;
156                 }
157         case KX_SCENE_ADD_FRONT_SCENE:
158                 {
159                         bool overlay=true;
160                         m_KetsjiEngine->ConvertAndAddScene(m_nextSceneName,overlay);
161                         break;
162                 }
163         case KX_SCENE_ADD_BACK_SCENE:
164                 {
165                         bool overlay=false;
166                         m_KetsjiEngine->ConvertAndAddScene(m_nextSceneName,overlay);
167                         break;
168                 }
169         case KX_SCENE_REMOVE_SCENE:
170                 {
171                         m_KetsjiEngine->RemoveScene(m_nextSceneName);
172                         break;
173                 }
174         case KX_SCENE_SUSPEND:
175                 {
176                         m_KetsjiEngine->SuspendScene(m_nextSceneName);
177                         break;
178                 }
179         case KX_SCENE_RESUME:
180                 {
181                         m_KetsjiEngine->ResumeScene(m_nextSceneName);
182                         break;
183                 }
184         default:
185                 ; /* do nothing? this is an internal error !!! */
186         }
187         
188         return false;
189 }
190
191
192
193 /*  returns a camera if the name is valid */
194 KX_Camera* KX_SceneActuator::FindCamera(char *camName)
195 {
196         KX_SceneList* sl = m_KetsjiEngine->CurrentScenes();
197         STR_String name = STR_String(camName);
198         KX_SceneList::iterator it = sl->begin();
199         KX_Camera* cam = NULL;
200
201         while ((it != sl->end()) && (!cam))
202         {
203                 cam = (*it)->FindCamera(name);
204                 it++;
205         }
206
207         return cam;
208 }
209
210
211
212 KX_Scene* KX_SceneActuator::FindScene(char * sceneName)
213 {
214         return m_KetsjiEngine->FindScene(sceneName);
215 }
216
217
218
219
220 /* ------------------------------------------------------------------------- */
221 /* Python functions                                                          */
222 /* ------------------------------------------------------------------------- */
223
224 /* Integration hooks ------------------------------------------------------- */
225 PyTypeObject KX_SceneActuator::Type = {
226 #if (PY_VERSION_HEX >= 0x02060000)
227         PyVarObject_HEAD_INIT(NULL, 0)
228 #else
229         /* python 2.5 and below */
230         PyObject_HEAD_INIT( NULL )  /* required py macro */
231         0,                          /* ob_size */
232 #endif
233                 "KX_SceneActuator",
234                 sizeof(PyObjectPlus_Proxy),
235                 0,
236                 py_base_dealloc,
237                 0,
238                 0,
239                 0,
240                 0,
241                 py_base_repr,
242                 0,0,0,0,0,0,
243                 py_base_getattro,
244                 py_base_setattro,
245                 0,0,0,0,0,0,0,0,0,
246                 Methods
247 };
248
249
250
251 PyParentObject KX_SceneActuator::Parents[] =
252 {
253         &KX_SceneActuator::Type,
254                 &SCA_IActuator::Type,
255                 &SCA_ILogicBrick::Type,
256                 &CValue::Type,
257                 NULL
258 };
259
260
261
262 PyMethodDef KX_SceneActuator::Methods[] =
263 {
264         //Deprecated functions ------>
265         {"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, (PY_METHODCHAR)SetUseRestart_doc},
266         {"setScene",      (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, (PY_METHODCHAR)SetScene_doc},
267         {"setCamera",     (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, (PY_METHODCHAR)SetCamera_doc},
268         {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_NOARGS, (PY_METHODCHAR)GetUseRestart_doc},
269         {"getScene",      (PyCFunction) KX_SceneActuator::sPyGetScene, METH_NOARGS, (PY_METHODCHAR)GetScene_doc},
270         {"getCamera",     (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_NOARGS, (PY_METHODCHAR)GetCamera_doc},
271         //<----- Deprecated
272         {NULL,NULL} //Sentinel
273 };
274
275 PyAttributeDef KX_SceneActuator::Attributes[] = {
276         KX_PYATTRIBUTE_STRING_RW("scene",0,32,true,KX_SceneActuator,m_nextSceneName),
277         KX_PYATTRIBUTE_RW_FUNCTION("camera",KX_SceneActuator,pyattr_get_camera,pyattr_set_camera),
278         KX_PYATTRIBUTE_BOOL_RW("useRestart", KX_SceneActuator, m_restart),
279         KX_PYATTRIBUTE_INT_RW("mode", KX_SCENE_NODEF+1, KX_SCENE_MAX-1, true, KX_SceneActuator, m_mode),
280         { NULL }        //Sentinel
281 };
282
283 PyObject* KX_SceneActuator::py_getattro(PyObject *attr)
284 {
285         py_getattro_up(SCA_IActuator);
286 }
287
288 PyObject* KX_SceneActuator::py_getattro_dict() {
289         py_getattro_dict_up(SCA_IActuator);
290 }
291
292 int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value)
293 {
294         py_setattro_up(SCA_IActuator);
295 }
296
297 PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
298 {
299         KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self);
300         if (!actuator->m_camera)
301                 Py_RETURN_NONE;
302         
303         return actuator->m_camera->GetProxy();
304 }
305
306 int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
307 {
308         KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self);
309         KX_Camera *camOb;
310         
311         if(value==Py_None)
312         {
313                 if (actuator->m_camera)
314                         actuator->m_camera->UnregisterActuator(actuator);
315                 
316                 actuator->m_camera= NULL;
317                 return 0;
318         }
319         
320         if (PyObject_TypeCheck(value, &KX_Camera::Type)) 
321         {
322                 KX_Camera *camOb= static_cast<KX_Camera*>BGE_PROXY_REF(value);
323                 
324                 if(camOb==NULL)
325                 {
326                         PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
327                         return 1;
328                 }
329                 
330                 if (actuator->m_camera)
331                         actuator->m_camera->UnregisterActuator(actuator);
332                 
333                 actuator->m_camera = camOb;
334                 actuator->m_camera->RegisterActuator(actuator);
335                 return 0;
336         }
337
338         if (PyString_Check(value))
339         {
340                 char *camName = PyString_AsString(value);
341
342                 camOb = actuator->FindCamera(camName);
343                 if (camOb) 
344                 {
345                         if (actuator->m_camera)
346                                 actuator->m_camera->UnregisterActuator(actuator);
347                         actuator->m_camera = camOb;
348                         actuator->m_camera->RegisterActuator(actuator);
349                         return 0;
350                 }
351                 PyErr_SetString(PyExc_TypeError, "not a valid camera name");
352                 return 1;
353         }
354         PyErr_SetString(PyExc_TypeError, "expected a string or a camera object reference");
355         return 1;
356 }
357
358
359 /* 2. setUseRestart--------------------------------------------------------- */
360 const char KX_SceneActuator::SetUseRestart_doc[] = 
361 "setUseRestart(flag)\n"
362 "\t- flag: 0 or 1.\n"
363 "\tSet flag to 1 to restart the scene.\n" ;
364 PyObject* KX_SceneActuator::PySetUseRestart(PyObject* args)
365 {
366         ShowDeprecationWarning("setUseRestart()", "the useRestart property");
367         int boolArg;
368         
369         if (!PyArg_ParseTuple(args, "i:setUseRestart", &boolArg))
370         {
371                 return NULL;
372         }
373         
374         m_restart = boolArg != 0;
375         
376         Py_RETURN_NONE;
377 }
378
379
380
381 /* 3. getUseRestart:                                                         */
382 const char KX_SceneActuator::GetUseRestart_doc[] = 
383 "getUseRestart()\n"
384 "\tReturn whether the scene will be restarted.\n" ;
385 PyObject* KX_SceneActuator::PyGetUseRestart()
386 {
387         ShowDeprecationWarning("getUseRestart()", "the useRestart property");
388         return PyInt_FromLong(!(m_restart == 0));
389 }
390
391
392
393 /* 4. set scene------------------------------------------------------------- */
394 const char KX_SceneActuator::SetScene_doc[] = 
395 "setScene(scene)\n"
396 "\t- scene: string\n"
397 "\tSet the name of scene the actuator will switch to.\n" ;
398 PyObject* KX_SceneActuator::PySetScene(PyObject* args)
399 {
400         ShowDeprecationWarning("setScene()", "the scene property");
401         /* one argument: a scene, ignore the rest */
402         char *scene_name;
403
404         if(!PyArg_ParseTuple(args, "s:setScene", &scene_name))
405         {
406                 return NULL;
407         }
408
409         /* Scene switch is done by name. */
410         m_nextSceneName = scene_name;
411
412         Py_RETURN_NONE;
413 }
414
415
416
417 /* 5. getScene:                                                              */
418 const char KX_SceneActuator::GetScene_doc[] = 
419 "getScene()\n"
420 "\tReturn the name of the scene the actuator wants to switch to.\n" ;
421 PyObject* KX_SceneActuator::PyGetScene()
422 {
423         ShowDeprecationWarning("getScene()", "the scene property");
424         return PyString_FromString(m_nextSceneName);
425 }
426
427
428
429 /* 6. set camera------------------------------------------------------------ */
430 const char KX_SceneActuator::SetCamera_doc[] = 
431 "setCamera(camera)\n"
432 "\t- camera: string\n"
433 "\tSet the camera to switch to.\n" ;
434 PyObject* KX_SceneActuator::PySetCamera(PyObject* args)
435 {
436         ShowDeprecationWarning("setCamera()", "the camera property");
437         PyObject *cam;
438         if (PyArg_ParseTuple(args, "O!:setCamera", &KX_Camera::Type, &cam))
439         {
440                 KX_Camera *new_camera;
441                 
442                 new_camera = static_cast<KX_Camera*>BGE_PROXY_REF(cam);
443                 if(new_camera==NULL)
444                 {
445                         PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
446                         return NULL;
447                 }
448                 
449                 if (m_camera)
450                         m_camera->UnregisterActuator(this);
451                 
452                 m_camera= new_camera;
453                 
454                 m_camera->RegisterActuator(this);
455                 Py_RETURN_NONE;
456         }
457         PyErr_Clear();
458
459         /* one argument: a scene, ignore the rest */
460         char *camName;
461         if(!PyArg_ParseTuple(args, "s:setCamera", &camName))
462         {
463                 return NULL;
464         }
465
466         KX_Camera *camOb = FindCamera(camName);
467         if (camOb) 
468         {
469                 if (m_camera)
470                         m_camera->UnregisterActuator(this);
471                 m_camera = camOb;
472                 m_camera->RegisterActuator(this);
473         }
474
475         Py_RETURN_NONE;
476 }
477
478
479
480 /* 7. getCamera:                                                             */
481 const char KX_SceneActuator::GetCamera_doc[] = 
482 "getCamera()\n"
483 "\tReturn the name of the camera to switch to.\n" ;
484 PyObject* KX_SceneActuator::PyGetCamera()
485 {
486         ShowDeprecationWarning("getCamera()", "the camera property");
487         if (m_camera) {
488                 return PyString_FromString(m_camera->GetName());
489         }
490         else {
491                 Py_RETURN_NONE;
492         }
493 }
494 /* eof */