5f490747c2b4f38468cf72a817535f083df4051c
[blender.git] / source / gameengine / Ketsji / KX_Light.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/Ketsji/KX_Light.cpp
29  *  \ingroup ketsji
30  */
31
32 #ifdef _MSC_VER
33 #  pragma warning (disable:4786)
34 #endif
35
36 #include <stdio.h>
37
38 #include "KX_Light.h"
39 #include "KX_Camera.h"
40 #include "RAS_IRasterizer.h"
41 #include "RAS_ICanvas.h"
42 #include "RAS_ILightObject.h"
43
44 #include "KX_PyMath.h"
45
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_lamp_types.h"
49
50 #include "BKE_scene.h"
51 #include "MEM_guardedalloc.h"
52
53 #include "BLI_math.h"
54
55 KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
56                                RAS_IRasterizer* rasterizer,
57                                RAS_ILightObject* lightobj,
58                                bool glsl)
59         : KX_GameObject(sgReplicationInfo,callbacks),
60           m_rasterizer(rasterizer)
61 {
62         m_lightobj = lightobj;
63         m_lightobj->m_scene = sgReplicationInfo;
64         m_lightobj->m_light = this;
65         m_rasterizer->AddLight(m_lightobj);
66         m_lightobj->m_glsl = glsl;
67         m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene();
68         m_base = NULL;
69 };
70
71
72 KX_LightObject::~KX_LightObject()
73 {
74         if (m_lightobj) {
75                 m_rasterizer->RemoveLight(m_lightobj);
76                 delete(m_lightobj);
77         }
78
79         if (m_base) {
80                 BKE_scene_base_unlink(m_blenderscene, m_base);
81                 MEM_freeN(m_base);
82         }
83 }
84
85
86 CValue*         KX_LightObject::GetReplica()
87 {
88
89         KX_LightObject* replica = new KX_LightObject(*this);
90
91         replica->ProcessReplica();
92         
93         replica->m_lightobj = m_lightobj->Clone();
94         replica->m_lightobj->m_light = replica;
95         m_rasterizer->AddLight(replica->m_lightobj);
96         if (m_base)
97                 m_base = NULL;
98
99         return replica;
100 }
101
102 void KX_LightObject::UpdateScene(KX_Scene *kxscene)
103 {
104         m_lightobj->m_scene = (void*)kxscene;
105         m_blenderscene = kxscene->GetBlenderScene();
106         m_base = BKE_scene_base_add(m_blenderscene, GetBlenderObject());
107 }
108
109 void KX_LightObject::SetLayer(int layer)
110 {
111         KX_GameObject::SetLayer(layer);
112         m_lightobj->m_layer = layer;
113 }
114
115 #ifdef WITH_PYTHON
116 /* ------------------------------------------------------------------------- */
117 /* Python Integration Hooks                                                                      */
118 /* ------------------------------------------------------------------------- */
119
120 PyTypeObject KX_LightObject::Type = {
121         PyVarObject_HEAD_INIT(NULL, 0)
122         "KX_LightObject",
123         sizeof(PyObjectPlus_Proxy),
124         0,
125         py_base_dealloc,
126         0,
127         0,
128         0,
129         0,
130         py_base_repr,
131         0,
132         &KX_GameObject::Sequence,
133         &KX_GameObject::Mapping,
134         0,0,0,
135         NULL,
136         NULL,
137         0,
138         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
139         0,0,0,0,0,0,0,
140         Methods,
141         0,
142         0,
143         &KX_GameObject::Type,
144         0,0,0,0,0,0,
145         py_base_new
146 };
147
148 PyMethodDef KX_LightObject::Methods[] = {
149         {NULL,NULL} //Sentinel
150 };
151
152 PyAttributeDef KX_LightObject::Attributes[] = {
153         KX_PYATTRIBUTE_RW_FUNCTION("layer", KX_LightObject, pyattr_get_layer, pyattr_set_layer),
154         KX_PYATTRIBUTE_RW_FUNCTION("energy", KX_LightObject, pyattr_get_energy, pyattr_set_energy),
155         KX_PYATTRIBUTE_RW_FUNCTION("distance", KX_LightObject, pyattr_get_distance, pyattr_set_distance),
156         KX_PYATTRIBUTE_RW_FUNCTION("color", KX_LightObject, pyattr_get_color, pyattr_set_color),
157         KX_PYATTRIBUTE_RW_FUNCTION("lin_attenuation", KX_LightObject, pyattr_get_lin_attenuation, pyattr_set_lin_attenuation),
158         KX_PYATTRIBUTE_RW_FUNCTION("quad_attenuation", KX_LightObject, pyattr_get_quad_attenuation, pyattr_set_quad_attenuation),
159         KX_PYATTRIBUTE_RW_FUNCTION("spotsize", KX_LightObject, pyattr_get_spotsize, pyattr_set_spotsize),
160         KX_PYATTRIBUTE_RW_FUNCTION("spotblend", KX_LightObject, pyattr_get_spotblend, pyattr_set_spotblend),
161         KX_PYATTRIBUTE_RO_FUNCTION("shadowClipStart", KX_LightObject, pyattr_get_shadow_clip_start),
162         KX_PYATTRIBUTE_RO_FUNCTION("shadowClipEnd", KX_LightObject, pyattr_get_shadow_clip_end),
163         KX_PYATTRIBUTE_RO_FUNCTION("shadowFrustumSize", KX_LightObject, pyattr_get_shadow_frustum_size),
164         KX_PYATTRIBUTE_RO_FUNCTION("shadowBias", KX_LightObject, pyattr_get_shadow_bias),
165         KX_PYATTRIBUTE_RO_FUNCTION("shadowBleedBias", KX_LightObject, pyattr_get_shadow_bleed_bias),
166         KX_PYATTRIBUTE_RO_FUNCTION("shadowBindId", KX_LightObject, pyattr_get_shadow_bind_code),
167         KX_PYATTRIBUTE_RO_FUNCTION("shadowMapType", KX_LightObject, pyattr_get_shadow_map_type),
168         KX_PYATTRIBUTE_RO_FUNCTION("shadowColor", KX_LightObject, pyattr_get_shadow_color),
169         KX_PYATTRIBUTE_RO_FUNCTION("useShadow", KX_LightObject, pyattr_get_shadow_active),
170         KX_PYATTRIBUTE_RO_FUNCTION("shadowMatrix", KX_LightObject, pyattr_get_shadow_matrix),
171         KX_PYATTRIBUTE_RO_FUNCTION("SPOT", KX_LightObject, pyattr_get_typeconst),
172         KX_PYATTRIBUTE_RO_FUNCTION("SUN", KX_LightObject, pyattr_get_typeconst),
173         KX_PYATTRIBUTE_RO_FUNCTION("NORMAL", KX_LightObject, pyattr_get_typeconst),
174         KX_PYATTRIBUTE_RW_FUNCTION("type", KX_LightObject, pyattr_get_type, pyattr_set_type),
175         { NULL }        //Sentinel
176 };
177
178 PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
179 {
180         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
181         return PyLong_FromLong(self->m_lightobj->m_layer);
182 }
183
184 int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
185 {
186         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
187         int layer = PyLong_AsLong(value);
188
189         if (layer == -1 && PyErr_Occurred()) {
190                 PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
191                 return PY_SET_ATTR_FAIL;
192         }
193
194         if (layer < 1) {
195                 PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name);
196                 return PY_SET_ATTR_FAIL;
197         }
198         else if (layer > MAX_LIGHT_LAYERS) {
199                 PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LIGHT_LAYERS, attrdef->m_name);
200                 return PY_SET_ATTR_FAIL;
201         }
202
203         self->SetLayer(layer);
204         return PY_SET_ATTR_SUCCESS;
205 }
206
207 PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
208 {
209         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
210         return PyFloat_FromDouble(self->m_lightobj->m_energy);
211 }
212
213 int KX_LightObject::pyattr_set_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
214 {
215         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
216
217         if (PyFloat_Check(value)) {
218                 float val = PyFloat_AsDouble(value);
219                 if (val < 0)
220                         val = 0;
221                 else if (val > 10)
222                         val = 10;
223
224                 self->m_lightobj->m_energy = val;
225                 return PY_SET_ATTR_SUCCESS;
226         }
227
228         PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
229         return PY_SET_ATTR_FAIL;
230 }
231
232 PyObject *KX_LightObject::pyattr_get_shadow_clip_start(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
233 {
234         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
235         return PyFloat_FromDouble(self->m_lightobj->m_shadowclipstart);
236 }
237
238 PyObject *KX_LightObject::pyattr_get_shadow_clip_end(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
239 {
240         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
241         return PyFloat_FromDouble(self->m_lightobj->m_shadowclipend);
242 }
243
244 PyObject *KX_LightObject::pyattr_get_shadow_frustum_size(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
245 {
246         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
247         return PyFloat_FromDouble(self->m_lightobj->m_shadowfrustumsize);
248 }
249
250 PyObject *KX_LightObject::pyattr_get_shadow_bind_code(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
251 {
252         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
253         return PyLong_FromLong(self->m_lightobj->GetShadowBindCode());
254 }
255
256 PyObject *KX_LightObject::pyattr_get_shadow_bias(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
257 {
258         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
259         return PyFloat_FromDouble(self->m_lightobj->m_shadowbias);
260 }
261
262 PyObject *KX_LightObject::pyattr_get_shadow_bleed_bias(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
263 {
264         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
265         return PyFloat_FromDouble(self->m_lightobj->m_shadowbleedbias);
266 }
267
268 PyObject *KX_LightObject::pyattr_get_shadow_map_type(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
269 {
270         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
271         return PyLong_FromLong(self->m_lightobj->m_shadowmaptype);
272 }
273
274 PyObject *KX_LightObject::pyattr_get_shadow_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
275 {
276         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
277         return PyObjectFrom(self->m_lightobj->GetShadowMatrix());
278 }
279
280 PyObject *KX_LightObject::pyattr_get_shadow_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
281 {
282         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
283         return PyColorFromVector(MT_Vector3(self->m_lightobj->m_shadowcolor));
284 }
285
286 PyObject *KX_LightObject::pyattr_get_shadow_active(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
287 {
288         KX_LightObject *self = static_cast<KX_LightObject *>(self_v);
289         return PyBool_FromLong(self->m_lightobj->HasShadowBuffer());
290 }
291
292 PyObject *KX_LightObject::pyattr_get_distance(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
293 {
294         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
295         return PyFloat_FromDouble(self->m_lightobj->m_distance);
296 }
297
298 int KX_LightObject::pyattr_set_distance(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
299 {
300         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
301
302         if (PyFloat_Check(value)) {
303                 float val = PyFloat_AsDouble(value);
304                 if (val < 0.01f)
305                         val = 0.01f;
306                 else if (val > 5000.f)
307                         val = 5000.f;
308
309                 self->m_lightobj->m_distance = val;
310                 return PY_SET_ATTR_SUCCESS;
311         }
312
313         PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
314         return PY_SET_ATTR_FAIL;
315 }
316
317 PyObject *KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
318 {
319         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
320         return Py_BuildValue("[fff]", self->m_lightobj->m_color[0], self->m_lightobj->m_color[1], self->m_lightobj->m_color[2]);
321 }
322
323 int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
324 {
325         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
326
327         MT_Vector3 color;
328         if (PyVecTo(value, color))
329         {
330                 self->m_lightobj->m_color[0] = color[0];
331                 self->m_lightobj->m_color[1] = color[1];
332                 self->m_lightobj->m_color[2] = color[2];
333                 return PY_SET_ATTR_SUCCESS;
334         }
335         return PY_SET_ATTR_FAIL;
336 }
337
338 PyObject *KX_LightObject::pyattr_get_lin_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
339 {
340         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
341         return PyFloat_FromDouble(self->m_lightobj->m_att1);
342 }
343
344 int KX_LightObject::pyattr_set_lin_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
345 {
346         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
347
348         if (PyFloat_Check(value)) {
349                 float val = PyFloat_AsDouble(value);
350                 if (val < 0.f)
351                         val = 0.f;
352                 else if (val > 1.f)
353                         val = 1.f;
354
355                 self->m_lightobj->m_att1 = val;
356                 return PY_SET_ATTR_SUCCESS;
357         }
358
359         PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
360         return PY_SET_ATTR_FAIL;
361 }
362
363 PyObject *KX_LightObject::pyattr_get_quad_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
364 {
365         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
366         return PyFloat_FromDouble(self->m_lightobj->m_att2);
367 }
368
369 int KX_LightObject::pyattr_set_quad_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
370 {
371         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
372
373         if (PyFloat_Check(value)) {
374                 float val = PyFloat_AsDouble(value);
375                 if (val < 0.f)
376                         val = 0.f;
377                 else if (val > 1.f)
378                         val = 1.f;
379
380                 self->m_lightobj->m_att2 = val;
381                 return PY_SET_ATTR_SUCCESS;
382         }
383
384         PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
385         return PY_SET_ATTR_FAIL;
386 }
387
388 PyObject *KX_LightObject::pyattr_get_spotsize(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
389 {
390         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
391         return PyFloat_FromDouble(RAD2DEG(self->m_lightobj->m_spotsize));
392 }
393
394 int KX_LightObject::pyattr_set_spotsize(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
395 {
396         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
397
398         if (PyFloat_Check(value)) {
399                 double val = PyFloat_AsDouble(value);
400                 if (val < 0.0)
401                         val = 0.0;
402                 else if (val > 180.0)
403                         val = 180.0;
404
405                 self->m_lightobj->m_spotsize = (float)DEG2RAD(val);
406                 return PY_SET_ATTR_SUCCESS;
407         }
408
409         PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
410         return PY_SET_ATTR_FAIL;
411 }
412 PyObject *KX_LightObject::pyattr_get_spotblend(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
413 {
414         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
415         return PyFloat_FromDouble(self->m_lightobj->m_spotblend);
416 }
417
418 int KX_LightObject::pyattr_set_spotblend(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
419 {
420         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
421
422         if (PyFloat_Check(value)) {
423                 float val = (float)PyFloat_AsDouble(value);
424                 if (val < 0.f)
425                         val = 0.f;
426                 else if (val > 1.f)
427                         val = 1.f;
428
429                 self->m_lightobj->m_spotblend = val;
430                 return PY_SET_ATTR_SUCCESS;
431         }
432
433         PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
434         return PY_SET_ATTR_FAIL;
435 }
436
437 PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
438 {
439         PyObject *retvalue;
440
441         const char* type = attrdef->m_name;
442
443         if (!strcmp(type, "SPOT")) {
444                 retvalue = PyLong_FromLong(RAS_ILightObject::LIGHT_SPOT);
445         } else if (!strcmp(type, "SUN")) {
446                 retvalue = PyLong_FromLong(RAS_ILightObject::LIGHT_SUN);
447         } else if (!strcmp(type, "NORMAL")) {
448                 retvalue = PyLong_FromLong(RAS_ILightObject::LIGHT_NORMAL);
449         }
450         else {
451                 /* should never happen */
452                 PyErr_SetString(PyExc_TypeError, "light.type: internal error, invalid light type");
453                 retvalue = NULL;
454         }
455
456         return retvalue;
457 }
458
459 PyObject *KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef)
460 {
461         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
462         return PyLong_FromLong(self->m_lightobj->m_type);
463 }
464
465 int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
466 {
467         KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
468         const int val = PyLong_AsLong(value);
469         if ((val==-1 && PyErr_Occurred()) || val<0 || val>2) {
470                 PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2");
471                 return PY_SET_ATTR_FAIL;
472         }
473         
474         switch (val) {
475                 case 0:
476                         self->m_lightobj->m_type = self->m_lightobj->LIGHT_SPOT;
477                         break;
478                 case 1:
479                         self->m_lightobj->m_type = self->m_lightobj->LIGHT_SUN;
480                         break;
481                 case 2:
482                         self->m_lightobj->m_type = self->m_lightobj->LIGHT_NORMAL;
483                         break;
484         }
485
486         return PY_SET_ATTR_SUCCESS;
487 }
488 #endif // WITH_PYTHON