2.50:
[blender.git] / source / gameengine / Ketsji / KX_PolyProxy.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include "KX_PolyProxy.h"
34 #include "KX_MeshProxy.h"
35 #include "RAS_MeshObject.h"
36 #include "KX_BlenderMaterial.h"
37 #include "KX_PolygonMaterial.h"
38
39 #include "KX_PyMath.h"
40
41 PyTypeObject KX_PolyProxy::Type = {
42 #if (PY_VERSION_HEX >= 0x02060000)
43         PyVarObject_HEAD_INIT(NULL, 0)
44 #else
45         /* python 2.5 and below */
46         PyObject_HEAD_INIT( NULL )  /* required py macro */
47         0,                          /* ob_size */
48 #endif
49         "KX_PolyProxy",
50         sizeof(PyObjectPlus_Proxy),
51         0,
52         py_base_dealloc,
53         0,
54         0,
55         0,
56         0,
57         py_base_repr,
58         0,0,0,0,0,0,
59         py_base_getattro,
60         py_base_setattro,
61         0,0,0,0,0,0,0,0,0,
62         Methods
63 };
64
65 PyParentObject KX_PolyProxy::Parents[] = {
66         &KX_PolyProxy::Type,
67         &CValue::Type,
68         &PyObjectPlus::Type,
69         NULL
70 };
71
72 PyMethodDef KX_PolyProxy::Methods[] = {
73         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialIndex),
74         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getNumVertex),
75         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isVisible),
76         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isCollider),
77         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialName),
78         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getTextureName),
79         KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex),
80         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMesh),
81         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterial),
82         {NULL,NULL} //Sentinel
83 };
84
85 PyAttributeDef KX_PolyProxy::Attributes[] = {
86         /* All dummy's so they come up in a dir() */
87         //KX_PYATTRIBUTE_TODO("DummyProps"),
88         KX_PYATTRIBUTE_DUMMY("matname"),
89         KX_PYATTRIBUTE_DUMMY("texture"),
90         KX_PYATTRIBUTE_DUMMY("material"),
91         KX_PYATTRIBUTE_DUMMY("matid"),
92         KX_PYATTRIBUTE_DUMMY("v1"),
93         KX_PYATTRIBUTE_DUMMY("v2"),
94         KX_PYATTRIBUTE_DUMMY("v3"),
95         KX_PYATTRIBUTE_DUMMY("v4"),
96         KX_PYATTRIBUTE_DUMMY("visible"),
97         KX_PYATTRIBUTE_DUMMY("collide"),
98         { NULL }        //Sentinel
99 };
100
101 PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
102 {
103         char *attr_str= PyString_AsString(attr);
104         if (!strcmp(attr_str, "matname"))
105         {
106                 return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
107         }
108         if (!strcmp(attr_str, "texture"))
109         {
110                 return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
111         }
112         if (!strcmp(attr_str, "material"))
113         {
114                 RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
115                 if(polymat->GetFlag() & RAS_BLENDERMAT)
116                 {
117                         KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
118                         return mat->GetProxy();
119                 }
120                 else
121                 {
122                         KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
123                         return mat->GetProxy();
124                 }
125         }
126         if (!strcmp(attr_str, "matid"))
127         {
128                 // we'll have to scan through the material bucket of the mes and compare with 
129                 // the one of the polygon
130                 RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
131                 unsigned int matid;
132                 for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++)
133                 {
134                         RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
135                         if (meshMat->m_bucket == polyBucket)
136                                 // found it
137                                 break;
138                 }
139                 return PyInt_FromLong(matid);
140         }
141         if (!strcmp(attr_str, "v1"))
142         {
143                 return PyInt_FromLong(m_polygon->GetVertexOffset(0));
144         }
145         if (!strcmp(attr_str, "v2"))
146         {
147                 return PyInt_FromLong(m_polygon->GetVertexOffset(1));
148         }
149         if (!strcmp(attr_str, "v3"))
150         {
151                 return PyInt_FromLong(m_polygon->GetVertexOffset(2));
152         }
153         if (!strcmp(attr_str, "v4"))
154         {
155                 return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0));
156         }
157         if (!strcmp(attr_str, "visible"))
158         {
159                 return PyInt_FromLong(m_polygon->IsVisible());
160         }
161         if (!strcmp(attr_str, "collide"))
162         {
163                 return PyInt_FromLong(m_polygon->IsCollider());
164         }
165         py_getattro_up(CValue);
166 }
167
168 PyObject* KX_PolyProxy::py_getattro_dict() {
169         py_getattro_dict_up(CValue);
170 }
171
172 KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon)
173 :       m_polygon(polygon),
174         m_mesh((RAS_MeshObject*)mesh)
175 {
176 }
177
178 KX_PolyProxy::~KX_PolyProxy()
179 {
180 }
181
182
183 // stuff for cvalue related things
184 CValue*         KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
185 CValue*         KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}      
186 STR_String      sPolyName="polygone";
187 const STR_String &      KX_PolyProxy::GetText() {return sPolyName;};
188 double          KX_PolyProxy::GetNumber() { return -1;}
189 STR_String&     KX_PolyProxy::GetName() { return sPolyName;}
190 void            KX_PolyProxy::SetName(const char *) { };
191 CValue*         KX_PolyProxy::GetReplica() { return NULL;}
192
193 // stuff for python integration
194
195 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, 
196 "getMaterialIndex() : return the material index of the polygon in the mesh\n")
197 {
198         RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
199         unsigned int matid;
200         for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++)
201         {
202                 RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
203                 if (meshMat->m_bucket == polyBucket)
204                         // found it
205                         break;
206         }
207         return PyInt_FromLong(matid);
208 }
209
210 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex,
211 "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n")
212 {
213         return PyInt_FromLong(m_polygon->VertexCount());
214 }
215
216 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible,
217 "isVisible() : returns whether the polygon is visible or not\n")
218 {
219         return PyInt_FromLong(m_polygon->IsVisible());
220 }
221
222 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider,
223 "isCollider() : returns whether the polygon is receives collision or not\n")
224 {
225         return PyInt_FromLong(m_polygon->IsCollider());
226 }
227
228 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName,
229 "getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n")
230 {
231         return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
232 }
233
234 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName,
235 "getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n")
236 {
237         return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
238 }
239
240 KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
241 "getVertexIndex(vertex) : returns the mesh vertex index of a polygon vertex\n"
242 "vertex: index of the vertex in the polygon: 0->3\n"
243 "return value can be used to retrieve the vertex details through mesh proxy\n"
244 "Note: getVertexIndex(3) on a triangle polygon returns 0\n")
245 {
246         int index;
247         if (!PyArg_ParseTuple(args,"i:getVertexIndex",&index))
248         {
249                 return NULL;
250         }
251         if (index < 0 || index > 3)
252         {
253                 PyErr_SetString(PyExc_AttributeError, "poly.getVertexIndex(int): KX_PolyProxy, expected an index between 0-3");
254                 return NULL;
255         }
256         if (index < m_polygon->VertexCount())
257         {
258                 return PyInt_FromLong(m_polygon->GetVertexOffset(index));
259         }
260         return PyInt_FromLong(0);
261 }
262
263 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh,
264 "getMesh() : returns a mesh proxy\n")
265 {
266         KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh);
267         return meshproxy->NewProxy(true);
268 }
269
270 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial,
271 "getMaterial() : returns a material\n")
272 {
273         RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
274         if(polymat->GetFlag() & RAS_BLENDERMAT)
275         {
276                 KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
277                 return mat->GetProxy();
278         }
279         else
280         {
281                 KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
282                 return mat->GetProxy();
283         }
284 }