* First commit merging 2.4-based sim_physics in to volume25 branch.
[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         PyVarObject_HEAD_INIT(NULL, 0)
43         "KX_PolyProxy",
44         sizeof(PyObjectPlus_Proxy),
45         0,
46         py_base_dealloc,
47         0,
48         0,
49         0,
50         0,
51         py_base_repr,
52         0,0,0,0,0,0,0,0,0,
53         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
54         0,0,0,0,0,0,0,
55         Methods,
56         0,
57         0,
58         &CValue::Type,
59         0,0,0,0,0,0,
60         py_base_new
61 };
62
63 PyMethodDef KX_PolyProxy::Methods[] = {
64         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialIndex),
65         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getNumVertex),
66         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isVisible),
67         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,isCollider),
68         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterialName),
69         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getTextureName),
70         KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex),
71         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMesh),
72         KX_PYMETHODTABLE_NOARGS(KX_PolyProxy,getMaterial),
73         {NULL,NULL} //Sentinel
74 };
75
76 PyAttributeDef KX_PolyProxy::Attributes[] = {
77         /* All dummy's so they come up in a dir() */
78         //KX_PYATTRIBUTE_TODO("DummyProps"),
79         KX_PYATTRIBUTE_DUMMY("matname"),
80         KX_PYATTRIBUTE_DUMMY("texture"),
81         KX_PYATTRIBUTE_DUMMY("material"),
82         KX_PYATTRIBUTE_DUMMY("matid"),
83         KX_PYATTRIBUTE_DUMMY("v1"),
84         KX_PYATTRIBUTE_DUMMY("v2"),
85         KX_PYATTRIBUTE_DUMMY("v3"),
86         KX_PYATTRIBUTE_DUMMY("v4"),
87         KX_PYATTRIBUTE_DUMMY("visible"),
88         KX_PYATTRIBUTE_DUMMY("collide"),
89         { NULL }        //Sentinel
90 };
91
92 #if 0
93 PyObject* KX_PolyProxy::py_getattro(PyObject *attr)
94 {
95         char *attr_str= _PyUnicode_AsString(attr);
96         if (!strcmp(attr_str, "matname"))
97         {
98                 return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
99         }
100         if (!strcmp(attr_str, "texture"))
101         {
102                 return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
103         }
104         if (!strcmp(attr_str, "material"))
105         {
106                 RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
107                 if(polymat->GetFlag() & RAS_BLENDERMAT)
108                 {
109                         KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
110                         return mat->GetProxy();
111                 }
112                 else
113                 {
114                         KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
115                         return mat->GetProxy();
116                 }
117         }
118         if (!strcmp(attr_str, "matid"))
119         {
120                 // we'll have to scan through the material bucket of the mes and compare with 
121                 // the one of the polygon
122                 RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
123                 unsigned int matid;
124                 for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++)
125                 {
126                         RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
127                         if (meshMat->m_bucket == polyBucket)
128                                 // found it
129                                 break;
130                 }
131                 return PyLong_FromSsize_t(matid);
132         }
133         if (!strcmp(attr_str, "v1"))
134         {
135                 return PyLong_FromSsize_t(m_polygon->GetVertexOffset(0));
136         }
137         if (!strcmp(attr_str, "v2"))
138         {
139                 return PyLong_FromSsize_t(m_polygon->GetVertexOffset(1));
140         }
141         if (!strcmp(attr_str, "v3"))
142         {
143                 return PyLong_FromSsize_t(m_polygon->GetVertexOffset(2));
144         }
145         if (!strcmp(attr_str, "v4"))
146         {
147                 return PyLong_FromSsize_t(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0));
148         }
149         if (!strcmp(attr_str, "visible"))
150         {
151                 return PyLong_FromSsize_t(m_polygon->IsVisible());
152         }
153         if (!strcmp(attr_str, "collide"))
154         {
155                 return PyLong_FromSsize_t(m_polygon->IsCollider());
156         }
157         // py_getattro_up(CValue); // XXX -- todo, make all these attributes
158 }
159 #endif
160
161 KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon)
162 :       m_polygon(polygon),
163         m_mesh((RAS_MeshObject*)mesh)
164 {
165 }
166
167 KX_PolyProxy::~KX_PolyProxy()
168 {
169 }
170
171
172 // stuff for cvalue related things
173 CValue*         KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
174 CValue*         KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}      
175 STR_String      sPolyName="polygone";
176 const STR_String &      KX_PolyProxy::GetText() {return sPolyName;};
177 double          KX_PolyProxy::GetNumber() { return -1;}
178 STR_String&     KX_PolyProxy::GetName() { return sPolyName;}
179 void            KX_PolyProxy::SetName(const char *) { };
180 CValue*         KX_PolyProxy::GetReplica() { return NULL;}
181
182 // stuff for python integration
183
184 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, 
185 "getMaterialIndex() : return the material index of the polygon in the mesh\n")
186 {
187         RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
188         unsigned int matid;
189         for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++)
190         {
191                 RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
192                 if (meshMat->m_bucket == polyBucket)
193                         // found it
194                         break;
195         }
196         return PyLong_FromSsize_t(matid);
197 }
198
199 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex,
200 "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n")
201 {
202         return PyLong_FromSsize_t(m_polygon->VertexCount());
203 }
204
205 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible,
206 "isVisible() : returns whether the polygon is visible or not\n")
207 {
208         return PyLong_FromSsize_t(m_polygon->IsVisible());
209 }
210
211 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider,
212 "isCollider() : returns whether the polygon is receives collision or not\n")
213 {
214         return PyLong_FromSsize_t(m_polygon->IsCollider());
215 }
216
217 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName,
218 "getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n")
219 {
220         return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
221 }
222
223 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName,
224 "getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n")
225 {
226         return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
227 }
228
229 KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
230 "getVertexIndex(vertex) : returns the mesh vertex index of a polygon vertex\n"
231 "vertex: index of the vertex in the polygon: 0->3\n"
232 "return value can be used to retrieve the vertex details through mesh proxy\n"
233 "Note: getVertexIndex(3) on a triangle polygon returns 0\n")
234 {
235         int index;
236         if (!PyArg_ParseTuple(args,"i:getVertexIndex",&index))
237         {
238                 return NULL;
239         }
240         if (index < 0 || index > 3)
241         {
242                 PyErr_SetString(PyExc_AttributeError, "poly.getVertexIndex(int): KX_PolyProxy, expected an index between 0-3");
243                 return NULL;
244         }
245         if (index < m_polygon->VertexCount())
246         {
247                 return PyLong_FromSsize_t(m_polygon->GetVertexOffset(index));
248         }
249         return PyLong_FromSsize_t(0);
250 }
251
252 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh,
253 "getMesh() : returns a mesh proxy\n")
254 {
255         KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh);
256         return meshproxy->NewProxy(true);
257 }
258
259 KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial,
260 "getMaterial() : returns a material\n")
261 {
262         RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
263         if(polymat->GetFlag() & RAS_BLENDERMAT)
264         {
265                 KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
266                 return mat->GetProxy();
267         }
268         else
269         {
270                 KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
271                 return mat->GetProxy();
272         }
273 }