add missing files after merging
[blender.git] / source / gameengine / Ketsji / KX_ArmatureSensor.cpp
1 /*
2  * Armature sensor
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file gameengine/Ketsji/KX_ArmatureSensor.cpp
33  *  \ingroup ketsji
34  */
35
36
37 #include "DNA_action_types.h"
38 #include "DNA_constraint_types.h"
39 #include "BKE_constraint.h"
40 #include "DNA_sensor_types.h"
41
42 #include "BL_ArmatureObject.h"
43 #include "KX_ArmatureSensor.h"
44 #include "SCA_EventManager.h"
45 #include "SCA_LogicManager.h"
46
47 KX_ArmatureSensor::KX_ArmatureSensor(class SCA_EventManager* eventmgr,
48                                         SCA_IObject* gameobj,
49                                         const char *posechannel,
50                                         const char *constraintname,
51                                         int type,
52                                         float value)
53         : SCA_ISensor(gameobj,eventmgr),
54         m_constraint(NULL),
55         m_posechannel(posechannel),
56         m_constraintname(constraintname),
57         m_type(type),
58         m_value(value)
59 {
60         FindConstraint();
61 }
62
63 void KX_ArmatureSensor::Init()
64 {
65         m_lastresult = m_invert?true:false;
66         m_result = false;
67         m_reset = true;
68 }
69
70 void KX_ArmatureSensor::FindConstraint()
71 {
72         m_constraint = NULL;
73
74         if (m_gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
75                 BL_ArmatureObject* armobj = (BL_ArmatureObject*)m_gameobj;
76                 // get the persistent pose structure
77                 bPose* pose = armobj->GetOrigPose();
78                 bPoseChannel* pchan;
79                 bConstraint* pcon;
80                 // and locate the constraint
81                 for (pchan = (bPoseChannel*)pose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
82                         if (!strcmp(pchan->name, m_posechannel)) {
83                                 // now locate the constraint
84                                 for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) {
85                                         if (!strcmp(pcon->name, m_constraintname)) {
86                                                 if (pcon->flag & CONSTRAINT_DISABLE)
87                                                         /* this constraint is not valid, can't use it */
88                                                         break;
89                                                 m_constraint = pcon;
90                                                 break;  
91                                         }
92                                 }
93                                 break;
94                         }
95                 }
96         }
97 }
98
99
100 CValue* KX_ArmatureSensor::GetReplica()
101 {
102         KX_ArmatureSensor* replica = new KX_ArmatureSensor(*this);
103         // m_range_expr must be recalculated on replica!
104         replica->ProcessReplica();
105         return replica;
106 }
107
108 void KX_ArmatureSensor::ReParent(SCA_IObject* parent)
109 {
110         SCA_ISensor::ReParent(parent);
111         // must remap the constraint
112         FindConstraint();
113 }
114
115 bool KX_ArmatureSensor::IsPositiveTrigger()
116 {
117         return (m_invert) ? !m_result : m_result;
118 }
119
120
121 KX_ArmatureSensor::~KX_ArmatureSensor()
122 {
123 }
124
125 bool KX_ArmatureSensor::Evaluate()
126 {
127         bool reset = m_reset && m_level;
128
129         m_reset = false;
130         if (!m_constraint)
131                 return false;
132         switch (m_type) {
133         case SENS_ARM_STATE_CHANGED:
134                 m_result = !(m_constraint->flag & CONSTRAINT_OFF);
135                 break;
136         case SENS_ARM_LIN_ERROR_BELOW:
137                 m_result = (m_constraint->lin_error < m_value);
138                 break;
139         case SENS_ARM_LIN_ERROR_ABOVE:
140                 m_result = (m_constraint->lin_error > m_value);
141                 break;
142         case SENS_ARM_ROT_ERROR_BELOW:
143                 m_result = (m_constraint->rot_error < m_value);
144                 break;
145         case SENS_ARM_ROT_ERROR_ABOVE:
146                 m_result = (m_constraint->rot_error > m_value);
147                 break;
148         }
149         if (m_lastresult!=m_result)
150         {
151                 m_lastresult = m_result;
152                 return true;
153         }
154         return (reset) ? true : false;
155 }
156
157 #ifdef WITH_PYTHON
158
159 /* ------------------------------------------------------------------------- */
160 /* Python functions                                                          */
161 /* ------------------------------------------------------------------------- */
162
163 /* Integration hooks ------------------------------------------------------- */
164 PyTypeObject KX_ArmatureSensor::Type = {
165         PyVarObject_HEAD_INIT(NULL, 0)
166         "KX_ArmatureSensor",
167         sizeof(PyObjectPlus_Proxy),
168         0,
169         py_base_dealloc,
170         0,
171         0,
172         0,
173         0,
174         py_base_repr,
175         0,0,0,0,0,0,0,0,0,
176         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
177         0,0,0,0,0,0,0,
178         Methods,
179         0,
180         0,
181         &SCA_ISensor::Type,
182         0,0,0,0,0,0,
183         py_base_new
184 };
185
186 PyMethodDef KX_ArmatureSensor::Methods[] = {
187         {NULL,NULL} //Sentinel
188 };
189
190 PyAttributeDef KX_ArmatureSensor::Attributes[] = {
191         KX_PYATTRIBUTE_RO_FUNCTION("constraint", KX_ArmatureSensor, pyattr_get_constraint),
192         KX_PYATTRIBUTE_FLOAT_RW("value",-FLT_MAX,FLT_MAX,KX_ArmatureSensor,m_value),
193         KX_PYATTRIBUTE_INT_RW("type",0,SENS_ARM_MAXTYPE,false,KX_ArmatureSensor,m_type),
194         { NULL }        //Sentinel
195 };
196
197 PyObject* KX_ArmatureSensor::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
198 {
199         KX_ArmatureSensor* sensor = static_cast<KX_ArmatureSensor*>(self);
200         if (sensor->m_gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) {
201                 BL_ArmatureObject* armobj = (BL_ArmatureObject*)sensor->m_gameobj;
202                 BL_ArmatureConstraint* constraint = armobj->GetConstraint(sensor->m_posechannel, sensor->m_constraintname);
203                 if (constraint) 
204                         return constraint->GetProxy();
205         }
206         Py_RETURN_NONE;
207 }
208
209 #endif // WITH_PYTHON