BGE Python API cleanup - no functionality changes
[blender.git] / source / gameengine / Ketsji / KX_Light.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 #ifdef WIN32
34
35 #pragma warning (disable : 4786)
36 #endif
37
38 #include "KX_Light.h"
39 #include "KX_Camera.h"
40 #include "RAS_IRasterizer.h"
41 #include "RAS_IRenderTools.h"
42
43 #include "KX_PyMath.h"
44
45 #include "DNA_object_types.h"
46 #include "GPU_material.h"
47  
48 KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
49                                                            class RAS_IRenderTools* rendertools,
50                                                            const RAS_LightObject&       lightobj,
51                                                            bool glsl,
52                                                            PyTypeObject* T
53                                                            )
54  :
55         KX_GameObject(sgReplicationInfo,callbacks,T),
56                 m_rendertools(rendertools)
57 {
58         m_lightobj = lightobj;
59         m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr();
60         m_lightobj.m_scene = sgReplicationInfo;
61         m_rendertools->AddLight(&m_lightobj);
62         m_glsl = glsl;
63         m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene();
64 };
65
66
67 KX_LightObject::~KX_LightObject()
68 {
69         GPULamp *lamp;
70
71         if((lamp = GetGPULamp())) {
72                 float obmat[4][4] = {{0}};
73                 GPU_lamp_update(lamp, 0, obmat);
74         }
75
76         m_rendertools->RemoveLight(&m_lightobj);
77 }
78
79
80 CValue*         KX_LightObject::GetReplica()
81 {
82
83         KX_LightObject* replica = new KX_LightObject(*this);
84
85         // this will copy properties and so on...
86         CValue::AddDataToReplica(replica);
87
88         ProcessReplica(replica);
89         
90         replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr();
91         m_rendertools->AddLight(&replica->m_lightobj);
92
93         return replica;
94 }
95
96 GPULamp *KX_LightObject::GetGPULamp()
97 {
98         if(m_glsl)
99                 return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject());
100         else
101                 return false;
102 }
103
104 void KX_LightObject::Update()
105 {
106         GPULamp *lamp;
107
108         if((lamp = GetGPULamp())) {
109                 float obmat[4][4];
110                 double *dobmat = GetOpenGLMatrixPtr()->getPointer();
111
112                 for(int i=0; i<4; i++)
113                         for(int j=0; j<4; j++, dobmat++)
114                                 obmat[i][j] = (float)*dobmat;
115
116                 GPU_lamp_update(lamp, m_lightobj.m_layer, obmat);
117         }
118 }
119
120 bool KX_LightObject::HasShadowBuffer()
121 {
122         GPULamp *lamp;
123
124         if((lamp = GetGPULamp()))
125                 return GPU_lamp_has_shadow_buffer(lamp);
126         else
127                 return false;
128 }
129
130 int KX_LightObject::GetShadowLayer()
131 {
132         GPULamp *lamp;
133
134         if((lamp = GetGPULamp()))
135                 return GPU_lamp_shadow_layer(lamp);
136         else
137                 return 0;
138 }
139
140 void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans)
141 {
142         GPULamp *lamp;
143         float viewmat[4][4], winmat[4][4];
144         int winsize;
145
146         /* bind framebuffer */
147         lamp = GetGPULamp();
148         GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat);
149
150         /* setup camera transformation */
151         MT_Matrix4x4 modelviewmat((float*)viewmat);
152         MT_Matrix4x4 projectionmat((float*)winmat);
153
154         MT_Transform trans = MT_Transform((float*)viewmat);
155         camtrans.invert(trans);
156
157         cam->SetModelviewMatrix(modelviewmat);
158         cam->SetProjectionMatrix(projectionmat);
159         
160         cam->NodeSetLocalPosition(camtrans.getOrigin());
161         cam->NodeSetLocalOrientation(camtrans.getBasis());
162         cam->NodeUpdateGS(0);
163
164         /* setup rasterizer transformations */
165         ras->SetProjectionMatrix(projectionmat);
166         ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(),
167                 cam->GetCameraLocation(), cam->GetCameraOrientation());
168 }
169
170 void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras)
171 {
172         GPULamp *lamp = GetGPULamp();
173         GPU_lamp_shadow_buffer_unbind(lamp);
174 }
175
176 PyObject* KX_LightObject::py_getattro(PyObject *attr)
177 {
178         char *attr_str= PyString_AsString(attr);
179         
180         if (!strcmp(attr_str, "layer"))
181                 return PyInt_FromLong(m_lightobj.m_layer);
182         
183         if (!strcmp(attr_str, "energy"))
184                 return PyFloat_FromDouble(m_lightobj.m_energy);
185         
186         if (!strcmp(attr_str, "distance"))
187                 return PyFloat_FromDouble(m_lightobj.m_distance);
188         
189         if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color"))
190                 return Py_BuildValue("[fff]", m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue);
191                 
192         if (!strcmp(attr_str, "lin_attenuation"))
193                 return PyFloat_FromDouble(m_lightobj.m_att1);
194         
195         if (!strcmp(attr_str, "quad_attenuation"))
196                 return PyFloat_FromDouble(m_lightobj.m_att2);
197         
198         if (!strcmp(attr_str, "spotsize"))
199                 return PyFloat_FromDouble(m_lightobj.m_spotsize);
200         
201         if (!strcmp(attr_str, "spotblend"))
202                 return PyFloat_FromDouble(m_lightobj.m_spotblend);
203                 
204         if (!strcmp(attr_str, "SPOT"))
205                 return PyInt_FromLong(RAS_LightObject::LIGHT_SPOT);
206                 
207         if (!strcmp(attr_str, "SUN"))
208                 return PyInt_FromLong(RAS_LightObject::LIGHT_SUN);
209         
210         if (!strcmp(attr_str, "NORMAL"))
211                 return PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL);
212         
213         if (!strcmp(attr_str, "type"))
214                 return PyInt_FromLong(m_lightobj.m_type);
215                 
216         py_getattro_up(KX_GameObject);
217 }
218
219
220 int KX_LightObject::py_setattro(PyObject *attr, PyObject *pyvalue)
221 {
222         char *attr_str= PyString_AsString(attr);
223         
224         if (PyInt_Check(pyvalue))
225         {
226                 int value = PyInt_AsLong(pyvalue);
227                 if (!strcmp(attr_str, "layer"))
228                 {
229                         m_lightobj.m_layer = value;
230                         return PY_SET_ATTR_SUCCESS;
231                 }
232                 
233                 if (!strcmp(attr_str, "type"))
234                 {
235                         if (value >= RAS_LightObject::LIGHT_SPOT && value <= RAS_LightObject::LIGHT_NORMAL)
236                                 m_lightobj.m_type = (RAS_LightObject::LightType) value;
237                         return PY_SET_ATTR_SUCCESS;
238                 }
239         }
240         
241         if (PyFloat_Check(pyvalue) || PyInt_Check(pyvalue))
242         {
243                 float value = PyFloat_AsDouble(pyvalue);
244                 if (!strcmp(attr_str, "energy"))
245                 {
246                         m_lightobj.m_energy = value;
247                         return PY_SET_ATTR_SUCCESS;
248                 }
249         
250                 if (!strcmp(attr_str, "distance"))
251                 {
252                         m_lightobj.m_distance = value;
253                         return PY_SET_ATTR_SUCCESS;
254                 }
255                 
256                 if (!strcmp(attr_str, "lin_attenuation"))
257                 {
258                         m_lightobj.m_att1 = value;
259                         return PY_SET_ATTR_SUCCESS;
260                 }
261                 
262                 if (!strcmp(attr_str, "quad_attenuation"))
263                 {
264                         m_lightobj.m_att2 = value;
265                         return PY_SET_ATTR_SUCCESS;
266                 }
267                 
268                 if (!strcmp(attr_str, "spotsize"))
269                 {
270                         m_lightobj.m_spotsize = value;
271                         return PY_SET_ATTR_SUCCESS;
272                 }
273                 
274                 if (!strcmp(attr_str, "spotblend"))
275                 {
276                         m_lightobj.m_spotblend = value;
277                         return PY_SET_ATTR_SUCCESS;
278                 }
279         }
280
281         if (PySequence_Check(pyvalue))
282         {
283                 if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color"))
284                 {
285                         MT_Vector3 color;
286                         if (PyVecTo(pyvalue, color))
287                         {
288                                 m_lightobj.m_red = color[0];
289                                 m_lightobj.m_green = color[1];
290                                 m_lightobj.m_blue = color[2];
291                                 return PY_SET_ATTR_SUCCESS;
292                         }
293                         return PY_SET_ATTR_FAIL;
294                 }
295         }
296         
297         if (!strcmp(attr_str, "SPOT") || !strcmp(attr_str, "SUN") || !strcmp(attr_str, "NORMAL"))
298         {
299                 PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr_str);
300                 return PY_SET_ATTR_FAIL;
301         }
302         
303         return KX_GameObject::py_setattro(attr, pyvalue);
304 }
305
306 PyMethodDef KX_LightObject::Methods[] = {
307         {NULL,NULL} //Sentinel
308 };
309
310 PyAttributeDef KX_LightObject::Attributes[] = {
311         KX_PYATTRIBUTE_DUMMY("layer"),
312         KX_PYATTRIBUTE_DUMMY("energy"),
313         KX_PYATTRIBUTE_DUMMY("distance"),
314         KX_PYATTRIBUTE_DUMMY("colour"),
315         KX_PYATTRIBUTE_DUMMY("color"),
316         KX_PYATTRIBUTE_DUMMY("lin_attenuation"),
317         KX_PYATTRIBUTE_DUMMY("quad_attenuation"),
318         KX_PYATTRIBUTE_DUMMY("spotsize"),
319         KX_PYATTRIBUTE_DUMMY("spotblend"),
320         KX_PYATTRIBUTE_DUMMY("SPOT"),
321         KX_PYATTRIBUTE_DUMMY("SUN"),
322         KX_PYATTRIBUTE_DUMMY("NORMAL"),
323         KX_PYATTRIBUTE_DUMMY("type"),
324         { NULL }        //Sentinel
325 };
326
327 PyTypeObject KX_LightObject::Type = {
328         PyObject_HEAD_INIT(NULL)
329                 0,
330                 "KX_LightObject",
331                 sizeof(PyObjectPlus_Proxy),
332                 0,
333                 py_base_dealloc,
334                 0,
335                 0,
336                 0,
337                 0,
338                 py_base_repr,
339                 0,0,
340                 &KX_GameObject::Mapping,
341                 0,0,0,
342                 py_base_getattro,
343                 py_base_setattro,
344                 0,0,0,0,0,0,0,0,0,
345                 Methods
346 };
347
348 PyParentObject KX_LightObject::Parents[] = {
349         &KX_LightObject::Type,
350         &KX_GameObject::Type,
351                 &SCA_IObject::Type,
352                 &CValue::Type,
353                 NULL
354 };