blender/source/gameengine/Ketsji/KX_Light.cpp

414 lines
12 KiB
C++

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file gameengine/Ketsji/KX_Light.cpp
* \ingroup ketsji
*/
#ifdef _MSC_VER
# pragma warning (disable:4786)
#endif
#include <stdio.h>
#include "KX_Light.h"
#include "KX_Camera.h"
#include "RAS_IRasterizer.h"
#include "RAS_ICanvas.h"
#include "RAS_ILightObject.h"
#include "KX_PyMath.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_lamp_types.h"
#include "BKE_scene.h"
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
RAS_IRasterizer* rasterizer,
RAS_ILightObject* lightobj,
bool glsl)
: KX_GameObject(sgReplicationInfo,callbacks),
m_rasterizer(rasterizer)
{
m_lightobj = lightobj;
m_lightobj->m_scene = sgReplicationInfo;
m_lightobj->m_light = this;
m_rasterizer->AddLight(m_lightobj);
m_lightobj->m_glsl = glsl;
m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene();
m_base = NULL;
};
KX_LightObject::~KX_LightObject()
{
if (m_lightobj) {
m_rasterizer->RemoveLight(m_lightobj);
delete(m_lightobj);
}
if (m_base) {
BKE_scene_base_unlink(m_blenderscene, m_base);
MEM_freeN(m_base);
}
}
CValue* KX_LightObject::GetReplica()
{
KX_LightObject* replica = new KX_LightObject(*this);
replica->ProcessReplica();
replica->m_lightobj = m_lightobj->Clone();
replica->m_lightobj->m_light = replica;
m_rasterizer->AddLight(replica->m_lightobj);
if (m_base)
m_base = NULL;
return replica;
}
void KX_LightObject::UpdateScene(KX_Scene *kxscene)
{
m_lightobj->m_scene = (void*)kxscene;
m_blenderscene = kxscene->GetBlenderScene();
m_base = BKE_scene_base_add(m_blenderscene, GetBlenderObject());
}
void KX_LightObject::SetLayer(int layer)
{
m_lightobj->m_layer = layer;
}
#ifdef WITH_PYTHON
/* ------------------------------------------------------------------------- */
/* Python Integration Hooks */
/* ------------------------------------------------------------------------- */
PyTypeObject KX_LightObject::Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"KX_LightObject",
sizeof(PyObjectPlus_Proxy),
0,
py_base_dealloc,
0,
0,
0,
0,
py_base_repr,
0,
&KX_GameObject::Sequence,
&KX_GameObject::Mapping,
0,0,0,
NULL,
NULL,
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
0,0,0,0,0,0,0,
Methods,
0,
0,
&KX_GameObject::Type,
0,0,0,0,0,0,
py_base_new
};
PyMethodDef KX_LightObject::Methods[] = {
{NULL,NULL} //Sentinel
};
PyAttributeDef KX_LightObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("layer", KX_LightObject, pyattr_get_layer, pyattr_set_layer),
KX_PYATTRIBUTE_RW_FUNCTION("energy", KX_LightObject, pyattr_get_energy, pyattr_set_energy),
KX_PYATTRIBUTE_RW_FUNCTION("distance", KX_LightObject, pyattr_get_distance, pyattr_set_distance),
KX_PYATTRIBUTE_RW_FUNCTION("color", KX_LightObject, pyattr_get_color, pyattr_set_color),
KX_PYATTRIBUTE_RW_FUNCTION("lin_attenuation", KX_LightObject, pyattr_get_lin_attenuation, pyattr_set_lin_attenuation),
KX_PYATTRIBUTE_RW_FUNCTION("quad_attenuation", KX_LightObject, pyattr_get_quad_attenuation, pyattr_set_quad_attenuation),
KX_PYATTRIBUTE_RW_FUNCTION("spotsize", KX_LightObject, pyattr_get_spotsize, pyattr_set_spotsize),
KX_PYATTRIBUTE_RW_FUNCTION("spotblend", KX_LightObject, pyattr_get_spotblend, pyattr_set_spotblend),
KX_PYATTRIBUTE_RO_FUNCTION("SPOT", KX_LightObject, pyattr_get_typeconst),
KX_PYATTRIBUTE_RO_FUNCTION("SUN", KX_LightObject, pyattr_get_typeconst),
KX_PYATTRIBUTE_RO_FUNCTION("NORMAL", KX_LightObject, pyattr_get_typeconst),
KX_PYATTRIBUTE_RW_FUNCTION("type", KX_LightObject, pyattr_get_type, pyattr_set_type),
{ NULL } //Sentinel
};
PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyLong_FromLong(self->m_lightobj->m_layer);
}
int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyLong_Check(value)) {
int val = PyLong_AsLong(value);
if (val < 1)
val = 1;
else if (val > 20)
val = 20;
self->m_lightobj->m_layer = val;
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyFloat_FromDouble(self->m_lightobj->m_energy);
}
int KX_LightObject::pyattr_set_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyFloat_Check(value)) {
float val = PyFloat_AsDouble(value);
if (val < 0)
val = 0;
else if (val > 10)
val = 10;
self->m_lightobj->m_energy = val;
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_distance(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyFloat_FromDouble(self->m_lightobj->m_distance);
}
int KX_LightObject::pyattr_set_distance(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyFloat_Check(value)) {
float val = PyFloat_AsDouble(value);
if (val < 0.01)
val = 0.01;
else if (val > 5000.f)
val = 5000.f;
self->m_lightobj->m_energy = val;
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return Py_BuildValue("[fff]", self->m_lightobj->m_color[0], self->m_lightobj->m_color[1], self->m_lightobj->m_color[1]);
}
int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
MT_Vector3 color;
if (PyVecTo(value, color))
{
self->m_lightobj->m_color[0] = color[0];
self->m_lightobj->m_color[1] = color[1];
self->m_lightobj->m_color[2] = color[2];
return PY_SET_ATTR_SUCCESS;
}
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_lin_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyFloat_FromDouble(self->m_lightobj->m_att1);
}
int KX_LightObject::pyattr_set_lin_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyFloat_Check(value)) {
float val = PyFloat_AsDouble(value);
if (val < 0.f)
val = 0.f;
else if (val > 1.f)
val = 1.f;
self->m_lightobj->m_att1 = val;
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_quad_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyFloat_FromDouble(self->m_lightobj->m_att2);
}
int KX_LightObject::pyattr_set_quad_attenuation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyFloat_Check(value)) {
float val = PyFloat_AsDouble(value);
if (val < 0.f)
val = 0.f;
else if (val > 1.f)
val = 1.f;
self->m_lightobj->m_att2 = val;
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_spotsize(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyFloat_FromDouble(RAD2DEG(self->m_lightobj->m_spotsize));
}
int KX_LightObject::pyattr_set_spotsize(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyFloat_Check(value)) {
float val = PyFloat_AsDouble(value);
if (val < 0.f)
val = 0.f;
else if (val > 180.f)
val = 180.f;
self->m_lightobj->m_spotsize = DEG2RAD(val);
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_spotblend(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyFloat_FromDouble(self->m_lightobj->m_spotblend);
}
int KX_LightObject::pyattr_set_spotblend(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
if (PyFloat_Check(value)) {
float val = PyFloat_AsDouble(value);
if (val < 0.f)
val = 0.f;
else if (val > 1.f)
val = 1.f;
self->m_lightobj->m_spotblend = val;
return PY_SET_ATTR_SUCCESS;
}
PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
PyObject *retvalue;
const char* type = attrdef->m_name;
if (!strcmp(type, "SPOT")) {
retvalue = PyLong_FromLong(RAS_ILightObject::LIGHT_SPOT);
} else if (!strcmp(type, "SUN")) {
retvalue = PyLong_FromLong(RAS_ILightObject::LIGHT_SUN);
} else if (!strcmp(type, "NORMAL")) {
retvalue = PyLong_FromLong(RAS_ILightObject::LIGHT_NORMAL);
}
else {
/* should never happen */
PyErr_SetString(PyExc_TypeError, "light.type: internal error, invalid light type");
retvalue = NULL;
}
return retvalue;
}
PyObject *KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
return PyLong_FromLong(self->m_lightobj->m_type);
}
int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
const int val = PyLong_AsLong(value);
if ((val==-1 && PyErr_Occurred()) || val<0 || val>2) {
PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2");
return PY_SET_ATTR_FAIL;
}
switch (val) {
case 0:
self->m_lightobj->m_type = self->m_lightobj->LIGHT_SPOT;
break;
case 1:
self->m_lightobj->m_type = self->m_lightobj->LIGHT_SUN;
break;
case 2:
self->m_lightobj->m_type = self->m_lightobj->LIGHT_NORMAL;
break;
}
return PY_SET_ATTR_SUCCESS;
}
#endif // WITH_PYTHON