BGE: Extend Python API for KX_BlenderMaterial (specular, diffuse…)

Add support for material diffuse, specular… in KX_BlenderMaterial python proxy. And use mathutils in KX_BlenderMaterial for the specular and diffuse color in KX_BlenderMaterial.

Reviewers: sybren, brita_, kupoman, agoose77, dfelinto, moguri, campbellbarton, hg1

Reviewed By: moguri, campbellbarton, hg1

Subscribers: dfelinto

Projects: #game_engine

Differential Revision: https://developer.blender.org/D1298
This commit is contained in:
Porteries Tristan
2015-07-03 11:47:48 +02:00
parent 659e5234af
commit 145ab8c49e
6 changed files with 368 additions and 0 deletions

View File

@@ -89,6 +89,48 @@ base class --- :class:`PyObjectPlus`
:return: the material's shader
:rtype: :class:`BL_Shader`
.. attribute:: alpha
The material's alpha transparency.
:type: float between 0.0 and 1.0 inclusive
.. attribute:: hardness
How hard (sharp) the material's specular reflection is.
:type: integer between 1 and 511 inclusive
.. attribute:: emit
Amount of light to emit.
:type: float between 0.0 and 2.0 inclusive
.. attribute:: specularIntensity
How intense (bright) the material's specular reflection is.
:type: float between 0.0 and 1.0 inclusive
.. attribute:: diffuseIntensity
The material's amount of diffuse reflection.
:type: float between 0.0 and 1.0 inclusive
.. attribute:: specularColor
The material's specular color.
:type: :class:`mathutils.Color`
.. attribute:: diffuseColor
The material's diffuse color.
:type: :class:`mathutils.Color`
.. method:: setBlending(src, dest)
Set the pixel color arithmetic functions.

View File

@@ -30,6 +30,7 @@
#include "KX_Light.h"
#include "KX_GameObject.h"
#include "KX_MeshProxy.h"
#include "KX_PyMath.h"
#include "MT_Vector3.h"
#include "MT_Vector4.h"
@@ -52,6 +53,7 @@
#include "BKE_mesh.h"
// ------------------------------------
#include "BLI_utildefines.h"
#include "BLI_math.h"
#define spit(x) std::cout << x << std::endl;
@@ -844,6 +846,11 @@ void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
OnConstruction();
}
BL_Material *KX_BlenderMaterial::GetBLMaterial()
{
return mMaterial;
}
void KX_BlenderMaterial::SetBlenderGLSLShader()
{
if (!mBlenderShader)
@@ -855,6 +862,111 @@ void KX_BlenderMaterial::SetBlenderGLSLShader()
}
}
#ifdef USE_MATHUTILS
#define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1
#define MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR 2
static unsigned char mathutils_kxblendermaterial_color_cb_index = -1; /* index for our callbacks */
static int mathutils_kxblendermaterial_generic_check(BaseMathObject *bmo)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
if (!self)
return -1;
return 0;
}
static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial*>BGE_PROXY_REF(bmo->cb_user);
if (!self)
return -1;
switch (subtype) {
case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
{
copy_v3_v3(bmo->data, self->GetBLMaterial()->matcolor);
break;
}
case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
{
copy_v3_v3(bmo->data, self->GetBLMaterial()->speccolor);
break;
}
}
return 0;
}
static int mathutils_kxblendermaterial_color_set(BaseMathObject *bmo, int subtype)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
if (!self)
return -1;
switch (subtype) {
case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
{
BL_Material *mat = self->GetBLMaterial();
copy_v3_v3(mat->matcolor, bmo->data);
mat->material->r = bmo->data[0];
mat->material->g = bmo->data[1];
mat->material->b = bmo->data[2];
break;
}
case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
{
BL_Material *mat = self->GetBLMaterial();
copy_v3_v3(mat->speccolor, bmo->data);
mat->material->specr = bmo->data[0];
mat->material->specg = bmo->data[1];
mat->material->specb = bmo->data[2];
break;
}
}
return 0;
}
static int mathutils_kxblendermaterial_color_get_index(BaseMathObject *bmo, int subtype, int index)
{
/* lazy, avoid repeteing the case statement */
if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
return -1;
return 0;
}
static int mathutils_kxblendermaterial_color_set_index(BaseMathObject *bmo, int subtype, int index)
{
float f = bmo->data[index];
/* lazy, avoid repeateing the case statement */
if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
return -1;
bmo->data[index] = f;
return mathutils_kxblendermaterial_color_set(bmo, subtype);
}
static Mathutils_Callback mathutils_kxblendermaterial_color_cb = {
mathutils_kxblendermaterial_generic_check,
mathutils_kxblendermaterial_color_get,
mathutils_kxblendermaterial_color_set,
mathutils_kxblendermaterial_color_get_index,
mathutils_kxblendermaterial_color_set_index
};
void KX_BlenderMaterial_Mathutils_Callback_Init()
{
// register mathutils callbacks, ok to run more than once.
mathutils_kxblendermaterial_color_cb_index = Mathutils_RegisterCallback(&mathutils_kxblendermaterial_color_cb);
}
#endif // USE_MATHUTILS
#ifdef WITH_PYTHON
PyMethodDef KX_BlenderMaterial::Methods[] =
@@ -869,6 +981,14 @@ PyAttributeDef KX_BlenderMaterial::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha),
KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness),
KX_PYATTRIBUTE_RW_FUNCTION("specularIntensity", KX_BlenderMaterial, pyattr_get_specular_intensity, pyattr_set_specular_intensity),
KX_PYATTRIBUTE_RW_FUNCTION("specularColor", KX_BlenderMaterial, pyattr_get_specular_color, pyattr_set_specular_color),
KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity),
KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color),
KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit),
{ NULL } //Sentinel
};
@@ -913,6 +1033,170 @@ PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRI
return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
}
PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyFloat_FromDouble(self->GetBLMaterial()->alpha);
}
int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
float val = PyFloat_AsDouble(value);
if (val == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
CLAMP(val, 0.0f, 1.0f);
BL_Material *mat = self->GetBLMaterial();
mat->alpha = mat->material->alpha = val;
return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyLong_FromLong(self->GetBLMaterial()->hard);
}
int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
int val = PyLong_AsLong(value);
if (val == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
CLAMP(val, 1, 511);
BL_Material *mat = self->GetBLMaterial();
mat->hard = mat->material->har = val;
return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyFloat_FromDouble(self->GetBLMaterial()->spec_f);
}
int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
float val = PyFloat_AsDouble(value);
if (val == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
CLAMP(val, 0.0f, 1.0f);
BL_Material *mat = self->GetBLMaterial();
mat->spec_f = mat->material->spec = val;
return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_BlenderMaterial::pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR);
#else
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->speccolor));
#endif
}
int KX_BlenderMaterial::pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
MT_Vector3 color;
if (!PyVecTo(value, color))
return PY_SET_ATTR_FAIL;
BL_Material *mat = self->GetBLMaterial();
color.getValue(mat->speccolor);
mat->material->specr = color[0];
mat->material->specg = color[1];
mat->material->specb = color[2];
return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyFloat_FromDouble(self->GetBLMaterial()->ref);
}
int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
float val = PyFloat_AsDouble(value);
if (val == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
CLAMP(val, 0.0f, 1.0f);
BL_Material *mat = self->GetBLMaterial();
mat->ref = mat->material->ref = val;
return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_BlenderMaterial::pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR);
#else
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->matcolor));
#endif
}
int KX_BlenderMaterial::pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
MT_Vector3 color;
if (!PyVecTo(value, color))
return PY_SET_ATTR_FAIL;
BL_Material *mat = self->GetBLMaterial();
color.getValue(mat->matcolor);
mat->material->r = color[0];
mat->material->g = color[1];
mat->material->b = color[2];
return PY_SET_ATTR_SUCCESS;
}
PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
return PyFloat_FromDouble(self->GetBLMaterial()->emit);
}
int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
float val = PyFloat_AsDouble(value);
if (val == -1 && PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
return PY_SET_ATTR_FAIL;
}
CLAMP(val, 0.0f, 2.0f);
BL_Material *mat = self->GetBLMaterial();
mat->emit = mat->material->emit = val;
return PY_SET_ATTR_SUCCESS;
}
int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);

View File

@@ -30,6 +30,11 @@
struct MTFace;
class KX_Scene;
#ifdef USE_MATHUTILS
void KX_BlenderMaterial_Mathutils_Callback_Init(void);
#endif
class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial
{
Py_Header
@@ -99,6 +104,8 @@ public:
virtual void Replace_IScene(SCA_IScene *val);
BL_Material *GetBLMaterial();
#ifdef WITH_PYTHON
// --------------------------------
virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); }
@@ -107,6 +114,20 @@ public:
static PyObject *pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getShader);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getMaterialIndex);

View File

@@ -197,4 +197,19 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec)
#endif
}
PyObject *PyColorFromVector(const MT_Vector3 &vec)
{
#ifdef USE_MATHUTILS
float fvec[3];
vec.getValue(fvec);
return Color_CreatePyObject(fvec, NULL);
#else
PyObject *list = PyList_New(3);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1]));
PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2]));
return list;
#endif
}
#endif // WITH_PYTHON

View File

@@ -273,4 +273,9 @@ PyObject *PyObjectFrom(const MT_Tuple4 &pos);
#endif
/**
* Converts an MT_Vector3 to a python color object.
*/
PyObject *PyColorFromVector(const MT_Vector3 &vec);
#endif /* WITH_PYTHON */

View File

@@ -282,6 +282,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void)
KX_GameObject_Mathutils_Callback_Init();
KX_ObjectActuator_Mathutils_Callback_Init();
KX_WorldInfo_Mathutils_Callback_Init();
KX_BlenderMaterial_Mathutils_Callback_Init();
#endif
return m;