Fix for [#31813] "bge.types.KX_RadarSensor incorrect attributes" reported by Monster.
[blender.git] / source / gameengine / Ketsji / KX_RadarSensor.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/Ketsji/KX_RadarSensor.cpp
29  *  \ingroup ketsji
30  */
31
32
33 #include "KX_RadarSensor.h"
34 #include "KX_GameObject.h"
35 #include "KX_PyMath.h"
36 #include "PHY_IPhysicsController.h"
37 #include "PHY_IMotionState.h"
38 #include "DNA_sensor_types.h"
39
40 /**
41  *      RadarSensor constructor. Creates a near-sensor derived class, with a cone collision shape.
42  */
43 KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr,
44                 KX_GameObject* gameobj,
45                 PHY_IPhysicsController* physCtrl,
46                         double coneradius,
47                         double coneheight,
48                         int     axis,
49                         double margin,
50                         double resetmargin,
51                         bool bFindMaterial,
52                         const STR_String& touchedpropname)
53
54                         : KX_NearSensor(
55                                 eventmgr,
56                                 gameobj,
57                                 //DT_NewCone(coneradius,coneheight),
58                                 margin,
59                                 resetmargin,
60                                 bFindMaterial,
61                                 touchedpropname,
62                                 physCtrl),
63
64                                 m_coneradius(coneradius),
65                                 m_coneheight(coneheight),
66                                 m_axis(axis)
67 {
68         m_client_info->m_type = KX_ClientObjectInfo::SENSOR;
69         //m_client_info->m_clientobject = gameobj;
70         //m_client_info->m_auxilary_info = NULL;
71         //sumoObj->setClientObject(&m_client_info);
72 }
73                         
74 KX_RadarSensor::~KX_RadarSensor()
75 {
76         
77 }
78
79 CValue* KX_RadarSensor::GetReplica()
80 {
81         KX_RadarSensor* replica = new KX_RadarSensor(*this);
82         replica->ProcessReplica();
83         return replica;
84 }
85
86 /**
87  *      Transforms the collision object. A cone is not correctly centered
88  *      for usage.  */
89 void KX_RadarSensor::SynchronizeTransform()
90 {
91         // Getting the parent location was commented out. Why?
92         MT_Transform trans;
93         trans.setOrigin(((KX_GameObject*)GetParent())->NodeGetWorldPosition());
94         trans.setBasis(((KX_GameObject*)GetParent())->NodeGetWorldOrientation());
95         // What is the default orientation? pointing in the -y direction?
96         // is the geometry correctly converted?
97
98         // a collision cone is oriented
99         // center the cone correctly 
100         // depends on the radar 'axis'
101         switch (m_axis)
102         {
103         case SENS_RADAR_X_AXIS: // +X Axis
104                 {
105                         MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90));
106                         trans.rotate(rotquatje);
107                         trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
108                         break;
109                 };
110         case SENS_RADAR_Y_AXIS: // +Y Axis
111                 {
112                         MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180));
113                         trans.rotate(rotquatje);
114                         trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
115                         break;
116                 };
117         case SENS_RADAR_Z_AXIS: // +Z Axis
118                 {
119                         MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-90));
120                         trans.rotate(rotquatje);
121                         trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
122                         break;
123                 };
124         case SENS_RADAR_NEG_X_AXIS: // -X Axis
125                 {
126                         MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(-90));
127                         trans.rotate(rotquatje);
128                         trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
129                         break;
130                 };
131         case SENS_RADAR_NEG_Y_AXIS: // -Y Axis
132                 {
133                         //MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180));
134                         //trans.rotate(rotquatje);
135                         trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
136                         break;
137                 };
138         case SENS_RADAR_NEG_Z_AXIS: // -Z Axis
139                 {
140                         MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(90));
141                         trans.rotate(rotquatje);
142                         trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0));
143                         break;
144                 };
145         default:
146                 {
147                 }
148         }
149         
150         //Using a temp variable to translate MT_Point3 to float[3].
151         //float[3] works better for the Python interface.
152         MT_Point3 temp = trans.getOrigin();
153         m_cone_origin[0] = temp[0];
154         m_cone_origin[1] = temp[1];
155         m_cone_origin[2] = temp[2];
156
157         temp = trans(MT_Point3(0, -m_coneheight/2.0 ,0));
158         m_cone_target[0] = temp[0];
159         m_cone_target[1] = temp[1];
160         m_cone_target[2] = temp[2];
161
162
163         if (m_physCtrl)
164         {
165                 PHY_IMotionState* motionState = m_physCtrl->GetMotionState();
166                 const MT_Point3& pos = trans.getOrigin();
167                 float ori[12];
168                 trans.getBasis().getValue(ori);
169                 motionState->setWorldPosition(pos[0], pos[1], pos[2]);
170                 motionState->setWorldOrientation(ori);
171                 m_physCtrl->WriteMotionStateToDynamics(true);
172         }
173
174 }
175
176 /* ------------------------------------------------------------------------- */
177 /* Python Functions                                                                                                                      */
178 /* ------------------------------------------------------------------------- */
179
180 #ifdef WITH_PYTHON
181
182 /* ------------------------------------------------------------------------- */
183 /* Python Integration Hooks                                                  */
184 /* ------------------------------------------------------------------------- */
185 PyTypeObject KX_RadarSensor::Type = {
186         PyVarObject_HEAD_INIT(NULL, 0)
187         "KX_RadarSensor",
188         sizeof(PyObjectPlus_Proxy),
189         0,
190         py_base_dealloc,
191         0,
192         0,
193         0,
194         0,
195         py_base_repr,
196         0,0,0,0,0,0,0,0,0,
197         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
198         0,0,0,0,0,0,0,
199         Methods,
200         0,
201         0,
202         &KX_NearSensor::Type,
203         0,0,0,0,0,0,
204         py_base_new
205 };
206
207 PyMethodDef KX_RadarSensor::Methods[] = {
208         {NULL} //Sentinel
209 };
210
211 PyAttributeDef KX_RadarSensor::Attributes[] = {
212         KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneOrigin", KX_RadarSensor, m_cone_origin, 3),
213         KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneTarget", KX_RadarSensor, m_cone_target, 3),
214         KX_PYATTRIBUTE_FLOAT_RO("distance", KX_RadarSensor, m_coneheight),
215         KX_PYATTRIBUTE_RO_FUNCTION("angle", KX_RadarSensor, pyattr_get_angle),
216         KX_PYATTRIBUTE_INT_RW("axis", 0, 5, true, KX_RadarSensor, m_axis),
217         {NULL} //Sentinel
218 };
219
220 PyObject* KX_RadarSensor::pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
221 {
222         KX_RadarSensor* self= static_cast<KX_RadarSensor*>(self_v);
223
224         // The original angle from the gui was converted, so we recalculate the value here to maintain
225         // consistency between Python and the gui
226         return PyFloat_FromDouble(MT_degrees(atan(self->m_coneradius / self->m_coneheight)) * 2);
227         
228 }
229
230 #endif // WITH_PYTHON