From 145ab8c49efe0de188a55f4c682dd5fcf916f105 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Fri, 3 Jul 2015 11:47:48 +0200 Subject: =?UTF-8?q?BGE:=20Extend=20Python=20API=20for=20KX=5FBlenderMateri?= =?UTF-8?q?al=20(specular,=20diffuse=E2=80=A6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../rst/bge_types/bge.types.KX_BlenderMaterial.rst | 42 +++ source/gameengine/Ketsji/KX_BlenderMaterial.cpp | 284 +++++++++++++++++++++ source/gameengine/Ketsji/KX_BlenderMaterial.h | 21 ++ source/gameengine/Ketsji/KX_PyMath.cpp | 15 ++ source/gameengine/Ketsji/KX_PyMath.h | 5 + source/gameengine/Ketsji/KX_PythonInitTypes.cpp | 1 + 6 files changed, 368 insertions(+) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst b/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst index 80450526c9a..17f54031ec3 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst @@ -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. diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 7ec2673bf1f..abe565f8e2f 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -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_castBGE_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_castBGE_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_castBGE_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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(self_v); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 23921588d6a..0448236b10c 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -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); diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 76332e75204..798e93a12e9 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -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 diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 159506946e8..63a37806fb6 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -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 */ diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index b3511e4e61a..ef6ad4712a5 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -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; -- cgit v1.2.3