svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r22668:22701
[blender-staging.git] / source / gameengine / Ketsji / KXNetwork / KX_NetworkMessageSensor.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Ketsji Logic Extenstion: Network Message Sensor generic implementation
29  */
30
31 #include "KX_NetworkMessageSensor.h"
32 #include "KX_NetworkEventManager.h"
33 #include "NG_NetworkMessage.h"
34 #include "NG_NetworkScene.h"
35 #include "NG_NetworkObject.h"
36 #include "SCA_IObject.h"        
37 #include "InputParser.h"
38 #include "ListValue.h"
39 #include "StringValue.h"
40
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44
45 #ifdef NAN_NET_DEBUG
46   #include <iostream>
47 #endif
48
49 KX_NetworkMessageSensor::KX_NetworkMessageSensor(
50         class KX_NetworkEventManager* eventmgr, // our eventmanager
51         class NG_NetworkScene *NetworkScene,    // our scene
52         SCA_IObject* gameobj,                                   // the sensor controlling object
53         const STR_String &subject
54 ) :
55     SCA_ISensor(gameobj,eventmgr),
56     m_NetworkScene(NetworkScene),
57     m_subject(subject),
58     m_frame_message_count (0),
59     m_BodyList(NULL),
60     m_SubjectList(NULL)
61 {
62         Init();
63 }
64
65 void KX_NetworkMessageSensor::Init()
66 {
67     m_IsUp = false;
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         replica->ProcessReplica();
81
82         return replica;
83 }
84
85 // Return true only for flank (UP and DOWN)
86 bool KX_NetworkMessageSensor::Evaluate()
87 {
88         bool result = false;
89         bool WasUp = m_IsUp;
90
91         m_IsUp = false;
92
93         if (m_BodyList) {
94                 m_BodyList->Release();
95                 m_BodyList = NULL;
96         }
97
98         if (m_SubjectList) {
99                 m_SubjectList->Release();
100                 m_SubjectList = NULL;
101         }
102
103         STR_String& toname=GetParent()->GetName();
104         STR_String& subject = this->m_subject;
105
106         vector<NG_NetworkMessage*> messages =
107                 m_NetworkScene->FindMessages(toname,"",subject,true);
108
109         m_frame_message_count = messages.size();
110
111         if (!messages.empty()) {
112 #ifdef NAN_NET_DEBUG
113                 printf("KX_NetworkMessageSensor found one or more messages\n");
114 #endif
115                 m_IsUp = true;
116                 m_BodyList = new CListValue();
117                 m_SubjectList = new CListValue();
118         }
119
120         vector<NG_NetworkMessage*>::iterator mesit;
121         for (mesit=messages.begin();mesit!=messages.end();mesit++)
122         {
123                 // save the body
124                 const STR_String& body = (*mesit)->GetMessageText();
125                 // save the subject
126                 const STR_String& messub = (*mesit)->GetSubject();
127 #ifdef NAN_NET_DEBUG
128                 if (body) {
129                         cout << "body [" << body << "]\n";
130                 }
131 #endif
132                 m_BodyList->Add(new CStringValue(body,"body"));
133                 // Store Subject
134                 m_SubjectList->Add(new CStringValue(messub,"subject"));
135
136                 // free the message
137                 (*mesit)->Release();
138         }
139         messages.clear();
140
141         result = (WasUp != m_IsUp);
142
143         // Return always true if a message was received otherwise we can loose messages
144         if (m_IsUp)
145                 return true;
146         // Is it usefull to return also true when the first frame without a message?? 
147         // This will cause a fast on/off cycle that seems useless!
148         return result;
149 }
150
151 // return true for being up (no flank needed)
152 bool KX_NetworkMessageSensor::IsPositiveTrigger()
153 {
154 //      printf("KX_NetworkMessageSensor IsPositiveTrigger\n");
155         //attempt to fix [ #3809 ] IPO Actuator does not work with some Sensors
156         //a better solution is to properly introduce separate Edge and Level triggering concept
157
158         return m_IsUp;
159 }
160
161 /* --------------------------------------------------------------------- */
162 /* Python interface ---------------------------------------------------- */
163 /* --------------------------------------------------------------------- */
164
165 /* Integration hooks --------------------------------------------------- */
166 PyTypeObject KX_NetworkMessageSensor::Type = {
167         PyVarObject_HEAD_INIT(NULL, 0)
168         "KX_NetworkMessageSensor",
169         sizeof(PyObjectPlus_Proxy),
170         0,
171         py_base_dealloc,
172         0,
173         0,
174         0,
175         0,
176         py_base_repr,
177         0,0,0,0,0,0,0,0,0,
178         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
179         0,0,0,0,0,0,0,
180         Methods,
181         0,
182         0,
183         &SCA_ISensor::Type,
184         0,0,0,0,0,0,
185         py_base_new
186 };
187
188 PyMethodDef KX_NetworkMessageSensor::Methods[] = {
189         // Deprecated ----->
190         {"setSubjectFilterText", (PyCFunction)
191                 KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O,
192                 (const char *)SetSubjectFilterText_doc},
193         {"getFrameMessageCount", (PyCFunction)
194                 KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_NOARGS,
195                 (const char *)GetFrameMessageCount_doc},
196         {"getBodies", (PyCFunction)
197                 KX_NetworkMessageSensor::sPyGetBodies, METH_NOARGS,
198                 (const char *)GetBodies_doc},
199         {"getSubject", (PyCFunction)
200                 KX_NetworkMessageSensor::sPyGetSubject, METH_NOARGS,
201                 (const char *)GetSubject_doc},
202         {"getSubjects", (PyCFunction)
203                 KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS,
204                 (const char *)GetSubjects_doc},
205         // <-----
206         {NULL,NULL} //Sentinel
207 };
208
209 PyAttributeDef KX_NetworkMessageSensor::Attributes[] = {
210         KX_PYATTRIBUTE_STRING_RW("subject", 0, 100, false, KX_NetworkMessageSensor, m_subject),
211         KX_PYATTRIBUTE_INT_RO("frameMessageCount", KX_NetworkMessageSensor, m_frame_message_count),
212         KX_PYATTRIBUTE_RO_FUNCTION("bodies", KX_NetworkMessageSensor, pyattr_get_bodies),
213         KX_PYATTRIBUTE_RO_FUNCTION("subjects", KX_NetworkMessageSensor, pyattr_get_subjects),
214         { NULL }        //Sentinel
215 };
216
217 PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
218 {
219         KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
220         if (self->m_BodyList) {
221                 return self->m_BodyList->GetProxy();
222         } else {
223                 return (new CListValue())->NewProxy(true);
224         }
225 }
226
227 PyObject* KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
228 {
229         KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v);
230         if (self->m_SubjectList) {
231                 return self->m_SubjectList->GetProxy();
232         } else {
233                 return (new CListValue())->NewProxy(true);
234         }
235 }
236
237 // Deprecated ----->
238 // 1. Set the message subject that this sensor listens for
239 const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = 
240 "\tsetSubjectFilterText(value)\n"
241 "\tChange the message subject text that this sensor is listening to.\n";
242
243 PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(PyObject* value)
244 {
245         ShowDeprecationWarning("setSubjectFilterText()", "subject");
246         char* Subject = _PyUnicode_AsString(value);
247         if (Subject==NULL) {
248                 PyErr_SetString(PyExc_TypeError, "sensor.tsetSubjectFilterText(string): KX_NetworkMessageSensor, expected a string message");
249                 return NULL;
250         }
251         
252         m_subject = Subject;
253         Py_RETURN_NONE;
254 }
255
256 // 2. Get the number of messages received since the last frame
257 const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
258 "\tgetFrameMessageCount()\n"
259 "\tGet the number of messages received since the last frame.\n";
260
261 PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount()
262 {
263         ShowDeprecationWarning("getFrameMessageCount()", "frameMessageCount");
264         return PyLong_FromSsize_t(long(m_frame_message_count));
265 }
266
267 // 3. Get the message bodies
268 const char KX_NetworkMessageSensor::GetBodies_doc[] =
269 "\tgetBodies()\n"
270 "\tGet the list of message bodies.\n";
271
272 PyObject* KX_NetworkMessageSensor::PyGetBodies()
273 {
274         ShowDeprecationWarning("getBodies()", "bodies");
275         if (m_BodyList) {
276                 return m_BodyList->GetProxy();
277         } else {
278                 return (new CListValue())->NewProxy(true);
279         }
280 }
281
282 // 4. Get the message subject: field of the message sensor
283 const char KX_NetworkMessageSensor::GetSubject_doc[] =
284 "\tgetSubject()\n"
285 "\tGet the subject: field of the message sensor.\n";
286
287 PyObject* KX_NetworkMessageSensor::PyGetSubject()
288 {
289         ShowDeprecationWarning("getSubject()", "subject");
290         return PyUnicode_FromString(m_subject ? m_subject : "");
291 }
292
293 // 5. Get the message subjects
294 const char KX_NetworkMessageSensor::GetSubjects_doc[] =
295 "\tgetSubjects()\n"
296 "\tGet list of message subjects.\n";
297
298 PyObject* KX_NetworkMessageSensor::PyGetSubjects()
299 {
300         ShowDeprecationWarning("getSubjects()", "subjects");
301         if (m_SubjectList) {
302                 return m_SubjectList->GetProxy();
303         } else {
304                 return (new CListValue())->NewProxy(true);
305         }
306 }
307 // <----- Deprecated