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