svn merge ^/trunk/blender -r43124:43160
[blender.git] / source / gameengine / Converter / BL_ArmatureActuator.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/Converter/BL_ArmatureActuator.cpp
29  *  \ingroup bgeconv
30  */
31
32
33 #include "DNA_action_types.h"
34 #include "DNA_constraint_types.h"
35 #include "DNA_actuator_types.h"
36 #include "BKE_constraint.h"
37 #include "BL_ArmatureActuator.h"
38 #include "BL_ArmatureObject.h"
39 #include "BLI_math.h"
40
41 /**
42  * This class is the conversion of the Pose channel constraint.
43  * It makes a link between the pose constraint and the KX scene.
44  * The main purpose is to give access to the constraint target 
45  * to link it to a game object. 
46  * It also allows to activate/deactivate constraints during the game.
47  * Later it will also be possible to create constraint on the fly
48  */
49
50 BL_ArmatureActuator::BL_ArmatureActuator(SCA_IObject* obj,
51                                                 int type,
52                                                 const char *posechannel,
53                                                 const char *constraintname,
54                                                 KX_GameObject* targetobj,
55                                                 KX_GameObject* subtargetobj,
56                                                 float weight) :
57         SCA_IActuator(obj, KX_ACT_ARMATURE),
58         m_constraint(NULL),
59         m_gametarget(targetobj),
60         m_gamesubtarget(subtargetobj),
61         m_posechannel(posechannel),
62         m_constraintname(constraintname),
63         m_weight(weight),
64         m_type(type)
65 {
66         if (m_gametarget)
67                 m_gametarget->RegisterActuator(this);
68         if (m_gamesubtarget)
69                 m_gamesubtarget->RegisterActuator(this);
70         FindConstraint();
71 }
72
73 BL_ArmatureActuator::~BL_ArmatureActuator()
74 {
75         if (m_gametarget)
76                 m_gametarget->UnregisterActuator(this);
77         if (m_gamesubtarget)
78                 m_gamesubtarget->UnregisterActuator(this);
79 }
80
81 void BL_ArmatureActuator::ProcessReplica()
82 {
83         // the replica is tracking the same object => register it (this may be changed in Relnk())
84         if (m_gametarget)
85                 m_gametarget->RegisterActuator(this);
86         if (m_gamesubtarget)
87                 m_gamesubtarget->UnregisterActuator(this);
88         SCA_IActuator::ProcessReplica();
89 }
90
91 void BL_ArmatureActuator::ReParent(SCA_IObject* parent)
92 {
93         SCA_IActuator::ReParent(parent);
94         // must remap the constraint
95         FindConstraint();
96 }
97
98 bool BL_ArmatureActuator::UnlinkObject(SCA_IObject* clientobj)
99 {
100         bool res=false;
101         if (clientobj == m_gametarget)
102         {
103                 // this object is being deleted, we cannot continue to track it.
104                 m_gametarget = NULL;
105                 res = true;
106         }
107         if (clientobj == m_gamesubtarget)
108         {
109                 // this object is being deleted, we cannot continue to track it.
110                 m_gamesubtarget = NULL;
111                 res = true;
112         }
113         return res;
114 }
115
116 void BL_ArmatureActuator::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map)
117 {
118         void **h_obj = (*obj_map)[m_gametarget];
119         if (h_obj) {
120                 if (m_gametarget)
121                         m_gametarget->UnregisterActuator(this);
122                 m_gametarget = (KX_GameObject*)(*h_obj);
123                 m_gametarget->RegisterActuator(this);
124         }
125         h_obj = (*obj_map)[m_gamesubtarget];
126         if (h_obj) {
127                 if (m_gamesubtarget)
128                         m_gamesubtarget->UnregisterActuator(this);
129                 m_gamesubtarget = (KX_GameObject*)(*h_obj);
130                 m_gamesubtarget->RegisterActuator(this);
131         }
132 }
133
134 void BL_ArmatureActuator::FindConstraint()
135 {
136         m_constraint = NULL;
137
138         if (m_gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
139                 BL_ArmatureObject* armobj = (BL_ArmatureObject*)m_gameobj;
140                 m_constraint = armobj->GetConstraint(m_posechannel, m_constraintname);
141         }
142 }
143
144 bool BL_ArmatureActuator::Update(double curtime, bool frame)
145 {
146         // the only role of this actuator is to ensure that the armature pose will be evaluated
147         bool result = false;    
148         bool bNegativeEvent = IsNegativeEvent();
149         RemoveAllEvents();
150
151         if (!bNegativeEvent) {
152                 BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
153                 switch (m_type) {
154                 case ACT_ARM_RUN:
155                         result = true;
156                         obj->SetActiveAction(NULL, 0, curtime);
157                         break;
158                 case ACT_ARM_ENABLE:
159                         if (m_constraint)
160                                 m_constraint->ClrConstraintFlag(CONSTRAINT_OFF);
161                         break;
162                 case ACT_ARM_DISABLE:
163                         if (m_constraint)
164                                 m_constraint->SetConstraintFlag(CONSTRAINT_OFF);
165                         break;
166                 case ACT_ARM_SETTARGET:
167                         if (m_constraint) {
168                                 m_constraint->SetTarget(m_gametarget);
169                                 m_constraint->SetSubtarget(m_gamesubtarget);
170                         }
171                         break;
172                 case ACT_ARM_SETWEIGHT:
173                         if (m_constraint)
174                                 m_constraint->SetWeight(m_weight);
175                         break;
176                 }
177         }
178         return result;
179 }
180
181 #ifdef WITH_PYTHON
182
183 /* ------------------------------------------------------------------------- */
184 /* Python Integration Hooks                                                                      */
185 /* ------------------------------------------------------------------------- */
186
187 PyTypeObject BL_ArmatureActuator::Type = {
188         PyVarObject_HEAD_INIT(NULL, 0)
189                 "BL_ArmatureActuator",
190                 sizeof(PyObjectPlus_Proxy),
191                 0,
192                 py_base_dealloc,
193                 0,
194                 0,
195                 0,
196                 0,
197                 py_base_repr,
198                 0,0,0,0,0,0,0,0,0,
199                 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
200                 0,0,0,0,0,0,0,
201                 Methods,
202                 0,
203                 0,
204                 &SCA_IActuator::Type,
205                 0,0,0,0,0,0,
206                 py_base_new
207 };
208
209
210 PyMethodDef BL_ArmatureActuator::Methods[] = {
211         {NULL,NULL} //Sentinel
212 };
213
214 PyAttributeDef BL_ArmatureActuator::Attributes[] = {
215         KX_PYATTRIBUTE_RO_FUNCTION("constraint", BL_ArmatureActuator, pyattr_get_constraint),
216         KX_PYATTRIBUTE_RW_FUNCTION("target", BL_ArmatureActuator, pyattr_get_object, pyattr_set_object),
217         KX_PYATTRIBUTE_RW_FUNCTION("subtarget", BL_ArmatureActuator, pyattr_get_object, pyattr_set_object),
218         KX_PYATTRIBUTE_FLOAT_RW("weight",0.0f,1.0f,BL_ArmatureActuator,m_weight),
219         KX_PYATTRIBUTE_INT_RW("type",0,ACT_ARM_MAXTYPE,false,BL_ArmatureActuator,m_type),
220         { NULL }        //Sentinel
221 };
222
223 PyObject* BL_ArmatureActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
224 {
225         BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
226         KX_GameObject *target = (!strcmp(attrdef->m_name, "target")) ? actuator->m_gametarget : actuator->m_gamesubtarget;
227         if (!target)    
228                 Py_RETURN_NONE;
229         else
230                 return target->GetProxy();
231 }
232
233 int BL_ArmatureActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
234 {
235         BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
236         KX_GameObject* &target = (!strcmp(attrdef->m_name, "target")) ? actuator->m_gametarget : actuator->m_gamesubtarget;
237         KX_GameObject *gameobj;
238                 
239         if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: BL_ArmatureActuator"))
240                 return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
241                 
242         if (target != NULL)
243                 target->UnregisterActuator(actuator);   
244
245         target = gameobj;
246                 
247         if (target)
248                 target->RegisterActuator(actuator);
249                 
250         return PY_SET_ATTR_SUCCESS;
251 }
252
253 PyObject* BL_ArmatureActuator::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
254 {
255         BL_ArmatureActuator* actuator = static_cast<BL_ArmatureActuator*>(self);
256         BL_ArmatureConstraint* constraint = actuator->m_constraint;
257         if (!constraint)        
258                 Py_RETURN_NONE;
259         else
260                 return constraint->GetProxy();
261 }
262
263 #endif // WITH_PYTHON
264