patch 8235 8218 8211 added: various gameengine improvements, fixed windows project...
[blender.git] / source / gameengine / Ketsji / KXNetwork / KX_NetworkMessageSensor.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Ketsji Logic Extenstion: Network Message Sensor generic implementation
32  */
33
34 #include "KX_NetworkMessageSensor.h"
35 #include "KX_NetworkEventManager.h"
36 #include "NG_NetworkMessage.h"
37 #include "NG_NetworkScene.h"
38 #include "NG_NetworkObject.h"
39 #include "SCA_IObject.h"        
40 #include "InputParser.h"
41 #include "ListValue.h"
42 #include "StringValue.h"
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47
48 #ifdef NAN_NET_DEBUG
49   #include <iostream>
50 #endif
51
52 KX_NetworkMessageSensor::KX_NetworkMessageSensor(
53         class KX_NetworkEventManager* eventmgr, // our eventmanager
54         class NG_NetworkScene *NetworkScene,    // our scene
55         SCA_IObject* gameobj,                                   // the sensor controlling object
56         const STR_String &subject,
57         PyTypeObject* T
58 ) :
59     SCA_ISensor(gameobj,eventmgr,T),
60     m_Networkeventmgr(eventmgr),
61     m_NetworkScene(NetworkScene),
62     m_subject(subject),
63     m_frame_message_count (0),
64     m_IsUp(false),
65     m_BodyList(NULL),
66     m_SubjectList(NULL)
67 {
68 }
69
70 KX_NetworkMessageSensor::~KX_NetworkMessageSensor()
71 {
72 }
73
74 CValue* KX_NetworkMessageSensor::GetReplica() {
75         // This is the standard sensor implementation of GetReplica
76         // There may be more network message sensor specific stuff to do here.
77         CValue* replica = new KX_NetworkMessageSensor(*this);
78
79         if (replica == NULL) return NULL;
80
81         // this will copy properties and so on...
82         CValue::AddDataToReplica(replica);
83
84         return replica;
85 }
86
87 // Return true only for flank (UP and DOWN)
88 bool KX_NetworkMessageSensor::Evaluate(CValue* event)
89 {
90         bool result = false;
91         bool WasUp = m_IsUp;
92
93         m_IsUp = false;
94
95         if (m_BodyList) {
96                 m_BodyList->Release();
97                 m_BodyList = NULL;
98         }
99
100         if (m_SubjectList) {
101                 m_SubjectList->Release();
102                 m_SubjectList = NULL;
103         }
104
105         STR_String toname=GetParent()->GetName();
106         STR_String subject = this->m_subject;
107
108         vector<NG_NetworkMessage*> messages =
109                 m_NetworkScene->FindMessages(toname,"",subject,true);
110
111         m_frame_message_count = messages.size();
112
113         if (!messages.empty()) {
114 #ifdef NAN_NET_DEBUG
115                 printf("KX_NetworkMessageSensor found one or more messages\n");
116 #endif
117                 m_IsUp = true;
118                 m_BodyList = new CListValue();
119                 m_SubjectList = new CListValue();
120         }
121
122         vector<NG_NetworkMessage*>::iterator mesit;
123         for (mesit=messages.begin();mesit!=messages.end();mesit++)
124         {
125                 // save the body
126                 STR_String body = (*mesit)->GetMessageText();
127                 // save the subject
128                 STR_String messub = (*mesit)->GetSubject();
129 #ifdef NAN_NET_DEBUG
130                 if (body) {
131                         cout << "body [" << body << "]\n";
132                 }
133 #endif
134                 m_BodyList->Add(new CStringValue(body,"body"));
135                 // Store Subject
136                 m_SubjectList->Add(new CStringValue(messub,"subject"));
137
138                 // free the message
139                 (*mesit)->Release();
140         }
141         messages.clear();
142
143         result = (WasUp != m_IsUp);
144
145         // Return always true if a message was received otherwise we can loose messages
146         if (m_IsUp)
147                 return true;
148         // Is it usefull to return also true when the first frame without a message?? 
149         // This will cause a fast on/off cycle that seems useless!
150         return result;
151 }
152
153 // return true for being up (no flank needed)
154 bool KX_NetworkMessageSensor::IsPositiveTrigger()
155 {
156 //      printf("KX_NetworkMessageSensor IsPositiveTrigger\n");
157         //attempt to fix [ #3809 ] IPO Actuator does not work with some Sensors
158         //a better solution is to properly introduce separate Edge and Level triggering concept
159
160         return m_IsUp;
161 }
162
163 /* --------------------------------------------------------------------- */
164 /* Python interface ---------------------------------------------------- */
165 /* --------------------------------------------------------------------- */
166
167 /* Integration hooks --------------------------------------------------- */
168 PyTypeObject KX_NetworkMessageSensor::Type = {
169         PyObject_HEAD_INIT(&PyType_Type)
170         0,
171         "KX_NetworkMessageSensor",
172         sizeof(KX_NetworkMessageSensor),
173         0,
174         PyDestructor,
175         0,
176         __getattr,
177         __setattr,
178         0, //&MyPyCompare,
179         __repr,
180         0, //&cvalue_as_number,
181         0,
182         0,
183         0,
184         0
185 };
186
187 PyParentObject KX_NetworkMessageSensor::Parents[] = {
188         &KX_NetworkMessageSensor::Type,
189         &SCA_ISensor::Type,
190         &SCA_ILogicBrick::Type,
191         &CValue::Type,
192         NULL
193 };
194
195 PyMethodDef KX_NetworkMessageSensor::Methods[] = {
196         {"setSubjectFilterText", (PyCFunction)
197                 KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS,
198                 SetSubjectFilterText_doc},
199         {"getFrameMessageCount", (PyCFunction)
200                 KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS,
201                 GetFrameMessageCount_doc},
202         {"getBodies", (PyCFunction)
203                 KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS,
204                 GetBodies_doc},
205         {"getSubject", (PyCFunction)
206                 KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS,
207                 GetSubject_doc},
208         {"getSubjects", (PyCFunction)
209                 KX_NetworkMessageSensor::sPyGetSubjects, METH_VARARGS,
210                 GetSubjects_doc},
211         {NULL,NULL} //Sentinel
212 };
213
214 PyObject* KX_NetworkMessageSensor::_getattr(const STR_String& attr) {
215         _getattr_up(SCA_ISensor); // implicit return!
216 }
217
218 // 1. Set the message subject that this sensor listens for
219 char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = 
220 "\tsetSubjectFilterText(value)\n"
221 "\tChange the message subject text that this sensor is listening to.\n";
222
223 PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(
224         PyObject* self,
225         PyObject* args,
226         PyObject* kwds)
227 {
228         char* Subject;
229
230         if (PyArg_ParseTuple(args, "s", &Subject))
231         {
232              m_subject = Subject;
233         }
234
235         Py_Return;
236 }
237
238 // 2. Get the number of messages received since the last frame
239 char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
240 "\tgetFrameMessageCount()\n"
241 "\tGet the number of messages received since the last frame.\n";
242
243 PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount(
244         PyObject* self,
245         PyObject* args,
246         PyObject* kwds)
247 {
248         return PyInt_FromLong(long(m_frame_message_count));
249 }
250
251 // 3. Get the message bodies
252 char KX_NetworkMessageSensor::GetBodies_doc[] =
253 "\tgetBodies()\n"
254 "\tGet the list of message bodies.\n";
255
256 PyObject* KX_NetworkMessageSensor::PyGetBodies(
257         PyObject* self,
258         PyObject* args,
259         PyObject* kwds)
260 {
261         if (m_BodyList) {
262                 return ((PyObject*) m_BodyList->AddRef());
263         }
264
265         Py_Return;
266 }
267
268 // 4. Get the message subject: field of the message sensor
269 char KX_NetworkMessageSensor::GetSubject_doc[] =
270 "\tgetSubject()\n"
271 "\tGet the subject: field of the message sensor.\n";
272
273 PyObject* KX_NetworkMessageSensor::PyGetSubject(
274         PyObject* self,
275         PyObject* args,
276         PyObject* kwds)
277 {
278         if (m_subject) {
279                 return PyString_FromString(m_subject);
280         }
281
282         Py_Return;
283 }
284
285 // 5. Get the message subjects
286 char KX_NetworkMessageSensor::GetSubjects_doc[] =
287 "\tgetSubjects()\n"
288 "\tGet list of message subjects.\n";
289
290 PyObject* KX_NetworkMessageSensor::PyGetSubjects(
291            PyObject* self,
292            PyObject* args,
293            PyObject* kwds)
294 {
295         if (m_SubjectList) {
296           return ((PyObject*) m_SubjectList->AddRef());
297           }
298
299         Py_Return;
300 }