BGE patch: Relink actuators with target within group when duplicating group; generali...
[blender.git] / source / gameengine / Ketsji / KX_ParentActuator.cpp
1 /**
2  * Set or remove an objects parent
3  *
4  * $Id: SCA_ParentActuator.cpp 13932 2008-03-01 19:05:41Z ben2610 $
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. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL LICENSE BLOCK *****
33  */
34
35 #include "KX_ParentActuator.h"
36 #include "KX_GameObject.h"
37 #include "KX_PythonInit.h"
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 /* ------------------------------------------------------------------------- */
44 /* Native functions                                                          */
45 /* ------------------------------------------------------------------------- */
46
47 KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, 
48                                                                          int mode,
49                                                                          SCA_IObject *ob,
50                                                                          PyTypeObject* T)
51         : SCA_IActuator(gameobj, T),
52           m_mode(mode),
53           m_ob(ob)
54 {
55         if (m_ob)
56                 m_ob->RegisterActuator(this);
57
58
59
60
61 KX_ParentActuator::~KX_ParentActuator()
62 {
63         if (m_ob)
64                 m_ob->UnregisterActuator(this);
65
66
67
68
69 CValue* KX_ParentActuator::GetReplica()
70 {
71         KX_ParentActuator* replica = new KX_ParentActuator(*this);
72         // replication just copy the m_base pointer => common random generator
73         replica->ProcessReplica();
74         CValue::AddDataToReplica(replica);
75
76         return replica;
77 }
78
79 void KX_ParentActuator::ProcessReplica()
80 {
81         if (m_ob)
82                 m_ob->RegisterActuator(this);
83         SCA_IActuator::ProcessReplica();
84 }
85
86
87 bool KX_ParentActuator::UnlinkObject(SCA_IObject* clientobj)
88 {
89         if (clientobj == m_ob)
90         {
91                 // this object is being deleted, we cannot continue to track it.
92                 m_ob = NULL;
93                 return true;
94         }
95         return false;
96 }
97
98 void KX_ParentActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
99 {
100         void **h_obj = (*obj_map)[m_ob];
101         if (h_obj) {
102                 if (m_ob)
103                         m_ob->UnregisterActuator(this);
104                 m_ob = (SCA_IObject*)(*h_obj);
105                 m_ob->RegisterActuator(this);
106         }
107 }
108
109
110
111 bool KX_ParentActuator::Update()
112 {
113         bool bNegativeEvent = IsNegativeEvent();
114         RemoveAllEvents();
115
116         if (bNegativeEvent)
117                 return false; // do nothing on negative events
118
119         KX_GameObject *obj = (KX_GameObject*) GetParent();
120         KX_Scene *scene = PHY_GetActiveScene();
121         switch (m_mode) {
122                 case KX_PARENT_SET:
123                         if (m_ob)
124                                 obj->SetParent(scene, (KX_GameObject*)m_ob);
125                         break;
126                 case KX_PARENT_REMOVE:
127                         obj->RemoveParent(scene);
128                         break;
129         };
130         
131         return false;
132 }
133
134 /* ------------------------------------------------------------------------- */
135 /* Python functions                                                          */
136 /* ------------------------------------------------------------------------- */
137
138 /* Integration hooks ------------------------------------------------------- */
139 PyTypeObject KX_ParentActuator::Type = {
140         PyObject_HEAD_INIT(&PyType_Type)
141         0,
142         "KX_ParentActuator",
143         sizeof(KX_ParentActuator),
144         0,
145         PyDestructor,
146         0,
147         __getattr,
148         __setattr,
149         0, //&MyPyCompare,
150         __repr,
151         0, //&cvalue_as_number,
152         0,
153         0,
154         0,
155         0
156 };
157
158 PyParentObject KX_ParentActuator::Parents[] = {
159         &KX_ParentActuator::Type,
160         &SCA_IActuator::Type,
161         &SCA_ILogicBrick::Type,
162         &CValue::Type,
163         NULL
164 };
165
166 PyMethodDef KX_ParentActuator::Methods[] = {
167         {"setObject",         (PyCFunction) KX_ParentActuator::sPySetObject, METH_VARARGS, SetObject_doc},
168         {"getObject",         (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
169         {NULL,NULL} //Sentinel
170 };
171
172 PyObject* KX_ParentActuator::_getattr(const STR_String& attr) {
173         _getattr_up(SCA_IActuator);
174 }
175
176 /* 1. setObject                                                            */
177 char KX_ParentActuator::SetObject_doc[] = 
178 "setObject(object)\n"
179 "\tSet the object to set as parent.\n"
180 "\tCan be an object name or an object\n";
181 PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObject* kwds) {
182         PyObject* gameobj;
183         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
184         {
185                 if (m_ob != NULL)
186                         m_ob->UnregisterActuator(this);
187                 m_ob = (SCA_IObject*)gameobj;
188                 if (m_ob)
189                         m_ob->RegisterActuator(this);
190                 Py_Return;
191         }
192         PyErr_Clear();
193         
194         char* objectname;
195         if (PyArg_ParseTuple(args, "s", &objectname))
196         {
197                 SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
198                 if(object)
199                 {
200                         if (m_ob != NULL)
201                                 m_ob->UnregisterActuator(this);
202                         m_ob = object;
203                         m_ob->RegisterActuator(this);
204                         Py_Return;
205                 }
206         }
207         
208         return NULL;
209 }
210
211 /* 2. getObject                                                            */
212 char KX_ParentActuator::GetObject_doc[] =
213 "getObject()\n"
214 "\tReturns the object that is set to.\n";
215 PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args, PyObject* kwds) {
216         return PyString_FromString(m_ob->GetName());
217 }
218         
219 /* eof */