diff options
Diffstat (limited to 'source/gameengine/Ketsji')
102 files changed, 7157 insertions, 2554 deletions
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 8ec463be6ff..3df483b0598 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -52,7 +52,7 @@ void BL_BlenderShader::SetProg(bool enable, double time) { if(VerifyShader()) { if(enable) - GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, ~0, time); + GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, mBlenderScene->lay, time); else GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); } diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 60cb288436a..88d920043e0 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -729,9 +729,9 @@ void BL_Shader::SetUniform(int uniform, const int* val, int len) } -PyObject* BL_Shader::_getattr(const char *attr) +PyObject* BL_Shader::py_getattro(PyObject *attr) { - _getattr_up(PyObjectPlus); + py_getattro_up(PyObjectPlus); } @@ -772,24 +772,28 @@ PyAttributeDef BL_Shader::Attributes[] = { }; PyTypeObject BL_Shader::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "BL_Shader", - sizeof(BL_Shader), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, 0, - __repr, - 0 + 0, + 0, + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject BL_Shader::Parents[] = { - &PyObjectPlus::Type, &BL_Shader::Type, + &PyObjectPlus::Type, NULL }; @@ -803,7 +807,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProg } char *v,*f; int apply=0; - if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) ) + if( PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply) ) { vertProg = v; fragProg = f; @@ -854,7 +858,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") Py_RETURN_NONE; } if(mShader==0) { - PyErr_Format(PyExc_TypeError, "invalid shader object"); + PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object"); return NULL; } int stat = 0; @@ -886,7 +890,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) const char *uniform=""; int index=-1; - if(PyArg_ParseTuple(args, "si", &uniform, &index)) + if(PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) { int loc = GetUniformLocation(uniform); if(loc != -1) { @@ -911,7 +915,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" ) { int pass = 1; - if(!PyArg_ParseTuple(args, "i", &pass)) + if(!PyArg_ParseTuple(args, "i:setNumberOfPasses", &pass)) return NULL; mPass = 1; @@ -927,7 +931,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) const char *uniform=""; float value=0; - if(PyArg_ParseTuple(args, "sf", &uniform, &value )) + if(PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value )) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -951,7 +955,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)") } const char *uniform=""; float array[2]={ 0,0 }; - if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] )) + if(PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] )) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -975,7 +979,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") } const char *uniform=""; float array[3]={0,0,0}; - if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2])) + if(PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2])) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1000,7 +1004,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " } const char *uniform=""; float array[4]={0,0,0,0}; - if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3])) + if(PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3])) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1024,7 +1028,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) } const char *uniform=""; int value=0; - if(PyArg_ParseTuple(args, "si", &uniform, &value )) + if(PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value )) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1048,7 +1052,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)") } const char *uniform=""; int array[2]={ 0,0 }; - if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] )) + if(PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] )) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1073,7 +1077,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") const char *uniform=""; int array[3]={0,0,0}; - if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2])) + if(PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2])) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1096,7 +1100,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " } const char *uniform=""; int array[4]={0,0,0, 0}; - if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] )) + if(PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] )) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1121,7 +1125,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis PyObject *listPtr =0; float array_data[4] = {0.f,0.f,0.f,0.f}; - if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr)) + if(PyArg_ParseTuple(args, "sO:setUniformfv", &uniform, &listPtr)) { int loc = GetUniformLocation(uniform); if(loc != -1) @@ -1171,7 +1175,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis }break; default: { - PyErr_Format(PyExc_TypeError, "Invalid list size"); + PyErr_SetString(PyExc_TypeError, "shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. invalid list size"); return NULL; }break; } @@ -1181,7 +1185,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis return NULL; } -KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )") +KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 or list3 or list4) )") { if(mError) { Py_RETURN_NONE; @@ -1190,70 +1194,84 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 PyObject *listPtr =0; int array_data[4] = {0,0,0,0}; - if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr)) + if(!PyArg_ParseTuple(args, "sO:setUniformiv", &uniform, &listPtr)) + return NULL; + + int loc = GetUniformLocation(uniform); + + if(loc == -1) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value"); + return NULL; + } + + if(!PySequence_Check(listPtr)) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence"); + return NULL; + } + + unsigned int list_size = PySequence_Size(listPtr); + + for(unsigned int i=0; (i<list_size && i<4); i++) { - int loc = GetUniformLocation(uniform); - if(loc != -1) + PyObject *item = PySequence_GetItem(listPtr, i); + array_data[i] = PyInt_AsLong(item); + Py_DECREF(item); + } + + if(PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int"); + return NULL; + } + + /* Sanity checks done! */ + + switch(list_size) + { + case 2: { - if(PySequence_Check(listPtr)) - { - unsigned int list_size = PySequence_Size(listPtr); - - for(unsigned int i=0; (i<list_size && i<4); i++) - { - PyObject *item = PySequence_GetItem(listPtr, i); - array_data[i] = PyInt_AsLong(item); - Py_DECREF(item); - } - switch(list_size) - { - case 2: - { - int array2[2] = { array_data[0],array_data[1]}; + int array2[2] = { array_data[0],array_data[1]}; #ifdef SORT_UNIFORMS - SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2); + SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2); #else - SetUniform(loc, array2, 2); + SetUniform(loc, array2, 2); #endif - Py_RETURN_NONE; - } break; - case 3: - { - int array3[3] = { array_data[0],array_data[1],array_data[2] }; + Py_RETURN_NONE; + } break; + case 3: + { + int array3[3] = { array_data[0],array_data[1],array_data[2] }; #ifdef SORT_UNIFORMS - SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3); - + SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3); + #else - SetUniform(loc, array3, 3); + SetUniform(loc, array3, 3); #endif - Py_RETURN_NONE; - }break; - case 4: - { - int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] }; + Py_RETURN_NONE; + }break; + case 4: + { + int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] }; #ifdef SORT_UNIFORMS - SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4); - + SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4); + #else - SetUniform(loc, array4, 4); + SetUniform(loc, array4, 4); #endif - Py_RETURN_NONE; - }break; - default: - { - PyErr_Format(PyExc_TypeError, "Invalid list size"); - return NULL; - }break; - } - } - } + Py_RETURN_NONE; + }break; + default: + { + PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int list between 2 and 4"); + return NULL; + }break; } - return NULL; + + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, -"setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" ) +"setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)" ) { if(mError) { Py_RETURN_NONE; @@ -1269,33 +1287,38 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, const char *uniform=""; PyObject *matrix=0; int transp=1; // MT_ is row major so transpose by default.... - if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp)) - { - int loc = GetUniformLocation(uniform); - if(loc != -1) - { - if (PyObject_IsMT_Matrix(matrix, 4)) - { - MT_Matrix4x4 mat; - if (PyMatTo(matrix, mat)) - { + + if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4",&uniform, &matrix,&transp)) + return NULL; + + int loc = GetUniformLocation(uniform); + + if(loc == -1) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value"); + return NULL; + } + + MT_Matrix4x4 mat; + + if (!PyMatTo(matrix, mat)) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix"); + return NULL; + } + + /* Sanity checks done! */ + #ifdef SORT_UNIFORMS - mat.getValue(matr); - SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) ); + mat.getValue(matr); + SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) ); #else - SetUniform(loc,mat,(transp!=0)); + SetUniform(loc,mat,(transp!=0)); #endif - Py_RETURN_NONE; - } - } - } - } - return NULL; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3, -"setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" ) +"setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)" ) { if(mError) { Py_RETURN_NONE; @@ -1310,29 +1333,32 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3, const char *uniform=""; PyObject *matrix=0; int transp=1; // MT_ is row major so transpose by default.... - if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp)) - { - int loc = GetUniformLocation(uniform); - if(loc != -1) - { - if (PyObject_IsMT_Matrix(matrix, 3)) - { - MT_Matrix3x3 mat; - if (PyMatTo(matrix, mat)) - { + if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp)) + return NULL; + + int loc = GetUniformLocation(uniform); + + if(loc == -1) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value"); + return NULL; + } + + + MT_Matrix3x3 mat; + + if (!PyMatTo(matrix, mat)) { + PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix"); + return NULL; + } + + #ifdef SORT_UNIFORMS - mat.getValue(matr); - SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) ); + mat.getValue(matr); + SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) ); #else - SetUniform(loc,mat,(transp!=0)); + SetUniform(loc,mat,(transp!=0)); #endif - Py_RETURN_NONE; - - } - } - } - } - return NULL; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" ) @@ -1340,18 +1366,20 @@ KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" ) if(mError) { Py_RETURN_NONE; } + int attr=0; - if(PyArg_ParseTuple(args, "i", &attr )) { - if(mShader==0) { - PyErr_Format(PyExc_ValueError, "invalid shader object"); - return NULL; - } - mAttr=SHD_TANGENT; - glUseProgramObjectARB(mShader); - glBindAttribLocationARB(mShader, mAttr, "Tangent"); - Py_RETURN_NONE; + + if(!PyArg_ParseTuple(args, "i:setAttrib", &attr )) + return NULL; + + if(mShader==0) { + PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object"); + return NULL; } - return NULL; + mAttr=SHD_TANGENT; /* What the heck is going on here - attr is just ignored??? - Campbell */ + glUseProgramObjectARB(mShader); + glBindAttribLocationARB(mShader, mAttr, "Tangent"); + Py_RETURN_NONE; } @@ -1363,7 +1391,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) const char *uniform=""; int nloc=0; - if(PyArg_ParseTuple(args, "si",&uniform, &nloc)) + if(PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc)) { int loc = GetUniformLocation(uniform); if(loc != -1) diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 76acd5513ef..08cad5071fd 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -202,7 +202,8 @@ public: void SetUniform(int uniform, const int val); // Python interface - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_repr(void) { return PyString_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); } // ----------------------------------- KX_PYMETHOD_DOC( BL_Shader, setSource ); diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 58411f6d25e..73d7191ffde 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -25,17 +25,21 @@ # ***** END GPL LICENSE BLOCK ***** FILE(GLOB SRC *.cpp) -SET(SRC - ${SRC} - ../../../source/blender/python/api2_2x/Mathutils.c - ../../../source/blender/python/api2_2x/constant.c - ../../../source/blender/python/api2_2x/euler.c - ../../../source/blender/python/api2_2x/gen_utils.c - ../../../source/blender/python/api2_2x/matrix.c - ../../../source/blender/python/api2_2x/point.c - ../../../source/blender/python/api2_2x/quat.c - ../../../source/blender/python/api2_2x/vector.c -) + +#XXX disabled for 2.5 because of missing python +#SET(SRC +# ${SRC} +# ../../../source/blender/python/api2_2x/Mathutils.c +# ../../../source/blender/python/api2_2x/constant.c +# ../../../source/blender/python/api2_2x/euler.c +# ../../../source/blender/python/api2_2x/gen_utils.c +# ../../../source/blender/python/api2_2x/matrix.c +# ../../../source/blender/python/api2_2x/point.c +# ../../../source/blender/python/api2_2x/quat.c +# ../../../source/blender/python/api2_2x/vector.c +# ../../../source/blender/python/api2_2x/bpy_internal_import.c +# ../../../source/blender/python/api2_2x/BGL.c +#) SET(INC . @@ -66,7 +70,7 @@ SET(INC ../../../source/gameengine/Physics/Sumo ../../../source/gameengine/Physics/Sumo/Fuzzics/include ../../../source/gameengine/Network/LoopBackNetwork - ../../../intern/SoundSystem + ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader ../../../source/blender/gpu diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index 4e5f27df2da..2483a6bfb39 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -47,7 +47,7 @@ KX_NetworkMessageActuator::KX_NetworkMessageActuator( m_networkscene(networkscene), m_toPropName(toPropName), m_subject(subject), - m_bodyType(bodyType), + m_bPropBody(bodyType), m_body(body) { } @@ -69,7 +69,7 @@ bool KX_NetworkMessageActuator::Update() } //printf("messageactuator true event\n"); - if (m_bodyType == 1) // ACT_MESG_PROP in DNA_actuator_types.h + if (m_bPropBody) // ACT_MESG_PROP in DNA_actuator_types.h { m_networkscene->SendMessage( m_toPropName, @@ -105,22 +105,22 @@ CValue* KX_NetworkMessageActuator::GetReplica() /* Integration hooks -------------------------------------------------- */ PyTypeObject KX_NetworkMessageActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_NetworkMessageActuator", - sizeof(KX_NetworkMessageActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_NetworkMessageActuator::Parents[] = { @@ -132,6 +132,7 @@ PyParentObject KX_NetworkMessageActuator::Parents[] = { }; PyMethodDef KX_NetworkMessageActuator::Methods[] = { + // Deprecated -----> {"setToPropName", (PyCFunction) KX_NetworkMessageActuator::sPySetToPropName, METH_VARARGS}, {"setSubject", (PyCFunction) @@ -140,26 +141,36 @@ PyMethodDef KX_NetworkMessageActuator::Methods[] = { KX_NetworkMessageActuator::sPySetBodyType, METH_VARARGS}, {"setBody", (PyCFunction) KX_NetworkMessageActuator::sPySetBody, METH_VARARGS}, + // <----- {NULL,NULL} // Sentinel }; PyAttributeDef KX_NetworkMessageActuator::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW("propName", 0, 100, false, KX_NetworkMessageActuator, m_toPropName), + KX_PYATTRIBUTE_STRING_RW("subject", 0, 100, false, KX_NetworkMessageActuator, m_subject), + KX_PYATTRIBUTE_BOOL_RW("usePropBody", KX_NetworkMessageActuator, m_bPropBody), + KX_PYATTRIBUTE_STRING_RW("body", 0, 100, false, KX_NetworkMessageActuator, m_body), { NULL } //Sentinel }; -PyObject* KX_NetworkMessageActuator::_getattr(const char *attr) { - _getattr_up(SCA_IActuator); +PyObject* KX_NetworkMessageActuator::py_getattro(PyObject *attr) { + py_getattro_up(SCA_IActuator); } +int KX_NetworkMessageActuator::py_setattro(PyObject *attr, PyObject *value) { + py_setattro_up(SCA_IActuator); +} + +// Deprecated -----> // 1. SetToPropName PyObject* KX_NetworkMessageActuator::PySetToPropName( - PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setToProp()", "the propName property"); char* ToPropName; - if (PyArg_ParseTuple(args, "s", &ToPropName)) { + if (PyArg_ParseTuple(args, "s:setToPropName", &ToPropName)) { m_toPropName = ToPropName; } else { @@ -171,13 +182,13 @@ PyObject* KX_NetworkMessageActuator::PySetToPropName( // 2. SetSubject PyObject* KX_NetworkMessageActuator::PySetSubject( - PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setSubject()", "the subject property"); char* Subject; - if (PyArg_ParseTuple(args, "s", &Subject)) { + if (PyArg_ParseTuple(args, "s:setSubject", &Subject)) { m_subject = Subject; } else { @@ -189,14 +200,14 @@ PyObject* KX_NetworkMessageActuator::PySetSubject( // 3. SetBodyType PyObject* KX_NetworkMessageActuator::PySetBodyType( - PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBodyType()", "the usePropBody property"); int BodyType; - if (PyArg_ParseTuple(args, "i", &BodyType)) { - m_bodyType = BodyType; + if (PyArg_ParseTuple(args, "i:setBodyType", &BodyType)) { + m_bPropBody = (BodyType != 0); } else { return NULL; @@ -207,13 +218,13 @@ PyObject* KX_NetworkMessageActuator::PySetBodyType( // 4. SetBody PyObject* KX_NetworkMessageActuator::PySetBody( - PyObject* self, PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("setBody()", "the body property"); char* Body; - if (PyArg_ParseTuple(args, "s", &Body)) { + if (PyArg_ParseTuple(args, "s:setBody", &Body)) { m_body = Body; } else { @@ -223,3 +234,4 @@ PyObject* KX_NetworkMessageActuator::PySetBody( Py_RETURN_NONE; } +// <----- Deprecated
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index 96b55ef839b..850f825b8f3 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -41,7 +41,7 @@ class KX_NetworkMessageActuator : public SCA_IActuator class NG_NetworkScene* m_networkscene; // needed for replication STR_String m_toPropName; STR_String m_subject; - int m_bodyType; + bool m_bPropBody; STR_String m_body; public: KX_NetworkMessageActuator( @@ -61,12 +61,15 @@ public: /* Python interface ------------------------------------------- */ /* ------------------------------------------------------------ */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + // Deprecated -----> KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName); KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject); KX_PYMETHOD(KX_NetworkMessageActuator, SetBodyType); KX_PYMETHOD(KX_NetworkMessageActuator, SetBody); + // <----- }; diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index ac89d8b0716..7782567943e 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -168,22 +168,22 @@ bool KX_NetworkMessageSensor::IsPositiveTrigger() /* Integration hooks --------------------------------------------------- */ PyTypeObject KX_NetworkMessageSensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_NetworkMessageSensor", - sizeof(KX_NetworkMessageSensor), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_NetworkMessageSensor::Parents[] = { @@ -195,6 +195,7 @@ PyParentObject KX_NetworkMessageSensor::Parents[] = { }; PyMethodDef KX_NetworkMessageSensor::Methods[] = { + // Deprecated -----> {"setSubjectFilterText", (PyCFunction) KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O, (PY_METHODCHAR)SetSubjectFilterText_doc}, @@ -210,27 +211,58 @@ PyMethodDef KX_NetworkMessageSensor::Methods[] = { {"getSubjects", (PyCFunction) KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS, (PY_METHODCHAR)GetSubjects_doc}, + // <----- {NULL,NULL} //Sentinel }; PyAttributeDef KX_NetworkMessageSensor::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW("subject", 0, 100, false, KX_NetworkMessageSensor, m_subject), + KX_PYATTRIBUTE_INT_RO("frameMessageCount", KX_NetworkMessageSensor, m_frame_message_count), + KX_PYATTRIBUTE_RO_FUNCTION("bodies", KX_NetworkMessageSensor, pyattr_get_bodies), + KX_PYATTRIBUTE_RO_FUNCTION("subjects", KX_NetworkMessageSensor, pyattr_get_subjects), { NULL } //Sentinel }; -PyObject* KX_NetworkMessageSensor::_getattr(const char *attr) { - _getattr_up(SCA_ISensor); // implicit return! +PyObject* KX_NetworkMessageSensor::py_getattro(PyObject *attr) { + py_getattro_up(SCA_ISensor); } +int KX_NetworkMessageSensor::py_setattro(PyObject *attr, PyObject *value) { + return SCA_ISensor::py_setattro(attr, value); +} + +PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v); + if (self->m_BodyList) { + return self->m_BodyList->GetProxy(); + } else { + return (new CListValue())->NewProxy(true); + } +} + +PyObject* KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v); + if (self->m_SubjectList) { + return self->m_SubjectList->GetProxy(); + } else { + return (new CListValue())->NewProxy(true); + } +} + +// Deprecated -----> // 1. Set the message subject that this sensor listens for const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = "\tsetSubjectFilterText(value)\n" "\tChange the message subject text that this sensor is listening to.\n"; -PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value) +PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(PyObject* value) { + ShowDeprecationWarning("setSubjectFilterText()", "subject"); char* Subject = PyString_AsString(value); if (Subject==NULL) { - PyErr_SetString(PyExc_TypeError, "expected a string message"); + PyErr_SetString(PyExc_TypeError, "sensor.tsetSubjectFilterText(string): KX_NetworkMessageSensor, expected a string message"); return NULL; } @@ -243,8 +275,9 @@ const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = "\tgetFrameMessageCount()\n" "\tGet the number of messages received since the last frame.\n"; -PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount() { + ShowDeprecationWarning("getFrameMessageCount()", "frameMessageCount"); return PyInt_FromLong(long(m_frame_message_count)); } @@ -253,12 +286,13 @@ const char KX_NetworkMessageSensor::GetBodies_doc[] = "\tgetBodies()\n" "\tGet the list of message bodies.\n"; -PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetBodies() { + ShowDeprecationWarning("getBodies()", "bodies"); if (m_BodyList) { - return ((PyObject*) m_BodyList->AddRef()); + return m_BodyList->GetProxy(); } else { - return ((PyObject*) new CListValue()); + return (new CListValue())->NewProxy(true); } } @@ -267,8 +301,9 @@ const char KX_NetworkMessageSensor::GetSubject_doc[] = "\tgetSubject()\n" "\tGet the subject: field of the message sensor.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetSubject() { + ShowDeprecationWarning("getSubject()", "subject"); return PyString_FromString(m_subject ? m_subject : ""); } @@ -277,11 +312,13 @@ const char KX_NetworkMessageSensor::GetSubjects_doc[] = "\tgetSubjects()\n" "\tGet list of message subjects.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetSubjects() { + ShowDeprecationWarning("getSubjects()", "subjects"); if (m_SubjectList) { - return ((PyObject*) m_SubjectList->AddRef()); + return m_SubjectList->GetProxy(); } else { - return ((PyObject*) new CListValue()); + return (new CListValue())->NewProxy(true); } } +// <----- Deprecated
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 26adbc9945a..ac0e880d25c 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -72,14 +72,20 @@ public: /* Python interface -------------------------------------------- */ /* ------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + // Deprecated -----> KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetBodies); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubject); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubjects); + // <----- + /* attributes */ + static PyObject* pyattr_get_bodies(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_subjects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript index 2476ed1f275..b417edf6413 100644 --- a/source/gameengine/Ketsji/KXNetwork/SConscript +++ b/source/gameengine/Ketsji/KXNetwork/SConscript @@ -15,4 +15,4 @@ if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/O2') -env.BlenderLib ( 'kx_network', Split(sources), Split(incs), defines=[],libtype=['game2', 'player'], priority=[5, 155], cxx_compileflags=cxxflags ) +env.BlenderLib ( 'kx_network', Split(sources), Split(incs), defines=[],libtype=['core', 'player'], priority=[400, 145], cxx_compileflags=cxxflags ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index b9bd7647f89..849332008ce 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -753,36 +753,40 @@ PyAttributeDef KX_BlenderMaterial::Attributes[] = { }; PyTypeObject KX_BlenderMaterial::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_BlenderMaterial", - sizeof(KX_BlenderMaterial), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, 0, - __repr, - 0 + 0, + 0, + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_BlenderMaterial::Parents[] = { - &PyObjectPlus::Type, &KX_BlenderMaterial::Type, + &PyObjectPlus::Type, NULL }; -PyObject* KX_BlenderMaterial::_getattr(const char *attr) +PyObject* KX_BlenderMaterial::py_getattro(PyObject *attr) { - _getattr_up(PyObjectPlus); + py_getattro_up(PyObjectPlus); } -int KX_BlenderMaterial::_setattr(const char *attr, PyObject *pyvalue) +int KX_BlenderMaterial::py_setattro(PyObject *attr, PyObject *pyvalue) { - return PyObjectPlus::_setattr(attr, pyvalue); + return PyObjectPlus::py_setattro(attr, pyvalue); } @@ -823,8 +827,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") m_flag &= ~RAS_BLENDERGLSL; mMaterial->SetSharedMaterial(true); mScene->GetBucketManager()->ReleaseDisplayLists(this); - Py_INCREF(mShader); - return mShader; + return mShader->GetProxy(); }else { // decref all references to the object @@ -832,18 +835,13 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") // We will then go back to fixed functionality // for this material if(mShader) { - if(mShader->ob_refcnt > 1) { - Py_DECREF(mShader); - } - else { - delete mShader; - mShader=0; - } + delete mShader; /* will handle python de-referencing */ + mShader=0; } } Py_RETURN_NONE; } - PyErr_Format(PyExc_ValueError, "GLSL Error"); + PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error"); return NULL; } @@ -893,7 +891,7 @@ static unsigned int GL_array[11] = { KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.src, GameLogic.dest)") { unsigned int b[2]; - if(PyArg_ParseTuple(args, "ii", &b[0], &b[1])) + if(PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1])) { bool value_found[2] = {false, false}; for(int i=0; i<11; i++) @@ -909,7 +907,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.sr if(value_found[0] && value_found[1]) break; } if(!value_found[0] || !value_found[1]) { - PyErr_Format(PyExc_ValueError, "invalid enum."); + PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum."); return NULL; } mUserDefBlend = true; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 2cf623dbd85..48d4730ab07 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -82,8 +82,9 @@ public: ); // -------------------------------- - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); } KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 062e9f7df50..831f9241fec 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -59,6 +59,24 @@ void KX_BulletPhysicsController::applyImpulse(const MT_Point3& attach, const MT_ } +float KX_BulletPhysicsController::GetLinVelocityMin() +{ + return (float)CcdPhysicsController::GetLinVelocityMin(); +} +void KX_BulletPhysicsController::SetLinVelocityMin(float val) +{ + CcdPhysicsController::SetLinVelocityMin(val); +} + +float KX_BulletPhysicsController::GetLinVelocityMax() +{ + return (float)CcdPhysicsController::GetLinVelocityMax(); +} +void KX_BulletPhysicsController::SetLinVelocityMax(float val) +{ + CcdPhysicsController::SetLinVelocityMax(val); +} + void KX_BulletPhysicsController::SetObject (SG_IObject* object) { SG_Controller::SetObject(object); @@ -73,6 +91,10 @@ void KX_BulletPhysicsController::SetObject (SG_IObject* object) } +MT_Scalar KX_BulletPhysicsController::GetRadius() +{ + return MT_Scalar(CcdPhysicsController::GetRadius()); +} void KX_BulletPhysicsController::setMargin (float collisionMargin) { @@ -162,9 +184,18 @@ MT_Scalar KX_BulletPhysicsController::GetMass() } -MT_Scalar KX_BulletPhysicsController::GetRadius() +MT_Vector3 KX_BulletPhysicsController::GetLocalInertia() { - return MT_Scalar(CcdPhysicsController::GetRadius()); + MT_Vector3 inertia(0.f, 0.f, 0.f); + btVector3 inv_inertia; + if (GetRigidBody()) { + inv_inertia = GetRigidBody()->getInvInertiaDiagLocal(); + if (!btFuzzyZero(inv_inertia.getX()) && + !btFuzzyZero(inv_inertia.getY()) && + !btFuzzyZero(inv_inertia.getZ())) + inertia = MT_Vector3(1.f/inv_inertia.getX(), 1.f/inv_inertia.getY(), 1.f/inv_inertia.getZ()); + } + return inertia; } MT_Vector3 KX_BulletPhysicsController::getReactionForce() @@ -417,13 +448,14 @@ void KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly) { if (!nondynaonly) { + /* btTransform worldTrans; if (GetRigidBody()) { GetRigidBody()->getMotionState()->getWorldTransform(worldTrans); GetRigidBody()->setCenterOfMassTransform(worldTrans); } - + */ /* scaling? if (m_bDyna) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 44fbde7054e..b39098206f7 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -42,6 +42,7 @@ public: virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); virtual void SetMass(MT_Scalar newmass); + virtual MT_Vector3 GetLocalInertia(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); virtual void AddCompoundChild(KX_IPhysicsController* child); @@ -55,7 +56,11 @@ public: virtual SG_Controller* GetReplica(class SG_Node* destnode); virtual MT_Scalar GetRadius(); - + + virtual float GetLinVelocityMin(); + virtual void SetLinVelocityMin(float val); + virtual float GetLinVelocityMax(); + virtual void SetLinVelocityMax(float val); virtual void SetSumoTransform(bool nondynaonly); // todo: remove next line ! diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index ef7883910fd..121d4512265 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -98,7 +98,7 @@ bool KX_CDActuator::Update() SND_CDObject::Instance()->SetPlaymode(SND_CD_ALL); SND_CDObject::Instance()->SetTrack(1); SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); - result = true; + //result = true; break; } case KX_CDACT_PLAY_TRACK: @@ -106,7 +106,7 @@ bool KX_CDActuator::Update() SND_CDObject::Instance()->SetPlaymode(SND_CD_TRACK); SND_CDObject::Instance()->SetTrack(m_track); SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); - result = true; + //result = true; break; } case KX_CDACT_LOOP_TRACK: @@ -114,7 +114,7 @@ bool KX_CDActuator::Update() SND_CDObject::Instance()->SetPlaymode(SND_CD_ALL); SND_CDObject::Instance()->SetTrack(m_track); SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); - result = true; + //result = true; break; } case KX_CDACT_STOP: @@ -125,19 +125,19 @@ bool KX_CDActuator::Update() case KX_CDACT_PAUSE: { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PAUSE); - result = true; + //result = true; break; } case KX_CDACT_RESUME: { SND_CDObject::Instance()->SetPlaystate(SND_MUST_RESUME); - result = true; + //result = true; break; } case KX_CDACT_VOLUME: { SND_CDObject::Instance()->SetGain(m_gain); - result = true; + //result = true; break; } default: @@ -158,22 +158,22 @@ bool KX_CDActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_CDActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_SoundActuator", - sizeof(KX_CDActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -189,54 +189,111 @@ PyParentObject KX_CDActuator::Parents[] = { PyMethodDef KX_CDActuator::Methods[] = { - {"startCD",(PyCFunction) KX_CDActuator::sPyStartCD,METH_VARARGS,NULL}, - {"pauseCD",(PyCFunction) KX_CDActuator::sPyPauseCD,METH_VARARGS,NULL}, - {"stopCD",(PyCFunction) KX_CDActuator::sPyStopCD,METH_VARARGS,NULL}, + // Deprecated -----> {"setGain",(PyCFunction) KX_CDActuator::sPySetGain,METH_VARARGS,NULL}, {"getGain",(PyCFunction) KX_CDActuator::sPyGetGain,METH_VARARGS,NULL}, + // <----- + KX_PYMETHODTABLE_NOARGS(KX_CDActuator, startCD), + KX_PYMETHODTABLE_NOARGS(KX_CDActuator, pauseCD), + KX_PYMETHODTABLE_NOARGS(KX_CDActuator, resumeCD), + KX_PYMETHODTABLE_NOARGS(KX_CDActuator, stopCD), + KX_PYMETHODTABLE_NOARGS(KX_CDActuator, playAll), + KX_PYMETHODTABLE_O(KX_CDActuator, playTrack), {NULL,NULL,NULL,NULL} //Sentinel }; PyAttributeDef KX_CDActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW_CHECK("volume", 0.0, 1.0, KX_CDActuator, m_gain,pyattr_setGain), + KX_PYATTRIBUTE_INT_RW("track", 1, 99, false, KX_CDActuator, m_track), { NULL } //Sentinel }; -PyObject* KX_CDActuator::_getattr(const char *attr) +int KX_CDActuator::pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { - _getattr_up(SCA_IActuator); + KX_CDActuator* act = static_cast<KX_CDActuator*>(self); + SND_CDObject::Instance()->SetGain(act->m_gain); + return 0; } +PyObject* KX_CDActuator::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_IActuator); +} + +int KX_CDActuator::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_IActuator); +} -PyObject* KX_CDActuator::PyStartCD(PyObject* self, PyObject* args, PyObject* kwds) +KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, startCD, +"startCD()\n" +"\tStarts the CD playing.\n") { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); Py_RETURN_NONE; } - -PyObject* KX_CDActuator::PyPauseCD(PyObject* self, PyObject* args, PyObject* kwds) +KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, pauseCD, +"pauseCD()\n" +"\tPauses the CD playing.\n") { SND_CDObject::Instance()->SetPlaystate(SND_MUST_PAUSE); Py_RETURN_NONE; } +KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, resumeCD, +"resumeCD()\n" +"\tResumes the CD playing.\n") +{ + SND_CDObject::Instance()->SetPlaystate(SND_MUST_RESUME); + Py_RETURN_NONE; +} + -PyObject* KX_CDActuator::PyStopCD(PyObject* self, PyObject* args, PyObject* kwds) +KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, stopCD, +"stopCD()\n" +"\tStops the CD playing.\n") { SND_CDObject::Instance()->SetPlaystate(SND_MUST_STOP); Py_RETURN_NONE; } +KX_PYMETHODDEF_DOC_O(KX_CDActuator, playTrack, +"playTrack(trackNumber)\n" +"\tPlays the track selected.\n") +{ + if (PyInt_Check(value)) { + int track = PyInt_AsLong(value); + SND_CDObject::Instance()->SetPlaymode(SND_CD_TRACK); + SND_CDObject::Instance()->SetTrack(track); + SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); + } + Py_RETURN_NONE; +} + + + +KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, playAll, +"playAll()\n" +"\tPlays the CD from the beginning.\n") +{ + SND_CDObject::Instance()->SetPlaymode(SND_CD_ALL); + SND_CDObject::Instance()->SetTrack(1); + SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); + Py_RETURN_NONE; +} -PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds) +// Deprecated -----> +PyObject* KX_CDActuator::PySetGain(PyObject* args) { float gain = 1.0; - if (!PyArg_ParseTuple(args, "f", &gain)) + ShowDeprecationWarning("setGain()", "the volume property"); + if (!PyArg_ParseTuple(args, "f:setGain", &gain)) return NULL; SND_CDObject::Instance()->SetGain(gain); @@ -246,10 +303,12 @@ PyObject* KX_CDActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwd -PyObject* KX_CDActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_CDActuator::PyGetGain(PyObject* args) { float gain = SND_CDObject::Instance()->GetGain(); + ShowDeprecationWarning("getGain()", "the volume property"); PyObject* result = PyFloat_FromDouble(gain); return result; } +// <----- diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h index 393c49083f9..b674755e59f 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.h +++ b/source/gameengine/Ketsji/KX_CDActuator.h @@ -81,13 +81,24 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + + // Deprecated -----> + KX_PYMETHOD_VARARGS(KX_CDActuator,SetGain); + KX_PYMETHOD_VARARGS(KX_CDActuator,GetGain); + // <----- + + KX_PYMETHOD_DOC_NOARGS(KX_CDActuator, startCD); + KX_PYMETHOD_DOC_NOARGS(KX_CDActuator, pauseCD); + KX_PYMETHOD_DOC_NOARGS(KX_CDActuator, resumeCD); + KX_PYMETHOD_DOC_NOARGS(KX_CDActuator, stopCD); + KX_PYMETHOD_DOC_NOARGS(KX_CDActuator, playAll); + KX_PYMETHOD_DOC_O(KX_CDActuator, playTrack); + + static int pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + - KX_PYMETHOD(KX_CDActuator,StartCD); - KX_PYMETHOD(KX_CDActuator,PauseCD); - KX_PYMETHOD(KX_CDActuator,StopCD); - KX_PYMETHOD(KX_CDActuator,SetGain); - KX_PYMETHOD(KX_CDActuator,GetGain); }; #endif //__KX_CDACTUATOR diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 5caac2fc670..c8575424751 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -484,56 +484,53 @@ PyMethodDef KX_Camera::Methods[] = { }; PyAttributeDef KX_Camera::Attributes[] = { + + KX_PYATTRIBUTE_BOOL_RW("frustum_culling", KX_Camera, m_frustum_culling), + KX_PYATTRIBUTE_RW_FUNCTION("perspective", KX_Camera, pyattr_get_perspective, pyattr_set_perspective), + + KX_PYATTRIBUTE_RW_FUNCTION("lens", KX_Camera, pyattr_get_lens, pyattr_set_lens), + KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near), + KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far), + + KX_PYATTRIBUTE_RO_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix), + KX_PYATTRIBUTE_RO_FUNCTION("modelview_matrix", KX_Camera, pyattr_get_modelview_matrix), + KX_PYATTRIBUTE_RO_FUNCTION("camera_to_world", KX_Camera, pyattr_get_camera_to_world), + KX_PYATTRIBUTE_RO_FUNCTION("world_to_camera", KX_Camera, pyattr_get_world_to_camera), + + /* Grrr, functions for constants? */ + KX_PYATTRIBUTE_RO_FUNCTION("INSIDE", KX_Camera, pyattr_get_INSIDE), + KX_PYATTRIBUTE_RO_FUNCTION("OUTSIDE", KX_Camera, pyattr_get_OUTSIDE), + KX_PYATTRIBUTE_RO_FUNCTION("INTERSECT", KX_Camera, pyattr_get_INTERSECT), + { NULL } //Sentinel }; -char KX_Camera::doc[] = "Module KX_Camera\n\n" -"Constants:\n" -"\tINSIDE\n" -"\tINTERSECT\n" -"\tOUTSIDE\n" -"Attributes:\n" -"\tlens -> float\n" -"\t\tThe camera's lens value\n" -"\tnear -> float\n" -"\t\tThe camera's near clip distance\n" -"\tfar -> float\n" -"\t\tThe camera's far clip distance\n" -"\tfrustum_culling -> bool\n" -"\t\tNon zero if this camera is frustum culling.\n" -"\tprojection_matrix -> [[float]]\n" -"\t\tThis camera's projection matrix.\n" -"\tmodelview_matrix -> [[float]] (read only)\n" -"\t\tThis camera's model view matrix.\n" -"\t\tRegenerated every frame from the camera's position and orientation.\n" -"\tcamera_to_world -> [[float]] (read only)\n" -"\t\tThis camera's camera to world transform.\n" -"\t\tRegenerated every frame from the camera's position and orientation.\n" -"\tworld_to_camera -> [[float]] (read only)\n" -"\t\tThis camera's world to camera transform.\n" -"\t\tRegenerated every frame from the camera's position and orientation.\n" -"\t\tThis is camera_to_world inverted.\n"; - PyTypeObject KX_Camera::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_Camera", - sizeof(KX_Camera), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - doc + py_base_repr, + 0,0, + &KX_GameObject::Mapping, + 0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; + + + + + PyParentObject KX_Camera::Parents[] = { &KX_Camera::Type, &KX_GameObject::Type, @@ -542,90 +539,14 @@ PyParentObject KX_Camera::Parents[] = { NULL }; -PyObject* KX_Camera::_getattr(const char *attr) -{ - if (!strcmp(attr, "INSIDE")) - return PyInt_FromLong(INSIDE); /* new ref */ - if (!strcmp(attr, "OUTSIDE")) - return PyInt_FromLong(OUTSIDE); /* new ref */ - if (!strcmp(attr, "INTERSECT")) - return PyInt_FromLong(INTERSECT); /* new ref */ - - if (!strcmp(attr, "lens")) - return PyFloat_FromDouble(GetLens()); /* new ref */ - if (!strcmp(attr, "near")) - return PyFloat_FromDouble(GetCameraNear()); /* new ref */ - if (!strcmp(attr, "far")) - return PyFloat_FromDouble(GetCameraFar()); /* new ref */ - if (!strcmp(attr, "frustum_culling")) - return PyInt_FromLong(m_frustum_culling); /* new ref */ - if (!strcmp(attr, "perspective")) - return PyInt_FromLong(m_camdata.m_perspective); /* new ref */ - if (!strcmp(attr, "projection_matrix")) - return PyObjectFrom(GetProjectionMatrix()); /* new ref */ - if (!strcmp(attr, "modelview_matrix")) - return PyObjectFrom(GetModelviewMatrix()); /* new ref */ - if (!strcmp(attr, "camera_to_world")) - return PyObjectFrom(GetCameraToWorld()); /* new ref */ - if (!strcmp(attr, "world_to_camera")) - return PyObjectFrom(GetWorldToCamera()); /* new ref */ - - _getattr_up(KX_GameObject); -} - -int KX_Camera::_setattr(const char *attr, PyObject *pyvalue) -{ - if (PyInt_Check(pyvalue)) - { - if (!strcmp(attr, "frustum_culling")) - { - m_frustum_culling = PyInt_AsLong(pyvalue); - return 0; - } - - if (!strcmp(attr, "perspective")) - { - m_camdata.m_perspective = PyInt_AsLong(pyvalue); - return 0; - } - } - - if (PyFloat_Check(pyvalue)) - { - if (!strcmp(attr, "lens")) - { - m_camdata.m_lens = PyFloat_AsDouble(pyvalue); - m_set_projection_matrix = false; - return 0; - } - if (!strcmp(attr, "near")) - { - m_camdata.m_clipstart = PyFloat_AsDouble(pyvalue); - m_set_projection_matrix = false; - return 0; - } - if (!strcmp(attr, "far")) - { - m_camdata.m_clipend = PyFloat_AsDouble(pyvalue); - m_set_projection_matrix = false; - return 0; - } - } - - if (PyObject_IsMT_Matrix(pyvalue, 4)) - { - if (!strcmp(attr, "projection_matrix")) - { - MT_Matrix4x4 mat; - if (PyMatTo(pyvalue, mat)) - { - SetProjectionMatrix(mat); - return 0; - } - return 1; - } - } - return KX_GameObject::_setattr(attr, pyvalue); +PyObject* KX_Camera::py_getattro(PyObject *attr) +{ + py_getattro_up(KX_GameObject); +} + +int KX_Camera::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(KX_GameObject); } KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, @@ -648,7 +569,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, { PyObject *pycenter; float radius; - if (PyArg_ParseTuple(args, "Of", &pycenter, &radius)) + if (PyArg_ParseTuple(args, "Of:sphereInsideFrustum", &pycenter, &radius)) { MT_Point3 center; if (PyVecTo(pycenter, center)) @@ -657,7 +578,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, } } - PyErr_SetString(PyExc_TypeError, "sphereInsideFrustum: Expected arguments: (center, radius)"); + PyErr_SetString(PyExc_TypeError, "camera.sphereInsideFrustum(center, radius): KX_Camera, expected arguments: (center, radius)"); return NULL; } @@ -690,7 +611,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, unsigned int num_points = PySequence_Size(value); if (num_points != 8) { - PyErr_Format(PyExc_TypeError, "boxInsideFrustum: Expected eight (8) points, got %d", num_points); + PyErr_Format(PyExc_TypeError, "camera.boxInsideFrustum(box): KX_Camera, expected eight (8) points, got %d", num_points); return NULL; } @@ -729,7 +650,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */ } - PyErr_SetString(PyExc_TypeError, "pointInsideFrustum: Expected point argument."); + PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); return NULL; } @@ -805,7 +726,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, setProjectionMatrix, MT_Matrix4x4 mat; if (!PyMatTo(value, mat)) { - PyErr_SetString(PyExc_TypeError, "setProjectionMatrix: Expected 4x4 list as matrix argument."); + PyErr_SetString(PyExc_TypeError, "camera.setProjectionMatrix(matrix): KX_Camera, expected 4x4 list as matrix argument."); return NULL; } @@ -821,7 +742,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, enableViewport, int viewport = PyObject_IsTrue(value); if (viewport == -1) { - PyErr_SetString(PyExc_ValueError, "expected True/False or 0/1"); + PyErr_SetString(PyExc_ValueError, "camera.enableViewport(bool): KX_Camera, expected True/False or 0/1"); return NULL; } @@ -856,3 +777,126 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, scene->SetCameraOnTop(this); Py_RETURN_NONE; } + +PyObject* KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyBool_FromLong(self->m_camdata.m_perspective); +} + +int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + int param = PyObject_IsTrue( value ); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1"); + return -1; + } + + self->m_camdata.m_perspective= param; + return 0; +} + +PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyFloat_FromDouble(self->m_camdata.m_lens); +} + +int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + float param = PyFloat_AsDouble(value); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero"); + return -1; + } + + self->m_camdata.m_lens= param; + self->m_set_projection_matrix = false; + return 0; +} + +PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyFloat_FromDouble(self->m_camdata.m_clipstart); +} + +int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + float param = PyFloat_AsDouble(value); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero"); + return -1; + } + + self->m_camdata.m_clipstart= param; + self->m_set_projection_matrix = false; + return 0; +} + +PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyFloat_FromDouble(self->m_camdata.m_clipend); +} + +int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + float param = PyFloat_AsDouble(value); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero"); + return -1; + } + + self->m_camdata.m_clipend= param; + self->m_set_projection_matrix = false; + return 0; +} + +PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyObjectFrom(self->GetProjectionMatrix()); +} + +int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + MT_Matrix4x4 mat; + if (!PyMatTo(value, mat)) + return -1; + + self->SetProjectionMatrix(mat); + return 0; +} + +PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyObjectFrom(self->GetModelviewMatrix()); +} + +PyObject* KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyObjectFrom(self->GetCameraToWorld()); +} + +PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyObjectFrom(self->GetWorldToCamera()); +} + + +PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ return PyInt_FromLong(INSIDE); } +PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ return PyInt_FromLong(OUTSIDE); } +PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ return PyInt_FromLong(INTERSECT); } + diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index efd18f99390..4accd4bc2f1 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -45,6 +45,7 @@ class KX_Camera : public KX_GameObject { Py_Header; protected: + friend class KX_Scene; /** Camera parameters (clips distances, focal lenght). These * params are closely tied to Blender. In the gameengine, only the * projection and modelview matrices are relevant. There's a @@ -67,6 +68,7 @@ protected: * Storage for the projection matrix that is passed to the * rasterizer. */ MT_Matrix4x4 m_projection_matrix; + //MT_Matrix4x4 m_projection_matrix1; /** * Storage for the modelview matrix that is passed to the @@ -108,11 +110,6 @@ protected: bool m_set_frustum_center; /** - * Python module doc string. - */ - static char doc[]; - - /** * Extracts the camera clip frames from the projection and world-to-camera matrices. */ void ExtractClipPlanes(); @@ -124,6 +121,16 @@ protected: * Extracts the bound sphere of the view frustum. */ void ExtractFrustumSphere(); + /** + * return the clip plane + */ + MT_Vector4 *GetNormalizedClipPlanes() + { + ExtractClipPlanes(); + NormalizeClipPlanes(); + return m_planes; + } + public: enum { INSIDE, INTERSECT, OUTSIDE } ; @@ -270,9 +277,29 @@ public: KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); - virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ - virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ + virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + + static PyObject* pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + + static PyObject* pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + + static PyObject* pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + static PyObject* pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; #endif //__KX_CAMERA diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 65f3aea12f9..8ef9f318142 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -33,10 +33,10 @@ #include "KX_CameraActuator.h" #include <iostream> #include <math.h> +#include <float.h> #include "KX_GameObject.h" #include "PyObjectPlus.h" -#include "blendef.h" STR_String KX_CameraActuator::X_AXIS_STRING = "x"; STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; @@ -371,22 +371,22 @@ bool KX_CameraActuator::string2axischoice(const char *axisString) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_CameraActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_CameraActuator", - sizeof(KX_CameraActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_CameraActuator::Parents[] = { @@ -408,56 +408,25 @@ PyMethodDef KX_CameraActuator::Methods[] = { {"setHeight",(PyCFunction) KX_CameraActuator::sPySetHeight, METH_VARARGS, (PY_METHODCHAR)SetHeight_doc}, {"getHeight",(PyCFunction) KX_CameraActuator::sPyGetHeight, METH_NOARGS, (PY_METHODCHAR)GetHeight_doc}, {"setXY" ,(PyCFunction) KX_CameraActuator::sPySetXY, METH_VARARGS, (PY_METHODCHAR)SetXY_doc}, - {"getXY" ,(PyCFunction) KX_CameraActuator::sPyGetXY, METH_VARARGS, (PY_METHODCHAR)GetXY_doc}, + {"getXY" ,(PyCFunction) KX_CameraActuator::sPyGetXY, METH_NOARGS, (PY_METHODCHAR)GetXY_doc}, {NULL,NULL,NULL,NULL} //Sentinel }; PyAttributeDef KX_CameraActuator::Attributes[] = { - KX_PYATTRIBUTE_FLOAT_RW("min",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_minHeight), - KX_PYATTRIBUTE_FLOAT_RW("max",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_maxHeight), - KX_PYATTRIBUTE_FLOAT_RW("height",-MAXFLOAT,MAXFLOAT,KX_CameraActuator,m_height), + KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_minHeight), + KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_maxHeight), + KX_PYATTRIBUTE_FLOAT_RW("height",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_height), KX_PYATTRIBUTE_BOOL_RW("xy",KX_CameraActuator,m_x), + KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), {NULL} }; -PyObject* KX_CameraActuator::_getattr(const char *attr) { - PyObject* object; - - if (!strcmp(attr, "object")) { - if (!m_ob) Py_RETURN_NONE; - else return m_ob->AddRef(); - } - - object = _getattr_self(Attributes, this, attr); - if (object != NULL) - return object; - _getattr_up(SCA_IActuator); +PyObject* KX_CameraActuator::py_getattro(PyObject *attr) { + py_getattro_up(SCA_IActuator); } -int KX_CameraActuator::_setattr(const char *attr, PyObject* value) { - int ret; - - if (!strcmp(attr, "object")) { - KX_GameObject *gameobj; - - if (!ConvertPythonToGameObject(value, &gameobj, true)) - return 1; // ConvertPythonToGameObject sets the error - - if (m_ob != NULL) - m_ob->UnregisterActuator(this); - - m_ob = (SCA_IObject*)gameobj; - - if (m_ob) - m_ob->RegisterActuator(this); - - return 0; - } - - ret = _setattr_self(Attributes, this, attr, value); - if (ret >= 0) - return ret; - return SCA_IActuator::_setattr(attr, value); +int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) { + py_setattro_up(SCA_IActuator); } /* get obj ---------------------------------------------------------- */ @@ -465,13 +434,13 @@ const char KX_CameraActuator::GetObject_doc[] = "getObject(name_only = 1)\n" "name_only - optional arg, when true will return the KX_GameObject rather then its name\n" "\tReturns the object this sensor reacts to.\n"; -PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args) +PyObject* KX_CameraActuator::PyGetObject(PyObject* args) { int ret_name_only = 1; ShowDeprecationWarning("getObject()", "the object property"); - if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) + if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only)) return NULL; if (!m_ob) @@ -480,20 +449,20 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_ob->GetName()); else - return m_ob->AddRef(); + return m_ob->GetProxy(); } /* set obj ---------------------------------------------------------- */ const char KX_CameraActuator::SetObject_doc[] = "setObject(object)\n" "\t- object: KX_GameObject, string or None\n" "\tSets the object this sensor reacts to.\n"; -PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value) +PyObject* KX_CameraActuator::PySetObject(PyObject* value) { KX_GameObject *gameobj; ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_CameraActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_ob != NULL) @@ -510,9 +479,7 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value) const char KX_CameraActuator::GetMin_doc[] = "getMin\n" "\tReturns the minimum value set in the Min: field.\n"; -PyObject* KX_CameraActuator::PyGetMin(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PyGetMin() { ShowDeprecationWarning("getMin()", "the min property"); return PyFloat_FromDouble(m_minHeight); @@ -521,13 +488,11 @@ PyObject* KX_CameraActuator::PyGetMin(PyObject* self, const char KX_CameraActuator::SetMin_doc[] = "setMin\n" "\tSets the minimum value.\n"; -PyObject* KX_CameraActuator::PySetMin(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PySetMin(PyObject* args) { ShowDeprecationWarning("setMin()", "the min property"); float min; - if(PyArg_ParseTuple(args,"f", &min)) + if(PyArg_ParseTuple(args,"f:setMin", &min)) { m_minHeight = min; Py_RETURN_NONE; @@ -538,9 +503,7 @@ PyObject* KX_CameraActuator::PySetMin(PyObject* self, const char KX_CameraActuator::GetMax_doc[] = "getMax\n" "\tReturns the maximum value set in the Max: field.\n"; -PyObject* KX_CameraActuator::PyGetMax(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PyGetMax() { ShowDeprecationWarning("getMax()", "the max property"); return PyFloat_FromDouble(m_maxHeight); @@ -549,13 +512,11 @@ PyObject* KX_CameraActuator::PyGetMax(PyObject* self, const char KX_CameraActuator::SetMax_doc[] = "setMax\n" "\tSets the maximum value.\n"; -PyObject* KX_CameraActuator::PySetMax(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PySetMax(PyObject* args) { ShowDeprecationWarning("getMax()", "the max property"); float max; - if(PyArg_ParseTuple(args,"f", &max)) + if(PyArg_ParseTuple(args,"f:setMax", &max)) { m_maxHeight = max; Py_RETURN_NONE; @@ -566,9 +527,7 @@ PyObject* KX_CameraActuator::PySetMax(PyObject* self, const char KX_CameraActuator::GetHeight_doc[] = "getHeight\n" "\tReturns the height value set in the height: field.\n"; -PyObject* KX_CameraActuator::PyGetHeight(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PyGetHeight() { ShowDeprecationWarning("getHeight()", "the height property"); return PyFloat_FromDouble(m_height); @@ -577,13 +536,11 @@ PyObject* KX_CameraActuator::PyGetHeight(PyObject* self, const char KX_CameraActuator::SetHeight_doc[] = "setHeight\n" "\tSets the height value.\n"; -PyObject* KX_CameraActuator::PySetHeight(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PySetHeight(PyObject* args) { ShowDeprecationWarning("getHeight()", "the height property"); float height; - if(PyArg_ParseTuple(args,"f", &height)) + if(PyArg_ParseTuple(args,"f:setHeight", &height)) { m_height = height; Py_RETURN_NONE; @@ -595,13 +552,11 @@ const char KX_CameraActuator::SetXY_doc[] = "setXY\n" "\tSets axis the camera tries to get behind.\n" "\t1=x, 0=y\n"; -PyObject* KX_CameraActuator::PySetXY(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PySetXY(PyObject* args) { ShowDeprecationWarning("setXY()", "the xy property"); int value; - if(PyArg_ParseTuple(args,"i", &value)) + if(PyArg_ParseTuple(args,"i:setXY", &value)) { m_x = value != 0; Py_RETURN_NONE; @@ -614,12 +569,36 @@ const char KX_CameraActuator::GetXY_doc[] = "getXY\n" "\tGets the axis the camera tries to get behind.\n" "\tTrue = X, False = Y\n"; -PyObject* KX_CameraActuator::PyGetXY(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_CameraActuator::PyGetXY() { ShowDeprecationWarning("getXY()", "the xy property"); return PyInt_FromLong(m_x); } +PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v); + if (self->m_ob==NULL) + Py_RETURN_NONE; + else + return self->m_ob->GetProxy(); +} + +int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v); + KX_GameObject *gameobj; + + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_CameraActuator")) + return 1; // ConvertPythonToGameObject sets the error + + if (self->m_ob) + self->m_ob->UnregisterActuator(self); + + if ((self->m_ob = (SCA_IObject*)gameobj)) + self->m_ob->RegisterActuator(self); + + return 0; +} + /* eof */ diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index 3b08536fc21..9298e1e868d 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -120,21 +120,24 @@ private : /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject* value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); /* set object to look at */ KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject); /* get current object */ KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,GetObject); - KX_PYMETHOD_DOC(KX_CameraActuator,SetMin); - KX_PYMETHOD_DOC(KX_CameraActuator,GetMin); - KX_PYMETHOD_DOC(KX_CameraActuator,SetMax); - KX_PYMETHOD_DOC(KX_CameraActuator,GetMax); - KX_PYMETHOD_DOC(KX_CameraActuator,SetHeight); - KX_PYMETHOD_DOC(KX_CameraActuator,GetHeight); - KX_PYMETHOD_DOC(KX_CameraActuator,SetXY); - KX_PYMETHOD_DOC(KX_CameraActuator,GetXY); + KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetMin); + KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetMin); + KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetMax); + KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetMax); + KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetHeight); + KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetHeight); + KX_PYMETHOD_DOC_VARARGS(KX_CameraActuator,SetXY); + KX_PYMETHOD_DOC_NOARGS(KX_CameraActuator,GetXY); + + static PyObject* pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); }; diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index fba9544d702..c2b4db2de8e 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -57,19 +57,21 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj, char *property, PyTypeObject* T) : SCA_IActuator(gameobj, T), - m_refDirection(refDir), + m_refDirVector(refDir), m_currentTime(0) { + m_refDirection[0] = refDir[0]; + m_refDirection[1] = refDir[1]; + m_refDirection[2] = refDir[2]; m_posDampTime = posDampTime; m_rotDampTime = rotDampTime; m_locrot = locrotxyz; m_option = option; m_activeTime = time; if (property) { - strncpy(m_property, property, sizeof(m_property)); - m_property[sizeof(m_property)-1] = 0; + m_property = property; } else { - m_property[0] = 0; + m_property = ""; } /* The units of bounds are determined by the type of constraint. To */ /* make the constraint application easier and more transparent later on, */ @@ -80,13 +82,16 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj, case KX_ACT_CONSTRAINT_ORIY: case KX_ACT_CONSTRAINT_ORIZ: { - MT_Scalar len = m_refDirection.length(); + MT_Scalar len = m_refDirVector.length(); if (MT_fuzzyZero(len)) { // missing a valid direction std::cout << "WARNING: Constraint actuator " << GetName() << ": There is no valid reference direction!" << std::endl; m_locrot = KX_ACT_CONSTRAINT_NODEF; } else { - m_refDirection /= len; + m_refDirection[0] /= len; + m_refDirection[1] /= len; + m_refDirection[2] /= len; + m_refDirVector /= len; } m_minimumBound = cos(minBound); m_maximumBound = cos(maxBound); @@ -116,7 +121,7 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* resu bool bFound = false; - if (m_property[0] == 0) + if (m_property.IsEmpty()) { bFound = true; } @@ -126,7 +131,7 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* resu { if (client->m_auxilary_info) { - bFound = !strcmp(m_property, ((char*)client->m_auxilary_info)); + bFound = !strcmp(m_property.Ptr(), ((char*)client->m_auxilary_info)); } } else @@ -209,7 +214,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) if ((m_maximumBound < (1.0f-FLT_EPSILON)) || (m_minimumBound < (1.0f-FLT_EPSILON))) { // reference direction needs to be evaluated // 1. get the cosine between current direction and target - cosangle = direction.dot(m_refDirection); + cosangle = direction.dot(m_refDirVector); if (cosangle >= (m_maximumBound-FLT_EPSILON) && cosangle <= (m_minimumBound+FLT_EPSILON)) { // no change to do result = true; @@ -218,27 +223,27 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) // 2. define a new reference direction // compute local axis with reference direction as X and // Y in direction X refDirection plane - MT_Vector3 zaxis = m_refDirection.cross(direction); + MT_Vector3 zaxis = m_refDirVector.cross(direction); if (MT_fuzzyZero2(zaxis.length2())) { // direction and refDirection are identical, // choose any other direction to define plane if (direction[0] < 0.9999) - zaxis = m_refDirection.cross(MT_Vector3(1.0,0.0,0.0)); + zaxis = m_refDirVector.cross(MT_Vector3(1.0,0.0,0.0)); else - zaxis = m_refDirection.cross(MT_Vector3(0.0,1.0,0.0)); + zaxis = m_refDirVector.cross(MT_Vector3(0.0,1.0,0.0)); } - MT_Vector3 yaxis = zaxis.cross(m_refDirection); + MT_Vector3 yaxis = zaxis.cross(m_refDirVector); yaxis.normalize(); if (cosangle > m_minimumBound) { // angle is too close to reference direction, // choose a new reference that is exactly at minimum angle - refDirection = m_minimumBound * m_refDirection + m_minimumSine * yaxis; + refDirection = m_minimumBound * m_refDirVector + m_minimumSine * yaxis; } else { // angle is too large, choose new reference direction at maximum angle - refDirection = m_maximumBound * m_refDirection + m_maximumSine * yaxis; + refDirection = m_maximumBound * m_refDirVector + m_maximumSine * yaxis; } } else { - refDirection = m_refDirection; + refDirection = m_refDirVector; } // apply damping on the direction direction = filter*direction + (1.0-filter)*refDirection; @@ -470,7 +475,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) // Fh force is stored in m_maximum MT_Scalar springForce = springExtent * m_maximumBound; // damping is stored in m_refDirection [0] = damping, [1] = rot damping - MT_Scalar springDamp = relativeVelocityRay * m_refDirection[0]; + MT_Scalar springDamp = relativeVelocityRay * m_refDirVector[0]; MT_Vector3 newVelocity = spc->GetLinearVelocity()-(springForce+springDamp)*direction; if (m_option & KX_ACT_CONSTRAINT_NORMAL) { @@ -483,7 +488,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) MT_Vector3 angVelocity = spc->GetAngularVelocity(); // remove component that is parallel to normal angVelocity -= angVelocity.dot(newnormal)*newnormal; - MT_Vector3 angDamp = angVelocity * ((m_refDirection[1]>MT_EPSILON)?m_refDirection[1]:m_refDirection[0]); + MT_Vector3 angDamp = angVelocity * ((m_refDirVector[1]>MT_EPSILON)?m_refDirVector[1]:m_refDirVector[0]); spc->SetAngularVelocity(spc->GetAngularVelocity()+(angSpring-angDamp), false); } } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) { @@ -560,22 +565,22 @@ bool KX_ConstraintActuator::IsValidMode(KX_ConstraintActuator::KX_CONSTRAINTTYPE /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_ConstraintActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_ConstraintActuator", - sizeof(KX_ConstraintActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_ConstraintActuator::Parents[] = { @@ -587,6 +592,7 @@ PyParentObject KX_ConstraintActuator::Parents[] = { }; PyMethodDef KX_ConstraintActuator::Methods[] = { + // Deprecated --> {"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, (PY_METHODCHAR)SetDamp_doc}, {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_NOARGS, (PY_METHODCHAR)GetDamp_doc}, {"setRotDamp", (PyCFunction) KX_ConstraintActuator::sPySetRotDamp, METH_VARARGS, (PY_METHODCHAR)SetRotDamp_doc}, @@ -609,15 +615,47 @@ PyMethodDef KX_ConstraintActuator::Methods[] = { {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, (PY_METHODCHAR)GetRayLength_doc}, {"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, (PY_METHODCHAR)SetLimit_doc}, {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_NOARGS, (PY_METHODCHAR)GetLimit_doc}, + // <-- {NULL,NULL} //Sentinel }; PyAttributeDef KX_ConstraintActuator::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("damp",0,100,true,KX_ConstraintActuator,m_posDampTime), + KX_PYATTRIBUTE_INT_RW("rotDamp",0,100,true,KX_ConstraintActuator,m_rotDampTime), + KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK("direction",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_refDirection,3,pyattr_check_direction), + KX_PYATTRIBUTE_INT_RW("option",0,0xFFFF,false,KX_ConstraintActuator,m_option), + KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_ConstraintActuator,m_activeTime), + KX_PYATTRIBUTE_STRING_RW("property",0,32,true,KX_ConstraintActuator,m_property), + KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_minimumBound), + KX_PYATTRIBUTE_FLOAT_RW("distance",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_minimumBound), + KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_maximumBound), + KX_PYATTRIBUTE_FLOAT_RW("rayLength",0,2000.f,KX_ConstraintActuator,m_maximumBound), + KX_PYATTRIBUTE_INT_RW("limit",KX_ConstraintActuator::KX_ACT_CONSTRAINT_NODEF+1,KX_ConstraintActuator::KX_ACT_CONSTRAINT_MAX-1,false,KX_ConstraintActuator,m_locrot), { NULL } //Sentinel }; -PyObject* KX_ConstraintActuator::_getattr(const char *attr) { - _getattr_up(SCA_IActuator); +PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_IActuator); +} + +int KX_ConstraintActuator::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IActuator); +} + + +int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_ConstraintActuator* act = static_cast<KX_ConstraintActuator*>(self); + MT_Vector3 dir(act->m_refDirection); + MT_Scalar len = dir.length(); + if (MT_fuzzyZero(len)) { + PyErr_SetString(PyExc_ValueError, "actuator.direction = vec: KX_ConstraintActuator, invalid direction"); + return 1; + } + act->m_refDirVector = dir/len; + return 0; } /* 2. setDamp */ @@ -626,11 +664,10 @@ const char KX_ConstraintActuator::SetDamp_doc[] = "\t- duration: integer\n" "\tSets the time constant of the orientation and distance constraint.\n" "\tIf the duration is negative, it is set to 0.\n"; -PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetDamp(PyObject* args) { + ShowDeprecationWarning("setDamp()", "the damp property"); int dampArg; - if(!PyArg_ParseTuple(args, "i", &dampArg)) { + if(!PyArg_ParseTuple(args, "i:setDamp", &dampArg)) { return NULL; } @@ -643,7 +680,8 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, const char KX_ConstraintActuator::GetDamp_doc[] = "getDamp()\n" "\tReturns the damping parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self){ +PyObject* KX_ConstraintActuator::PyGetDamp(){ + ShowDeprecationWarning("getDamp()", "the damp property"); return PyInt_FromLong(m_posDampTime); } @@ -653,11 +691,10 @@ const char KX_ConstraintActuator::SetRotDamp_doc[] = "\t- duration: integer\n" "\tSets the time constant of the orientation constraint.\n" "\tIf the duration is negative, it is set to 0.\n"; -PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* args) { + ShowDeprecationWarning("setRotDamp()", "the rotDamp property"); int dampArg; - if(!PyArg_ParseTuple(args, "i", &dampArg)) { + if(!PyArg_ParseTuple(args, "i:setRotDamp", &dampArg)) { return NULL; } @@ -670,7 +707,8 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, const char KX_ConstraintActuator::GetRotDamp_doc[] = "getRotDamp()\n" "\tReturns the damping time for application of the constraint.\n"; -PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self){ +PyObject* KX_ConstraintActuator::PyGetRotDamp(){ + ShowDeprecationWarning("getRotDamp()", "the rotDamp property"); return PyInt_FromLong(m_rotDampTime); } @@ -679,14 +717,13 @@ const char KX_ConstraintActuator::SetDirection_doc[] = "setDirection(vector)\n" "\t- vector: 3-tuple\n" "\tSets the reference direction in world coordinate for the orientation constraint.\n"; -PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetDirection(PyObject* args) { + ShowDeprecationWarning("setDirection()", "the direction property"); float x, y, z; MT_Scalar len; MT_Vector3 dir; - if(!PyArg_ParseTuple(args, "(fff)", &x, &y, &z)) { + if(!PyArg_ParseTuple(args, "(fff):setDirection", &x, &y, &z)) { return NULL; } dir[0] = x; @@ -697,7 +734,10 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, std::cout << "Invalid direction" << std::endl; return NULL; } - m_refDirection = dir/len; + m_refDirVector = dir/len; + m_refDirection[0] = x/len; + m_refDirection[1] = y/len; + m_refDirection[2] = z/len; Py_RETURN_NONE; } @@ -705,7 +745,8 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, const char KX_ConstraintActuator::GetDirection_doc[] = "getDirection()\n" "\tReturns the reference direction of the orientation constraint as a 3-tuple.\n"; -PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self){ +PyObject* KX_ConstraintActuator::PyGetDirection(){ + ShowDeprecationWarning("getDirection()", "the direction property"); PyObject *retVal = PyList_New(3); PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_refDirection[0])); @@ -724,11 +765,10 @@ const char KX_ConstraintActuator::SetOption_doc[] = "\t\t128 : Detect material rather than property\n" "\t\t256 : No deactivation if ray does not hit target\n" "\t\t512 : Activate distance control\n"; -PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetOption(PyObject* args) { + ShowDeprecationWarning("setOption()", "the option property"); int option; - if(!PyArg_ParseTuple(args, "i", &option)) { + if(!PyArg_ParseTuple(args, "i:setOption", &option)) { return NULL; } @@ -740,7 +780,8 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, const char KX_ConstraintActuator::GetOption_doc[] = "getOption()\n" "\tReturns the option parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self){ +PyObject* KX_ConstraintActuator::PyGetOption(){ + ShowDeprecationWarning("getOption()", "the option property"); return PyInt_FromLong(m_option); } @@ -751,11 +792,10 @@ const char KX_ConstraintActuator::SetTime_doc[] = "\tSets the activation time of the actuator.\n" "\tThe actuator disables itself after this many frame.\n" "\tIf set to 0 or negative, the actuator is not limited in time.\n"; -PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetTime(PyObject* args) { + ShowDeprecationWarning("setTime()", "the time property"); int t; - if(!PyArg_ParseTuple(args, "i", &t)) { + if(!PyArg_ParseTuple(args, "i:setTime", &t)) { return NULL; } @@ -769,7 +809,8 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, const char KX_ConstraintActuator::GetTime_doc[] = "getTime()\n" "\tReturns the time parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self){ +PyObject* KX_ConstraintActuator::PyGetTime(){ + ShowDeprecationWarning("getTime()", "the time property"); return PyInt_FromLong(m_activeTime); } @@ -779,18 +820,16 @@ const char KX_ConstraintActuator::SetProperty_doc[] = "\t- property: string\n" "\tSets the name of the property or material for the ray detection of the distance constraint.\n" "\tIf empty, the ray will detect any collisioning object.\n"; -PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetProperty(PyObject* args) { + ShowDeprecationWarning("setProperty()", "the 'property' property"); char *property; - if (!PyArg_ParseTuple(args, "s", &property)) { + if (!PyArg_ParseTuple(args, "s:setProperty", &property)) { return NULL; } if (property == NULL) { - m_property[0] = 0; + m_property = ""; } else { - strncpy(m_property, property, sizeof(m_property)); - m_property[sizeof(m_property)-1] = 0; + m_property = property; } Py_RETURN_NONE; @@ -799,8 +838,9 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, const char KX_ConstraintActuator::GetProperty_doc[] = "getProperty()\n" "\tReturns the property parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self){ - return PyString_FromString(m_property); +PyObject* KX_ConstraintActuator::PyGetProperty(){ + ShowDeprecationWarning("getProperty()", "the 'property' property"); + return PyString_FromString(m_property.Ptr()); } /* 4. setDistance */ @@ -814,11 +854,10 @@ const char KX_ConstraintActuator::SetMin_doc[] = "\t- lower_bound: float\n" "\tSets the lower value of the interval to which the value\n" "\tis clipped.\n"; -PyObject* KX_ConstraintActuator::PySetMin(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetMin(PyObject* args) { + ShowDeprecationWarning("setMin() or setDistance()", "the min or distance property"); float minArg; - if(!PyArg_ParseTuple(args, "f", &minArg)) { + if(!PyArg_ParseTuple(args, "f:setMin", &minArg)) { return NULL; } @@ -844,7 +883,8 @@ const char KX_ConstraintActuator::GetMin_doc[] = "getMin()\n" "\tReturns the lower value of the interval to which the value\n" "\tis clipped.\n"; -PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self) { +PyObject* KX_ConstraintActuator::PyGetMin() { + ShowDeprecationWarning("getMin() or getDistance()", "the min or distance property"); return PyFloat_FromDouble(m_minimumBound); } @@ -859,11 +899,10 @@ const char KX_ConstraintActuator::SetMax_doc[] = "\t- upper_bound: float\n" "\tSets the upper value of the interval to which the value\n" "\tis clipped.\n"; -PyObject* KX_ConstraintActuator::PySetMax(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PySetMax(PyObject* args){ + ShowDeprecationWarning("setMax() or setRayLength()", "the max or rayLength property"); float maxArg; - if(!PyArg_ParseTuple(args, "f", &maxArg)) { + if(!PyArg_ParseTuple(args, "f:setMax", &maxArg)) { return NULL; } @@ -889,7 +928,8 @@ const char KX_ConstraintActuator::GetMax_doc[] = "getMax()\n" "\tReturns the upper value of the interval to which the value\n" "\tis clipped.\n"; -PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self) { +PyObject* KX_ConstraintActuator::PyGetMax() { + ShowDeprecationWarning("getMax() or getRayLength()", "the max or rayLength property"); return PyFloat_FromDouble(m_maximumBound); } @@ -912,11 +952,10 @@ const char KX_ConstraintActuator::SetLimit_doc[] = "\t 14 : Align Y axis\n" "\t 15 : Align Z axis\n" "\tSets the type of constraint.\n"; -PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PySetLimit(PyObject* args) { + ShowDeprecationWarning("setLimit()", "the limit property"); int locrotArg; - if(!PyArg_ParseTuple(args, "i", &locrotArg)) { + if(!PyArg_ParseTuple(args, "i:setLimit", &locrotArg)) { return NULL; } @@ -928,7 +967,8 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, const char KX_ConstraintActuator::GetLimit_doc[] = "getLimit()\n" "\tReturns the type of constraint.\n"; -PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self) { +PyObject* KX_ConstraintActuator::PyGetLimit() { + ShowDeprecationWarning("setLimit()", "the limit property"); return PyInt_FromLong(m_locrot); } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 132b8a7328a..98f6fcd7906 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -56,7 +56,8 @@ protected: // sinus of maximum angle float m_maximumSine; // reference direction - MT_Vector3 m_refDirection; + float m_refDirection[3]; + MT_Vector3 m_refDirVector; // same as m_refDirection // locrotxyz choice (pick one): only one choice allowed at a time! int m_locrot; // active time of actuator @@ -65,7 +66,7 @@ protected: // option int m_option; // property to check - char m_property[32]; + STR_String m_property; // hit object KX_GameObject* m_hitObject; @@ -142,29 +143,33 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp); + static int pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_min(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetDamp); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDamp); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetRotDamp); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetRotDamp); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetRotDamp); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDirection); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetDirection); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDirection); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetOption); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetOption); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetOption); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetTime); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetTime); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetTime); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetProperty); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetProperty); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetProperty); - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMin); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetMin); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMin); static const char SetDistance_doc[]; static const char GetDistance_doc[]; - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMax); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetMax); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMax); static const char SetRayLength_doc[]; static const char GetRayLength_doc[]; - KX_PYMETHOD_DOC(KX_ConstraintActuator,SetLimit); + KX_PYMETHOD_DOC_VARARGS(KX_ConstraintActuator,SetLimit); KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetLimit); }; diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index f014c1896fe..7c3abb49159 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -49,17 +49,12 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper() { } //python integration methods -PyObject* KX_ConstraintWrapper::PyTestMethod(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ConstraintWrapper::PyTestMethod(PyObject* args, PyObject* kwds) { - Py_RETURN_NONE; } -PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* args, PyObject* kwds) { return PyInt_FromLong(m_constraintId); } @@ -69,22 +64,22 @@ PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* self, //python specific stuff PyTypeObject KX_ConstraintWrapper::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_ConstraintWrapper", - sizeof(KX_ConstraintWrapper), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_ConstraintWrapper::Parents[] = { @@ -92,16 +87,16 @@ PyParentObject KX_ConstraintWrapper::Parents[] = { NULL }; -PyObject* KX_ConstraintWrapper::_getattr(const char *attr) +PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr) { //here you can search for existing data members (like mass,friction etc.) - _getattr_up(PyObjectPlus); + py_getattro_up(PyObjectPlus); } -int KX_ConstraintWrapper::_setattr(const char *attr,PyObject* pyobj) +int KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* pyobj) { int result = 1; - + /* what the heck is this supposed to do?, needs attention */ if (PyList_Check(pyobj)) { result = 0; @@ -120,7 +115,7 @@ int KX_ConstraintWrapper::_setattr(const char *attr,PyObject* pyobj) result = 0; } if (result) - result = PyObjectPlus::_setattr(attr,pyobj); + result = PyObjectPlus::py_setattro(attr,pyobj); return result; }; diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index 36606d2d67b..6e67d842cb6 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -35,8 +35,8 @@ class KX_ConstraintWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); public: KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_ConstraintWrapper (); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 602486e0017..08e2ea30414 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -801,6 +801,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_gravity = btVector3(0,0,0); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; + ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min; + ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max; ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; @@ -881,8 +883,10 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, { shapeInfo->SetMesh(meshobj, false,false); } + + // Soft bodies require welding. Only avoid remove doubles for non-soft bodies! if (objprop->m_softbody) - shapeInfo->setVertexWeldingThreshold(0.01f); //todo: expose this to the UI + shapeInfo->setVertexWeldingThreshold1(0.01f); //todo: expose this to the UI bm = shapeInfo->CreateBulletShape(); //no moving concave meshes, so don't bother calculating inertia @@ -1103,16 +1107,19 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, if (rbody) { - btVector3 linearFactor( - objprop->m_lockXaxis? 0 : 1, - objprop->m_lockYaxis? 0 : 1, - objprop->m_lockZaxis? 0 : 1); - btVector3 angularFactor( - objprop->m_lockXRotaxis? 0 : 1, - objprop->m_lockYRotaxis? 0 : 1, - objprop->m_lockZRotaxis? 0 : 1); - rbody->setLinearFactor(linearFactor); - rbody->setAngularFactor(angularFactor); + if (objprop->m_angular_rigidbody) + { + btVector3 linearFactor( + objprop->m_lockXaxis? 0 : 1, + objprop->m_lockYaxis? 0 : 1, + objprop->m_lockZaxis? 0 : 1); + btVector3 angularFactor( + objprop->m_lockXRotaxis? 0 : 1, + objprop->m_lockYRotaxis? 0 : 1, + objprop->m_lockZRotaxis? 0 : 1); + rbody->setLinearFactor(linearFactor); + rbody->setAngularFactor(angularFactor); + } if (rbody && objprop->m_disableSleeping) { diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp new file mode 100644 index 00000000000..321370f9f3f --- /dev/null +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -0,0 +1,1819 @@ +/* $Id$ +----------------------------------------------------------------------------- + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA, or go to +http://www.gnu.org/copyleft/lesser.txt. + +Contributor(s): Dalai Felinto + +This code is originally inspired on some of the ideas and codes from Paul Bourke. +Developed as part of a Research and Development project for SAT - La Société des arts technologiques. +----------------------------------------------------------------------------- +*/ + +#include "KX_Dome.h" + +#include <structmember.h> +#include <float.h> +#include <math.h> + +#include "DNA_scene_types.h" +#include "RAS_CameraData.h" +#include "BLI_arithb.h" + +#include "GL/glew.h" + +// constructor +KX_Dome::KX_Dome ( + RAS_ICanvas* canvas, + /// rasterizer + RAS_IRasterizer* rasterizer, + /// render tools + RAS_IRenderTools* rendertools, + /// engine + KX_KetsjiEngine* engine, + + float size, //size for adjustments + short res, //resolution of the mesh + short mode, //mode - fisheye, truncated, warped, panoramic, ... + short angle, + float resbuf, //size adjustment of the buffer + struct Text* warptext + +): + m_canvas(canvas), + m_rasterizer(rasterizer), + m_rendertools(rendertools), + m_engine(engine), + m_drawingmode(engine->GetDrawType()), + m_size(size), + m_resolution(res), + m_mode(mode), + m_angle(angle), + m_resbuffer(resbuf), + canvaswidth(-1), canvasheight(-1), + dlistSupported(false) +{ + warp.usemesh = false; + + if (mode >= DOME_NUM_MODES) + m_mode = DOME_FISHEYE; + + if (warptext) // it there is a text data try to warp it + { + char *buf; + buf = txt_to_buf(warptext); + if (buf) + { + warp.usemesh = ParseWarpMesh(STR_String(buf)); + MEM_freeN(buf); + } + } + + //setting the viewport size + GLuint viewport[4]={0}; + glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); + + SetViewPort(viewport); + + switch(m_mode){ + case DOME_FISHEYE: + if (m_angle <= 180){ + cubetop.resize(1); + cubebottom.resize(1); + cubeleft.resize(2); + cuberight.resize(2); + + CreateMeshDome180(); + m_numfaces = 4; + }else if (m_angle > 180){ + cubetop.resize(2); + cubebottom.resize(2); + cubeleft.resize(2); + cubefront.resize(2); + cuberight.resize(2); + + CreateMeshDome250(); + m_numfaces = 5; + } break; + case DOME_TRUNCATED: + cubetop.resize(1); + cubebottom.resize(1); + cubeleft.resize(2); + cuberight.resize(2); + + m_angle = 180; + CreateMeshDome180(); + m_numfaces = 4; + break; + case DOME_PANORAM_SPH: + cubeleft.resize(2); + cubeleftback.resize(2); + cuberight.resize(2); + cuberightback.resize(2); + cubetop.resize(2); + cubebottom.resize(2); + + m_angle = 360; + CreateMeshPanorama(); + m_numfaces = 6; + break; + } + + m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces); + + CalculateCameraOrientation(); + + CreateGLImages(); + + dlistSupported = CreateDL(); +} + +// destructor +KX_Dome::~KX_Dome (void) +{ + GLuint m_numimages = m_numfaces; + + ClearGLImages(); + + if(dlistSupported) + glDeleteLists(dlistId, (GLsizei) m_numimages); +} + +void KX_Dome::SetViewPort(GLuint viewport[4]) +{ + if(canvaswidth != m_canvas->GetWidth() || canvasheight != m_canvas->GetHeight()) + { + m_viewport.SetLeft(viewport[0]); + m_viewport.SetBottom(viewport[1]); + m_viewport.SetRight(viewport[2]); + m_viewport.SetTop(viewport[3]); + + CalculateImageSize(); + } +} + +void KX_Dome::CreateGLImages(void) +{ + glGenTextures(m_numimages, (GLuint*)&domefacesId); + + for (int j=0;j<m_numfaces;j++){ + glBindTexture(GL_TEXTURE_2D, domefacesId[j]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_imagesize, m_imagesize, 0, GL_RGB8, + GL_UNSIGNED_BYTE, 0); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, m_imagesize, m_imagesize, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if(warp.usemesh){ + glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagewidth, warp.imageheight, 0, GL_RGB8, + GL_UNSIGNED_BYTE, 0); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagewidth, warp.imageheight, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } +} + +void KX_Dome::ClearGLImages(void) +{ + glDeleteTextures(m_numimages, (GLuint*)&domefacesId); +/* + for (int i=0;i<m_numimages;i++) + if(glIsTexture(domefacesId[i])) + glDeleteTextures(1, (GLuint*)&domefacesId[i]); +*/ +} + +void KX_Dome::CalculateImageSize(void) +{ +/* +- determine the minimum buffer size +- reduce the buffer for better performace +- create a power of 2 texture bigger than the buffer +*/ + + canvaswidth = m_canvas->GetWidth(); + canvasheight = m_canvas->GetHeight(); + + m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth); + m_buffersize *= m_resbuffer; //reduce buffer size for better performance + + int i = 0; + while ((1 << i) <= m_buffersize) + i++; + m_imagesize = (1 << i); + + if (warp.usemesh){ + warp.bufferwidth = canvaswidth; + warp.bufferheight = canvasheight; + + i = 0; + while ((1 << i) <= warp.bufferwidth) + i++; + warp.imagewidth = (1 << i); + + i = 0; + while ((1 << i) <= warp.bufferheight) + i++; + warp.imageheight = (1 << i); + } +} + +bool KX_Dome::CreateDL(){ + int i,j; + + dlistId = glGenLists((GLsizei) m_numimages); + if (dlistId != 0) { + if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED){ + glNewList(dlistId, GL_COMPILE); + GLDrawTriangles(cubetop, nfacestop); + glEndList(); + + glNewList(dlistId+1, GL_COMPILE); + GLDrawTriangles(cubebottom, nfacesbottom); + glEndList(); + + glNewList(dlistId+2, GL_COMPILE); + GLDrawTriangles(cubeleft, nfacesleft); + glEndList(); + + glNewList(dlistId+3, GL_COMPILE); + GLDrawTriangles(cuberight, nfacesright); + glEndList(); + + if (m_angle > 180){ + glNewList(dlistId+4, GL_COMPILE); + GLDrawTriangles(cubefront, nfacesfront); + glEndList(); + } + } + else if (m_mode == DOME_PANORAM_SPH) + { + glNewList(dlistId, GL_COMPILE); + GLDrawTriangles(cubetop, nfacestop); + glEndList(); + + glNewList(dlistId+1, GL_COMPILE); + GLDrawTriangles(cubebottom, nfacesbottom); + glEndList(); + + glNewList(dlistId+2, GL_COMPILE); + GLDrawTriangles(cubeleft, nfacesleft); + glEndList(); + + glNewList(dlistId+3, GL_COMPILE); + GLDrawTriangles(cuberight, nfacesright); + glEndList(); + + glNewList(dlistId+4, GL_COMPILE); + GLDrawTriangles(cubeleftback, nfacesleftback); + glEndList(); + + glNewList(dlistId+5, GL_COMPILE); + GLDrawTriangles(cuberightback, nfacesrightback); + glEndList(); + } + + if(warp.usemesh){ + glNewList((dlistId + m_numfaces), GL_COMPILE); + GLDrawWarpQuads(); + glEndList(); + } + + //clearing the vectors + cubetop.clear(); + cubebottom.clear(); + cuberight.clear(); + cubeleft.clear(); + cubefront.clear(); + cubeleftback.clear(); + cuberightback.clear(); + warp.nodes.clear(); + + } else // genList failed + return false; + + return true; +} + +void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces) +{ + int i,j; + glBegin(GL_TRIANGLES); + for (i=0;i<nfaces;i++) { + for (j=0;j<3;j++) { + glTexCoord2f(face[i].u[j],face[i].v[j]); + glVertex3f((GLfloat)face[i].verts[j][0],(GLfloat)face[i].verts[j][1],(GLfloat)face[i].verts[j][2]); + } + } + glEnd(); +} + +void KX_Dome::GLDrawWarpQuads(void) +{ + int i, j, i2; + float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth; + float uv_height = (float)(warp.bufferheight-1) / warp.imageheight; + + if(warp.mode ==2 ){ + glBegin(GL_QUADS); + for (i=0;i<warp.n_height-1;i++) { + for (j=0;j<warp.n_width-1;j++) { + if(warp.nodes[i][j].i < 0 || warp.nodes[i+1][j].i < 0 || warp.nodes[i+1][j+1].i < 0 || warp.nodes[i][j+1].i < 0) + continue; + + glColor3f(warp.nodes[i][j].i, warp.nodes[i][j].i, warp.nodes[i][j].i); + glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height)); + glVertex3f(warp.nodes[i][j].x, warp.nodes[i][j].y,0.0); + + glColor3f(warp.nodes[i+1][j].i, warp.nodes[i+1][j].i, warp.nodes[i+1][j].i); + glTexCoord2f((warp.nodes[i+1][j].u * uv_width), (warp.nodes[i+1][j].v * uv_height)); + glVertex3f(warp.nodes[i+1][j].x, warp.nodes[i+1][j].y,0.0); + + glColor3f(warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i); + glTexCoord2f((warp.nodes[i+1][j+1].u * uv_width), (warp.nodes[i+1][j+1].v * uv_height)); + glVertex3f(warp.nodes[i+1][j+1].x, warp.nodes[i+1][j+1].y,0.0); + + glColor3f(warp.nodes[i][j+1].i, warp.nodes[i][j+1].i, warp.nodes[i][j+1].i); + glTexCoord2f((warp.nodes[i][j+1].u * uv_width), (warp.nodes[i][j+1].v * uv_height)); + glVertex3f(warp.nodes[i][j+1].x, warp.nodes[i][j+1].y,0.0); + } + } + glEnd(); + } + else if (warp.mode == 1){ + glBegin(GL_QUADS); + for (i=0;i<warp.n_height-1;i++) { + for (j=0;j<warp.n_width-1;j++) { + i2 = (i+1) % warp.n_width; // Wrap around, i = warp.n_width = 0 + + if (warp.nodes[i][j].i < 0 || warp.nodes[i2][j].i < 0 || warp.nodes[i2][j+1].i < 0 || warp.nodes[i][j+1].i < 0) + continue; + + glColor3f(warp.nodes[i][j].i,warp.nodes[i][j].i,warp.nodes[i][j].i); + glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height)); + glVertex3f(warp.nodes[i][j].x,warp.nodes[i][j].y,0.0); + + glColor3f(warp.nodes[i2][j].i,warp.nodes[i2][j].i,warp.nodes[i2][j].i); + glTexCoord2f((warp.nodes[i2][j].u * uv_width), (warp.nodes[i2][j].v * uv_height)); + glVertex3f(warp.nodes[i2][j].x,warp.nodes[i2][j].y,0.0); + + glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i); + glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height)); + glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0); + + glColor3f(warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i,warp.nodes[i2][j+1].i); + glTexCoord2f((warp.nodes[i2][j+1].u * uv_width), (warp.nodes[i2][j+1].v * uv_height)); + glVertex3f(warp.nodes[i2][j+1].x,warp.nodes[i2][j+1].y,0.0); + + } + } + glEnd(); + } else{ + printf("Error: Warp Mode unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n"); + } +} + + +bool KX_Dome::ParseWarpMesh(STR_String text) +{ +/* +//Notes about the supported data format: +File example:: + mode + width height + n0_x n0_y n0_u n0_v n0_i + n1_x n1_y n1_u n1_v n1_i + n2_x n1_y n2_u n2_v n2_i + n3_x n3_y n3_u n3_v n3_i + (...) +First line is the image type the mesh is support to be applied to: 2 = fisheye, 1=radial +Tthe next line has the mesh dimensions +Rest of the lines are the nodes of the mesh. Each line has x y u v i + (x,y) are the normalised screen coordinates + (u,v) texture coordinates + i a multiplicative intensity factor + +x varies from -screen aspect to screen aspect +y varies from -1 to 1 +u and v vary from 0 to 1 +i ranges from 0 to 1, if negative don't draw that mesh node +*/ + int i,j,k; + int nodeX=0, nodeY=0; + + vector<STR_String> columns, lines; + + lines = text.Explode('\n'); + if(lines.size() < 6){ + printf("Error: Warp Mesh File with insufficient data!\n"); + return false; + } + columns = lines[1].Explode(' '); + + if(columns.size() !=2){ + printf("Error: Warp Mesh File incorrect. The second line should contain: width height.\n"); + return false; + } + + warp.mode = atoi(lines[0]);// 1 = radial, 2 = fisheye + + warp.n_width = atoi(columns[0]); + warp.n_height = atoi(columns[1]); + + if (lines.size() < 2 + (warp.n_width * warp.n_height)){ + printf("Error: Warp Mesh File with insufficient data!\n"); + return false; + }else{ + warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, vector<WarpMeshNode>(warp.n_width)); + + for(i=2; i-2 < (warp.n_width*warp.n_height); i++){ + columns = lines[i].Explode(' '); + + if (columns.size() == 5){ + nodeX = (i-2)%warp.n_width; + nodeY = ((i-2) - nodeX) / warp.n_width; + + warp.nodes[nodeY][nodeX].x = atof(columns[0]); + warp.nodes[nodeY][nodeX].y = atof(columns[1]); + warp.nodes[nodeY][nodeX].u = atof(columns[2]); + warp.nodes[nodeY][nodeX].v = atof(columns[3]); + warp.nodes[nodeY][nodeX].i = atof(columns[4]); + } + else{ + warp.nodes.clear(); + printf("Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n"); + return false; + } + } + } + return true; +} + +void KX_Dome::CreateMeshDome180(void) +{ +/* +1)- Define the faces of half of a cube + - each face is made out of 2 triangles +2) Subdivide the faces + - more resolution == more curved lines +3) Spherize the cube + - normalize the verts +4) Flatten onto xz plane + - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image +*/ + int i,j; + float sqrt_2 = sqrt(2.0); + float uv_ratio = (float)(m_buffersize-1) / m_imagesize; + + m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening + + //creating faces for the env mapcube 180º Dome + // Top Face - just a triangle + cubetop[0].verts[0][0] = -sqrt_2 / 2.0; + cubetop[0].verts[0][1] = 0.0; + cubetop[0].verts[0][2] = 0.5; + cubetop[0].u[0] = 0.0; + cubetop[0].v[0] = uv_ratio; + + cubetop[0].verts[1][0] = 0.0; + cubetop[0].verts[1][1] = sqrt_2 / 2.0; + cubetop[0].verts[1][2] = 0.5; + cubetop[0].u[1] = 0.0; + cubetop[0].v[1] = 0.0; + + cubetop[0].verts[2][0] = sqrt_2 / 2.0; + cubetop[0].verts[2][1] = 0.0; + cubetop[0].verts[2][2] = 0.5; + cubetop[0].u[2] = uv_ratio; + cubetop[0].v[2] = 0.0; + + nfacestop = 1; + + /* Bottom face - just a triangle */ + cubebottom[0].verts[0][0] = -sqrt_2 / 2.0; + cubebottom[0].verts[0][1] = 0.0; + cubebottom[0].verts[0][2] = -0.5; + cubebottom[0].u[0] = uv_ratio; + cubebottom[0].v[0] = 0.0; + + cubebottom[0].verts[1][0] = sqrt_2 / 2.0; + cubebottom[0].verts[1][1] = 0; + cubebottom[0].verts[1][2] = -0.5; + cubebottom[0].u[1] = 0.0; + cubebottom[0].v[1] = uv_ratio; + + cubebottom[0].verts[2][0] = 0.0; + cubebottom[0].verts[2][1] = sqrt_2 / 2.0; + cubebottom[0].verts[2][2] = -0.5; + cubebottom[0].u[2] = 0.0; + cubebottom[0].v[2] = 0.0; + + nfacesbottom = 1; + + /* Left face - two triangles */ + + cubeleft[0].verts[0][0] = -sqrt_2 / 2.0; + cubeleft[0].verts[0][1] = .0; + cubeleft[0].verts[0][2] = -0.5; + cubeleft[0].u[0] = 0.0; + cubeleft[0].v[0] = 0.0; + + cubeleft[0].verts[1][0] = 0.0; + cubeleft[0].verts[1][1] = sqrt_2 / 2.0; + cubeleft[0].verts[1][2] = -0.5; + cubeleft[0].u[1] = uv_ratio; + cubeleft[0].v[1] = 0.0; + + cubeleft[0].verts[2][0] = -sqrt_2 / 2.0; + cubeleft[0].verts[2][1] = 0.0; + cubeleft[0].verts[2][2] = 0.5; + cubeleft[0].u[2] = 0.0; + cubeleft[0].v[2] = uv_ratio; + + //second triangle + cubeleft[1].verts[0][0] = -sqrt_2 / 2.0; + cubeleft[1].verts[0][1] = 0.0; + cubeleft[1].verts[0][2] = 0.5; + cubeleft[1].u[0] = 0.0; + cubeleft[1].v[0] = uv_ratio; + + cubeleft[1].verts[1][0] = 0.0; + cubeleft[1].verts[1][1] = sqrt_2 / 2.0; + cubeleft[1].verts[1][2] = -0.5; + cubeleft[1].u[1] = uv_ratio; + cubeleft[1].v[1] = 0.0; + + cubeleft[1].verts[2][0] = 0.0; + cubeleft[1].verts[2][1] = sqrt_2 / 2.0; + cubeleft[1].verts[2][2] = 0.5; + cubeleft[1].u[2] = uv_ratio; + cubeleft[1].v[2] = uv_ratio; + + nfacesleft = 2; + + /* Right face - two triangles */ + cuberight[0].verts[0][0] = 0.0; + cuberight[0].verts[0][1] = sqrt_2 / 2.0; + cuberight[0].verts[0][2] = -0.5; + cuberight[0].u[0] = 0.0; + cuberight[0].v[0] = 0.0; + + cuberight[0].verts[1][0] = sqrt_2 / 2.0; + cuberight[0].verts[1][1] = 0.0; + cuberight[0].verts[1][2] = -0.5; + cuberight[0].u[1] = uv_ratio; + cuberight[0].v[1] = 0.0; + + cuberight[0].verts[2][0] = sqrt_2 / 2.0; + cuberight[0].verts[2][1] = 0.0; + cuberight[0].verts[2][2] = 0.5; + cuberight[0].u[2] = uv_ratio; + cuberight[0].v[2] = uv_ratio; + + //second triangle + cuberight[1].verts[0][0] = 0.0; + cuberight[1].verts[0][1] = sqrt_2 / 2.0; + cuberight[1].verts[0][2] = -0.5; + cuberight[1].u[0] = 0.0; + cuberight[1].v[0] = 0.0; + + cuberight[1].verts[1][0] = sqrt_2 / 2.0; + cuberight[1].verts[1][1] = 0.0; + cuberight[1].verts[1][2] = 0.5; + cuberight[1].u[1] = uv_ratio; + cuberight[1].v[1] = uv_ratio; + + cuberight[1].verts[2][0] = 0.0; + cuberight[1].verts[2][1] = sqrt_2 / 2.0; + cuberight[1].verts[2][2] = 0.5; + cuberight[1].u[2] = 0.0; + cuberight[1].v[2] = uv_ratio; + + nfacesright = 2; + + //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration + //Could be made more efficient for drawing if the triangles were ordered in a fan. Not that important since we are using DisplayLists + + for(i=0;i<m_resolution;i++){ + cubetop.resize(4*nfacestop); + SplitFace(cubetop,&nfacestop); + cubebottom.resize(4*nfacesbottom); + SplitFace(cubebottom,&nfacesbottom); + cubeleft.resize(4*nfacesleft); + SplitFace(cubeleft,&nfacesleft); + cuberight.resize(4*nfacesright); + SplitFace(cuberight,&nfacesright); + } + + // Turn into a hemisphere + for(j=0;j<3;j++){ + for(i=0;i<nfacestop;i++) + cubetop[i].verts[j].normalize(); + for(i=0;i<nfacesbottom;i++) + cubebottom[i].verts[j].normalize(); + for(i=0;i<nfacesleft;i++) + cubeleft[i].verts[j].normalize(); + for(i=0;i<nfacesright;i++) + cuberight[i].verts[j].normalize(); + } + + //flatten onto xz plane + for(i=0;i<nfacestop;i++) + FlattenDome(cubetop[i].verts); + for(i=0;i<nfacesbottom;i++) + FlattenDome(cubebottom[i].verts); + for(i=0;i<nfacesleft;i++) + FlattenDome(cubeleft[i].verts); + for(i=0;i<nfacesright;i++) + FlattenDome(cuberight[i].verts); + +} + +void KX_Dome::CreateMeshDome250(void) +{ +/* +1)- Define the faces of a cube without the back face + - each face is made out of 2 triangles +2) Subdivide the faces + - more resolution == more curved lines +3) Spherize the cube + - normalize the verts +4) Flatten onto xz plane + - transform it onto an equidistant spherical projection techniques to transform the sphere onto a dome image +*/ + + int i,j; + float uv_height, uv_base; + float verts_height; + + float rad_ang = m_angle * MT_PI / 180.0; + float uv_ratio = (float)(m_buffersize-1) / m_imagesize; + + m_radangle = m_angle * M_PI/180.0;//calculates the radians angle, used for flattening +/* +verts_height is the exactly needed height of the cube faces (not always 1.0). +When we want some horizontal information (e.g. for horizontal 220º domes) we don't need to create and tesselate the whole cube. +Therefore the lateral cube faces could be small, and the tesselate mesh would be completely used. +(if we always worked with verts_height = 1.0, we would be discarding a lot of the calculated and tesselated geometry). + +So I came out with this formula: +verts_height = tan((rad_ang/2) - (MT_PI/2))*sqrt(2.0); + +Here we take half the sphere(rad_ang/2) and subtract a quarter of it (MT_PI/2) +Therefore we have the lenght in radians of the dome/sphere over the horizon. +Once we take the tangent of that angle, you have the verts coordinate corresponding to the verts on the side faces. +Then we need to multiply it by sqrt(2.0) to get the coordinate of the verts on the diagonal of the original cube. +*/ + verts_height = tan((rad_ang/2) - (MT_PI/2))*sqrt(2.0); + + uv_height = uv_ratio * ((verts_height/2) + 0.5); + uv_base = uv_ratio * (1.0 - ((verts_height/2) + 0.5)); + + //creating faces for the env mapcube 180º Dome + // Front Face - 2 triangles + cubefront[0].verts[0][0] =-1.0; + cubefront[0].verts[0][1] = 1.0; + cubefront[0].verts[0][2] =-1.0; + cubefront[0].u[0] = 0.0; + cubefront[0].v[0] = 0.0; + + cubefront[0].verts[1][0] = 1.0; + cubefront[0].verts[1][1] = 1.0; + cubefront[0].verts[1][2] = 1.0; + cubefront[0].u[1] = uv_ratio; + cubefront[0].v[1] = uv_ratio; + + cubefront[0].verts[2][0] =-1.0; + cubefront[0].verts[2][1] = 1.0; + cubefront[0].verts[2][2] = 1.0; + cubefront[0].u[2] = 0.0; + cubefront[0].v[2] = uv_ratio; + + //second triangle + cubefront[1].verts[0][0] = 1.0; + cubefront[1].verts[0][1] = 1.0; + cubefront[1].verts[0][2] = 1.0; + cubefront[1].u[0] = uv_ratio; + cubefront[1].v[0] = uv_ratio; + + cubefront[1].verts[1][0] =-1.0; + cubefront[1].verts[1][1] = 1.0; + cubefront[1].verts[1][2] =-1.0; + cubefront[1].u[1] = 0.0; + cubefront[1].v[1] = 0.0; + + cubefront[1].verts[2][0] = 1.0; + cubefront[1].verts[2][1] = 1.0; + cubefront[1].verts[2][2] =-1.0; + cubefront[1].u[2] = uv_ratio; + cubefront[1].v[2] = 0.0; + + nfacesfront = 2; + + // Left Face - 2 triangles + cubeleft[0].verts[0][0] =-1.0; + cubeleft[0].verts[0][1] = 1.0; + cubeleft[0].verts[0][2] =-1.0; + cubeleft[0].u[0] = uv_ratio; + cubeleft[0].v[0] = 0.0; + + cubeleft[0].verts[1][0] =-1.0; + cubeleft[0].verts[1][1] =-verts_height; + cubeleft[0].verts[1][2] = 1.0; + cubeleft[0].u[1] = uv_base; + cubeleft[0].v[1] = uv_ratio; + + cubeleft[0].verts[2][0] =-1.0; + cubeleft[0].verts[2][1] =-verts_height; + cubeleft[0].verts[2][2] =-1.0; + cubeleft[0].u[2] = uv_base; + cubeleft[0].v[2] = 0.0; + + //second triangle + cubeleft[1].verts[0][0] =-1.0; + cubeleft[1].verts[0][1] =-verts_height; + cubeleft[1].verts[0][2] = 1.0; + cubeleft[1].u[0] = uv_base; + cubeleft[1].v[0] = uv_ratio; + + cubeleft[1].verts[1][0] =-1.0; + cubeleft[1].verts[1][1] = 1.0; + cubeleft[1].verts[1][2] =-1.0; + cubeleft[1].u[1] = uv_ratio; + cubeleft[1].v[1] = 0.0; + + cubeleft[1].verts[2][0] =-1.0; + cubeleft[1].verts[2][1] = 1.0; + cubeleft[1].verts[2][2] = 1.0; + cubeleft[1].u[2] = uv_ratio; + cubeleft[1].v[2] = uv_ratio; + + nfacesleft = 2; + + // right Face - 2 triangles + cuberight[0].verts[0][0] = 1.0; + cuberight[0].verts[0][1] = 1.0; + cuberight[0].verts[0][2] = 1.0; + cuberight[0].u[0] = 0.0; + cuberight[0].v[0] = uv_ratio; + + cuberight[0].verts[1][0] = 1.0; + cuberight[0].verts[1][1] =-verts_height; + cuberight[0].verts[1][2] =-1.0; + cuberight[0].u[1] = uv_height; + cuberight[0].v[1] = 0.0; + + cuberight[0].verts[2][0] = 1.0; + cuberight[0].verts[2][1] =-verts_height; + cuberight[0].verts[2][2] = 1.0; + cuberight[0].u[2] = uv_height; + cuberight[0].v[2] = uv_ratio; + + //second triangle + cuberight[1].verts[0][0] = 1.0; + cuberight[1].verts[0][1] =-verts_height; + cuberight[1].verts[0][2] =-1.0; + cuberight[1].u[0] = uv_height; + cuberight[1].v[0] = 0.0; + + cuberight[1].verts[1][0] = 1.0; + cuberight[1].verts[1][1] = 1.0; + cuberight[1].verts[1][2] = 1.0; + cuberight[1].u[1] = 0.0; + cuberight[1].v[1] = uv_ratio; + + cuberight[1].verts[2][0] = 1.0; + cuberight[1].verts[2][1] = 1.0; + cuberight[1].verts[2][2] =-1.0; + cuberight[1].u[2] = 0.0; + cuberight[1].v[2] = 0.0; + + nfacesright = 2; + + // top Face - 2 triangles + cubetop[0].verts[0][0] =-1.0; + cubetop[0].verts[0][1] = 1.0; + cubetop[0].verts[0][2] = 1.0; + cubetop[0].u[0] = 0.0; + cubetop[0].v[0] = 0.0; + + cubetop[0].verts[1][0] = 1.0; + cubetop[0].verts[1][1] =-verts_height; + cubetop[0].verts[1][2] = 1.0; + cubetop[0].u[1] = uv_ratio; + cubetop[0].v[1] = uv_height; + + cubetop[0].verts[2][0] =-1.0; + cubetop[0].verts[2][1] =-verts_height; + cubetop[0].verts[2][2] = 1.0; + cubetop[0].u[2] = 0.0; + cubetop[0].v[2] = uv_height; + + //second triangle + cubetop[1].verts[0][0] = 1.0; + cubetop[1].verts[0][1] =-verts_height; + cubetop[1].verts[0][2] = 1.0; + cubetop[1].u[0] = uv_ratio; + cubetop[1].v[0] = uv_height; + + cubetop[1].verts[1][0] =-1.0; + cubetop[1].verts[1][1] = 1.0; + cubetop[1].verts[1][2] = 1.0; + cubetop[1].u[1] = 0.0; + cubetop[1].v[1] = 0.0; + + cubetop[1].verts[2][0] = 1.0; + cubetop[1].verts[2][1] = 1.0; + cubetop[1].verts[2][2] = 1.0; + cubetop[1].u[2] = uv_ratio; + cubetop[1].v[2] = 0.0; + + nfacestop = 2; + + // bottom Face - 2 triangles + cubebottom[0].verts[0][0] =-1.0; + cubebottom[0].verts[0][1] =-verts_height; + cubebottom[0].verts[0][2] =-1.0; + cubebottom[0].u[0] = 0.0; + cubebottom[0].v[0] = uv_base; + + cubebottom[0].verts[1][0] = 1.0; + cubebottom[0].verts[1][1] = 1.0; + cubebottom[0].verts[1][2] =-1.0; + cubebottom[0].u[1] = uv_ratio; + cubebottom[0].v[1] = uv_ratio; + + cubebottom[0].verts[2][0] =-1.0; + cubebottom[0].verts[2][1] = 1.0; + cubebottom[0].verts[2][2] =-1.0; + cubebottom[0].u[2] = 0.0; + cubebottom[0].v[2] = uv_ratio; + + //second triangle + cubebottom[1].verts[0][0] = 1.0; + cubebottom[1].verts[0][1] = 1.0; + cubebottom[1].verts[0][2] =-1.0; + cubebottom[1].u[0] = uv_ratio; + cubebottom[1].v[0] = uv_ratio; + + cubebottom[1].verts[1][0] =-1.0; + cubebottom[1].verts[1][1] =-verts_height; + cubebottom[1].verts[1][2] =-1.0; + cubebottom[1].u[1] = 0.0; + cubebottom[1].v[1] = uv_base; + + cubebottom[1].verts[2][0] = 1.0; + cubebottom[1].verts[2][1] =-verts_height; + cubebottom[1].verts[2][2] =-1.0; + cubebottom[1].u[2] = uv_ratio; + cubebottom[1].v[2] = uv_base; + + nfacesbottom = 2; + + //Refine a triangular mesh by bisecting each edge forms 3 new triangles for each existing triangle on each iteration + //It could be made more efficient for drawing if the triangles were ordered in a strip! + + for(i=0;i<m_resolution;i++){ + cubefront.resize(4*nfacesfront); + SplitFace(cubefront,&nfacesfront); + cubetop.resize(4*nfacestop); + SplitFace(cubetop,&nfacestop); + cubebottom.resize(4*nfacesbottom); + SplitFace(cubebottom,&nfacesbottom); + cubeleft.resize(4*nfacesleft); + SplitFace(cubeleft,&nfacesleft); + cuberight.resize(4*nfacesright); + SplitFace(cuberight,&nfacesright); + } + + // Turn into a hemisphere/sphere + for(j=0;j<3;j++){ + for(i=0;i<nfacesfront;i++) + cubefront[i].verts[j].normalize(); + for(i=0;i<nfacestop;i++) + cubetop[i].verts[j].normalize(); + for(i=0;i<nfacesbottom;i++) + cubebottom[i].verts[j].normalize(); + for(i=0;i<nfacesleft;i++) + cubeleft[i].verts[j].normalize(); + for(i=0;i<nfacesright;i++) + cuberight[i].verts[j].normalize(); + } + + //flatten onto xz plane + for(i=0;i<nfacesfront;i++) + FlattenDome(cubefront[i].verts); + for(i=0;i<nfacestop;i++) + FlattenDome(cubetop[i].verts); + for(i=0;i<nfacesbottom;i++) + FlattenDome(cubebottom[i].verts); + for(i=0;i<nfacesleft;i++) + FlattenDome(cubeleft[i].verts); + for(i=0;i<nfacesright;i++) + FlattenDome(cuberight[i].verts); +} + +void KX_Dome::CreateMeshPanorama(void) +{ +/* +1)- Define the faces of a cube without the top and bottom faces + - each face is made out of 2 triangles +2) Subdivide the faces + - more resolution == more curved lines +3) Spherize the cube + - normalize the verts t +4) Flatten onto xz plane + - use spherical projection techniques to transform the sphere onto a flat panorama +*/ + int i,j; + + float sqrt_2 = sqrt(2.0); + float uv_ratio = (float)(m_buffersize-1) / m_imagesize; + + /* Top face - two triangles */ + cubetop[0].verts[0][0] = -sqrt_2; + cubetop[0].verts[0][1] = 0.0; + cubetop[0].verts[0][2] = 1.0; + cubetop[0].u[0] = 0.0; + cubetop[0].v[0] = uv_ratio; + + cubetop[0].verts[1][0] = 0.0; + cubetop[0].verts[1][1] = sqrt_2; + cubetop[0].verts[1][2] = 1.0; + cubetop[0].u[1] = 0.0; + cubetop[0].v[1] = 0.0; + + //second triangle + cubetop[0].verts[2][0] = sqrt_2; + cubetop[0].verts[2][1] = 0.0; + cubetop[0].verts[2][2] = 1.0; + cubetop[0].u[2] = uv_ratio; + cubetop[0].v[2] = 0.0; + + cubetop[1].verts[0][0] = sqrt_2; + cubetop[1].verts[0][1] = 0.0; + cubetop[1].verts[0][2] = 1.0; + cubetop[1].u[0] = uv_ratio; + cubetop[1].v[0] = 0.0; + + cubetop[1].verts[1][0] = 0.0; + cubetop[1].verts[1][1] = -sqrt_2; + cubetop[1].verts[1][2] = 1.0; + cubetop[1].u[1] = uv_ratio; + cubetop[1].v[1] = uv_ratio; + + cubetop[1].verts[2][0] = -sqrt_2; + cubetop[1].verts[2][1] = 0.0; + cubetop[1].verts[2][2] = 1.0; + cubetop[1].u[2] = 0.0; + cubetop[1].v[2] = uv_ratio; + + nfacestop = 2; + + /* Bottom face - two triangles */ + cubebottom[0].verts[0][0] = -sqrt_2; + cubebottom[0].verts[0][1] = 0.0; + cubebottom[0].verts[0][2] = -1.0; + cubebottom[0].u[0] = uv_ratio; + cubebottom[0].v[0] = 0.0; + + cubebottom[0].verts[1][0] = sqrt_2; + cubebottom[0].verts[1][1] = 0.0; + cubebottom[0].verts[1][2] = -1.0; + cubebottom[0].u[1] = 0.0; + cubebottom[0].v[1] = uv_ratio; + + cubebottom[0].verts[2][0] = 0.0; + cubebottom[0].verts[2][1] = sqrt_2; + cubebottom[0].verts[2][2] = -1.0; + cubebottom[0].u[2] = 0.0; + cubebottom[0].v[2] = 0.0; + + //second triangle + cubebottom[1].verts[0][0] = sqrt_2; + cubebottom[1].verts[0][1] = 0.0; + cubebottom[1].verts[0][2] = -1.0; + cubebottom[1].u[0] = 0.0; + cubebottom[1].v[0] = uv_ratio; + + cubebottom[1].verts[1][0] = -sqrt_2; + cubebottom[1].verts[1][1] = 0.0; + cubebottom[1].verts[1][2] = -1.0; + cubebottom[1].u[1] = uv_ratio; + cubebottom[1].v[1] = 0.0; + + cubebottom[1].verts[2][0] = 0.0; + cubebottom[1].verts[2][1] = -sqrt_2; + cubebottom[1].verts[2][2] = -1.0; + cubebottom[1].u[2] = uv_ratio; + cubebottom[1].v[2] = uv_ratio; + + nfacesbottom = 2; + + /* Left Back (135º) face - two triangles */ + + cubeleftback[0].verts[0][0] = 0; + cubeleftback[0].verts[0][1] = -sqrt_2; + cubeleftback[0].verts[0][2] = -1.0; + cubeleftback[0].u[0] = 0; + cubeleftback[0].v[0] = 0; + + cubeleftback[0].verts[1][0] = -sqrt_2; + cubeleftback[0].verts[1][1] = 0; + cubeleftback[0].verts[1][2] = -1.0; + cubeleftback[0].u[1] = uv_ratio; + cubeleftback[0].v[1] = 0; + + cubeleftback[0].verts[2][0] = 0; + cubeleftback[0].verts[2][1] = -sqrt_2; + cubeleftback[0].verts[2][2] = 1.0; + cubeleftback[0].u[2] = 0; + cubeleftback[0].v[2] = uv_ratio; + + //second triangle + cubeleftback[1].verts[0][0] = 0; + cubeleftback[1].verts[0][1] = -sqrt_2; + cubeleftback[1].verts[0][2] = 1.0; + cubeleftback[1].u[0] = 0; + cubeleftback[1].v[0] = uv_ratio; + + cubeleftback[1].verts[1][0] = -sqrt_2; + cubeleftback[1].verts[1][1] = 0; + cubeleftback[1].verts[1][2] = -1.0; + cubeleftback[1].u[1] = uv_ratio; + cubeleftback[1].v[1] = 0; + + cubeleftback[1].verts[2][0] = -sqrt_2; + cubeleftback[1].verts[2][1] = 0; + cubeleftback[1].verts[2][2] = 1.0; + cubeleftback[1].u[2] = uv_ratio; + cubeleftback[1].v[2] = uv_ratio; + + nfacesleftback = 2; + + /* Left face - two triangles */ + + cubeleft[0].verts[0][0] = -sqrt_2; + cubeleft[0].verts[0][1] = 0; + cubeleft[0].verts[0][2] = -1.0; + cubeleft[0].u[0] = 0; + cubeleft[0].v[0] = 0; + + cubeleft[0].verts[1][0] = 0; + cubeleft[0].verts[1][1] = sqrt_2; + cubeleft[0].verts[1][2] = -1.0; + cubeleft[0].u[1] = uv_ratio; + cubeleft[0].v[1] = 0; + + cubeleft[0].verts[2][0] = -sqrt_2; + cubeleft[0].verts[2][1] = 0; + cubeleft[0].verts[2][2] = 1.0; + cubeleft[0].u[2] = 0; + cubeleft[0].v[2] = uv_ratio; + + //second triangle + cubeleft[1].verts[0][0] = -sqrt_2; + cubeleft[1].verts[0][1] = 0; + cubeleft[1].verts[0][2] = 1.0; + cubeleft[1].u[0] = 0; + cubeleft[1].v[0] = uv_ratio; + + cubeleft[1].verts[1][0] = 0; + cubeleft[1].verts[1][1] = sqrt_2; + cubeleft[1].verts[1][2] = -1.0; + cubeleft[1].u[1] = uv_ratio; + cubeleft[1].v[1] = 0; + + cubeleft[1].verts[2][0] = 0; + cubeleft[1].verts[2][1] = sqrt_2; + cubeleft[1].verts[2][2] = 1.0; + cubeleft[1].u[2] = uv_ratio; + cubeleft[1].v[2] = uv_ratio; + + nfacesleft = 2; + + /* Right face - two triangles */ + cuberight[0].verts[0][0] = 0; + cuberight[0].verts[0][1] = sqrt_2; + cuberight[0].verts[0][2] = -1.0; + cuberight[0].u[0] = 0; + cuberight[0].v[0] = 0; + + cuberight[0].verts[1][0] = sqrt_2; + cuberight[0].verts[1][1] = 0; + cuberight[0].verts[1][2] = -1.0; + cuberight[0].u[1] = uv_ratio; + cuberight[0].v[1] = 0; + + cuberight[0].verts[2][0] = sqrt_2; + cuberight[0].verts[2][1] = 0; + cuberight[0].verts[2][2] = 1.0; + cuberight[0].u[2] = uv_ratio; + cuberight[0].v[2] = uv_ratio; + + //second triangle + cuberight[1].verts[0][0] = 0; + cuberight[1].verts[0][1] = sqrt_2; + cuberight[1].verts[0][2] = -1.0; + cuberight[1].u[0] = 0; + cuberight[1].v[0] = 0; + + cuberight[1].verts[1][0] = sqrt_2; + cuberight[1].verts[1][1] = 0; + cuberight[1].verts[1][2] = 1.0; + cuberight[1].u[1] = uv_ratio; + cuberight[1].v[1] = uv_ratio; + + cuberight[1].verts[2][0] = 0; + cuberight[1].verts[2][1] = sqrt_2; + cuberight[1].verts[2][2] = 1.0; + cuberight[1].u[2] = 0; + cuberight[1].v[2] = uv_ratio; + + nfacesright = 2; + + /* Right Back (-135º) face - two triangles */ + cuberightback[0].verts[0][0] = sqrt_2; + cuberightback[0].verts[0][1] = 0; + cuberightback[0].verts[0][2] = -1.0; + cuberightback[0].u[0] = 0; + cuberightback[0].v[0] = 0; + + cuberightback[0].verts[1][0] = 0; + cuberightback[0].verts[1][1] = -sqrt_2; + cuberightback[0].verts[1][2] = -1.0; + cuberightback[0].u[1] = uv_ratio; + cuberightback[0].v[1] = 0; + + cuberightback[0].verts[2][0] = 0; + cuberightback[0].verts[2][1] = -sqrt_2; + cuberightback[0].verts[2][2] = 1.0; + cuberightback[0].u[2] = uv_ratio; + cuberightback[0].v[2] = uv_ratio; + + //second triangle + cuberightback[1].verts[0][0] = sqrt_2; + cuberightback[1].verts[0][1] = 0; + cuberightback[1].verts[0][2] = -1.0; + cuberightback[1].u[0] = 0; + cuberightback[1].v[0] = 0; + + cuberightback[1].verts[1][0] = 0; + cuberightback[1].verts[1][1] = -sqrt_2; + cuberightback[1].verts[1][2] = 1.0; + cuberightback[1].u[1] = uv_ratio; + cuberightback[1].v[1] = uv_ratio; + + cuberightback[1].verts[2][0] = sqrt_2; + cuberightback[1].verts[2][1] = 0; + cuberightback[1].verts[2][2] = 1.0; + cuberightback[1].u[2] = 0; + cuberightback[1].v[2] = uv_ratio; + + nfacesrightback = 2; + + // Subdivide the faces + for(i=0;i<m_resolution;i++) + { + cubetop.resize(4*nfacestop); + SplitFace(cubetop,&nfacestop); + + cubebottom.resize(4*nfacesbottom); + SplitFace(cubebottom,&nfacesbottom); + + cubeleft.resize(4*nfacesleft); + SplitFace(cubeleft,&nfacesleft); + + cuberight.resize(4*nfacesright); + SplitFace(cuberight,&nfacesright); + + cubeleftback.resize(4*nfacesleftback); + SplitFace(cubeleftback,&nfacesleftback); + + cuberightback.resize(4*nfacesrightback); + SplitFace(cuberightback,&nfacesrightback); + } + + // Spherize the cube + for(j=0;j<3;j++) + { + for(i=0;i<nfacestop;i++) + cubetop[i].verts[j].normalize(); + + for(i=0;i<nfacesbottom;i++) + cubebottom[i].verts[j].normalize(); + + for(i=0;i<nfacesleftback;i++) + cubeleftback[i].verts[j].normalize(); + + for(i=0;i<nfacesleft;i++) + cubeleft[i].verts[j].normalize(); + + for(i=0;i<nfacesright;i++) + cuberight[i].verts[j].normalize(); + + for(i=0;i<nfacesrightback;i++) + cuberightback[i].verts[j].normalize(); + } + + //Flatten onto xz plane + for(i=0;i<nfacesleftback;i++) + FlattenPanorama(cubeleftback[i].verts); + + for(i=0;i<nfacesleft;i++) + FlattenPanorama(cubeleft[i].verts); + + for(i=0;i<nfacesright;i++) + FlattenPanorama(cuberight[i].verts); + + for(i=0;i<nfacesrightback;i++) + FlattenPanorama(cuberightback[i].verts); + + for(i=0;i<nfacestop;i++) + FlattenPanorama(cubetop[i].verts); + + for(i=0;i<nfacesbottom;i++) + FlattenPanorama(cubebottom[i].verts); +} + +void KX_Dome::FlattenDome(MT_Vector3 verts[3]) +{ + double phi, r; + + for (int i=0;i<3;i++){ + r = atan2(sqrt(verts[i][0]*verts[i][0] + verts[i][2]*verts[i][2]), verts[i][1]); + r /= m_radangle/2; + + phi = atan2(verts[i][2], verts[i][0]); + + verts[i][0] = r * cos(phi); + verts[i][1] = 0; + verts[i][2] = r * sin(phi); + + if (r > 1.0){ + //round the border + verts[i][0] = cos(phi); + verts[i][1] = -3.0; + verts[i][2] = sin(phi); + } + } +} + +void KX_Dome::FlattenPanorama(MT_Vector3 verts[3]) +{ +// it creates a full spherical panoramic (360º) + int i; + double phi; + bool edge=false; + + for (i=0;i<3;i++){ + phi = atan2(verts[i][1], verts[i][0]); + phi *= -1.0; //flipping + + if (phi == -MT_PI) //It's on the edge + edge=true; + + verts[i][0] = phi / MT_PI; + verts[i][1] = 0; + + verts[i][2] = atan2(verts[i][2], 1.0); + verts[i][2] /= MT_PI / 2; + } + if(edge){ + bool right=false; + + for (i=0;i<3;i++){ + if(fmod(verts[i][0],1.0) > 0.0){ + right=true; + break; + } + } + if(right){ + for (i=0;i<3;i++){ + if(verts[i][0] < 0.0) + verts[i][0] *= -1.0; + } + } + } +} + +void KX_Dome::SplitFace(vector <DomeFace>& face, int *nfaces) +{ + int i; + int n1, n2; + + n1 = n2 = *nfaces; + + for(i=0;i<n1;i++){ + + face[n2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2; + face[n2].verts[1] = face[i].verts[1]; + face[n2].verts[2] = (face[i].verts[1] + face[i].verts[2]) /2; + face[n2].u[0] = (face[i].u[0] + face[i].u[1]) /2; + face[n2].u[1] = face[i].u[1]; + face[n2].u[2] = (face[i].u[1] + face[i].u[2]) /2; + face[n2].v[0] = (face[i].v[0] + face[i].v[1]) /2; + face[n2].v[1] = face[i].v[1]; + face[n2].v[2] = (face[i].v[1] + face[i].v[2]) /2; + + face[n2+1].verts[0] = (face[i].verts[1] + face[i].verts[2]) /2; + face[n2+1].verts[1] = face[i].verts[2]; + face[n2+1].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2; + face[n2+1].u[0] = (face[i].u[1] + face[i].u[2]) /2; + face[n2+1].u[1] = face[i].u[2]; + face[n2+1].u[2] = (face[i].u[2] + face[i].u[0]) /2; + face[n2+1].v[0] = (face[i].v[1] + face[i].v[2]) /2; + face[n2+1].v[1] = face[i].v[2]; + face[n2+1].v[2] = (face[i].v[2] + face[i].v[0]) /2; + + face[n2+2].verts[0] = (face[i].verts[0] + face[i].verts[1]) /2; + face[n2+2].verts[1] = (face[i].verts[1] + face[i].verts[2]) /2; + face[n2+2].verts[2] = (face[i].verts[2] + face[i].verts[0]) /2; + face[n2+2].u[0] = (face[i].u[0] + face[i].u[1]) /2; + face[n2+2].u[1] = (face[i].u[1] + face[i].u[2]) /2; + face[n2+2].u[2] = (face[i].u[2] + face[i].u[0]) /2; + face[n2+2].v[0] = (face[i].v[0] + face[i].v[1]) /2; + face[n2+2].v[1] = (face[i].v[1] + face[i].v[2]) /2; + face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2; + + //face[i].verts[0] = face[i].verts[0] ; + face[i].verts[1] = (face[i].verts[0] + face[i].verts[1]) /2; + face[i].verts[2] = (face[i].verts[0] + face[i].verts[2]) /2; + //face[i].u[0] = face[i].u[0]; + face[i].u[1] = (face[i].u[0] + face[i].u[1]) /2; + face[i].u[2] = (face[i].u[0] + face[i].u[2]) /2; + //face[i].v[0] = face[i].v[0] ; + face[i].v[1] = (face[i].v[0] + face[i].v[1]) /2; + face[i].v[2] = (face[i].v[0] + face[i].v[2]) /2; + + n2 += 3; // number of faces + } + *nfaces = n2; +} + +void KX_Dome::CalculateFrustum(KX_Camera * cam) +{ + /* + // manually creating a 90º Field of View Frustum + + the original formula: + top = tan(fov*3.14159/360.0) * near [for fov in degrees] + fov*0.5 = arctan ((top-bottom)*0.5 / near) [for fov in radians] + bottom = -top + left = aspect * bottom + right = aspect * top + + // the equivalent GLU call is: + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(90.0,1.0,cam->GetCameraNear(),cam->GetCameraFar()); + */ + + RAS_FrameFrustum m_frustrum; //90 deg. Frustum + + m_frustrum.camnear = cam->GetCameraNear(); + m_frustrum.camfar = cam->GetCameraFar(); + +// float top = tan(90.0*MT_PI/360.0) * m_frustrum.camnear; + float top = m_frustrum.camnear; // for deg = 90º, tan = 1 + + m_frustrum.x1 = -top; + m_frustrum.x2 = top; + m_frustrum.y1 = -top; + m_frustrum.y2 = top; + + m_projmat = m_rasterizer->GetFrustumMatrix( + m_frustrum.x1, m_frustrum.x2, m_frustrum.y1, m_frustrum.y2, m_frustrum.camnear, m_frustrum.camfar); + +} + +void KX_Dome::CalculateCameraOrientation() +{ +/* +Uses 4 cameras for angles up to 180º +Uses 5 cameras for angles up to 250º +Uses 6 cameras for angles up to 360º +*/ + float deg45 = MT_PI / 4; + MT_Scalar c = cos(deg45); + MT_Scalar s = sin(deg45); + + if ((m_mode == DOME_FISHEYE && m_angle <= 180)|| m_mode == DOME_TRUNCATED){ + + m_locRot[0] = MT_Matrix3x3( // 90º - Top + c, -s, 0.0, + 0.0,0.0, -1.0, + s, c, 0.0); + + m_locRot[1] = MT_Matrix3x3( // 90º - Bottom + -s, c, 0.0, + 0.0,0.0, 1.0, + s, c, 0.0); + + m_locRot[2] = MT_Matrix3x3( // 45º - Left + c, 0.0, s, + 0, 1.0, 0.0, + -s, 0.0, c); + + m_locRot[3] = MT_Matrix3x3( // 45º - Right + c, 0.0, -s, + 0.0, 1.0, 0.0, + s, 0.0, c); + + } else if ((m_mode == DOME_FISHEYE && m_angle > 180)){ + + m_locRot[0] = MT_Matrix3x3( // 90º - Top + 1.0, 0.0, 0.0, + 0.0, 0.0,-1.0, + 0.0, 1.0, 0.0); + + m_locRot[1] = MT_Matrix3x3( // 90º - Bottom + 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, + 0.0,-1.0, 0.0); + + m_locRot[2] = MT_Matrix3x3( // -90º - Left + 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0, + -1.0, 0.0, 0.0); + + m_locRot[3] = MT_Matrix3x3( // 90º - Right + 0.0, 0.0,-1.0, + 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0); + + m_locRot[4] = MT_Matrix3x3( // 0º - Front + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0); + + m_locRot[5] = MT_Matrix3x3( // 180º - Back - NOT USING + -1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0,-1.0); + + } else if (m_mode == DOME_PANORAM_SPH){ + + m_locRot[0] = MT_Matrix3x3( // Top + c, s, 0.0, + 0.0,0.0, -1.0, + -s, c, 0.0); + + m_locRot[1] = MT_Matrix3x3( // Bottom + c, s, 0.0, + 0.0 ,0.0, 1.0, + s, -c, 0.0); + + m_locRot[2] = MT_Matrix3x3( // 45º - Left + -s, 0.0, c, + 0, 1.0, 0.0, + -c, 0.0, -s); + + m_locRot[3] = MT_Matrix3x3( // 45º - Right + c, 0.0, s, + 0, 1.0, 0.0, + -s, 0.0, c); + + m_locRot[4] = MT_Matrix3x3( // 135º - LeftBack + -s, 0.0, -c, + 0.0, 1.0, 0.0, + c, 0.0, -s); + + m_locRot[5] = MT_Matrix3x3( // 135º - RightBack + c, 0.0, -s, + 0.0, 1.0, 0.0, + s, 0.0, c); + } +} + +void KX_Dome::RotateCamera(KX_Camera* cam, int i) +{ +// I'm not using it, I'm doing inline calls for these commands +// but it's nice to have it here in case I need it + + MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation(); + + cam->NodeSetLocalOrientation(camori*m_locRot[i]); + cam->NodeUpdateGS(0.f); + + MT_Transform camtrans(cam->GetWorldToCamera()); + MT_Matrix4x4 viewmat(camtrans); + m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), + cam->GetCameraLocation(), cam->GetCameraOrientation()); + cam->SetModelviewMatrix(viewmat); + + // restore the original orientation + cam->NodeSetLocalOrientation(camori); + cam->NodeUpdateGS(0.f); +} + +void KX_Dome::Draw(void) +{ + + switch(m_mode){ + case DOME_FISHEYE: + DrawDomeFisheye(); + break; + case DOME_TRUNCATED: + DrawDomeFisheye(); + break; + case DOME_PANORAM_SPH: + DrawPanorama(); + break; + } + + if(warp.usemesh) + { + glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight); + DrawDomeWarped(); + } +} + +void KX_Dome::DrawDomeFisheye(void) +{ + int i,j; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Making the viewport always square + + int can_width = m_viewport.GetRight(); + int can_height = m_viewport.GetTop(); + + float ortho_width, ortho_height; + + if (warp.usemesh) + glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost + + else if(m_mode == DOME_TRUNCATED){ + ortho_width = 1.0; + ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; + + ortho_width /= m_size; + ortho_height /= m_size; + + glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0); + } else { + if (can_width < can_height){ + ortho_width = 1.0; + ortho_height = (float)can_height/can_width; + }else{ + ortho_width = (float)can_width/can_height; + ortho_height = 1.0; + } + + ortho_width /= m_size; + ortho_height /= m_size; + + glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); + + if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) + glPolygonMode(GL_FRONT, GL_LINE); + else + glPolygonMode(GL_FRONT, GL_FILL); + + glShadeModel(GL_SMOOTH); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glEnable(GL_TEXTURE_2D); + glColor3f(1.0,1.0,1.0); + + if (dlistSupported){ + for(i=0;i<m_numfaces;i++){ + glBindTexture(GL_TEXTURE_2D, domefacesId[i]); + glCallList(dlistId+i); + } + } + else { // DisplayLists not supported + // top triangle + glBindTexture(GL_TEXTURE_2D, domefacesId[0]); + GLDrawTriangles(cubetop, nfacestop); + + // bottom triangle + glBindTexture(GL_TEXTURE_2D, domefacesId[1]); + GLDrawTriangles(cubebottom, nfacesbottom); + + // left triangle + glBindTexture(GL_TEXTURE_2D, domefacesId[2]); + GLDrawTriangles(cubeleft, nfacesleft); + + // right triangle + glBindTexture(GL_TEXTURE_2D, domefacesId[3]); + GLDrawTriangles(cuberight, nfacesright); + + if (m_angle > 180){ + // front triangle + glBindTexture(GL_TEXTURE_2D, domefacesId[4]); + GLDrawTriangles(cubefront, nfacesfront); + } + } + glDisable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); +} + +void KX_Dome::DrawPanorama(void) +{ + int i,j; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Making the viewport always square + + int can_width = m_viewport.GetRight(); + int can_height = m_viewport.GetTop(); + + float ortho_height = 1.0; + float ortho_width = 1.0; + + if (warp.usemesh) + glOrtho((-1.0), 1.0, (-0.5), 0.5, -20.0, 10.0); //stretch the image to reduce resolution lost + + else { + //using all the screen + if ((can_width / 2) <= (can_height)){ + ortho_width = 1.0; + ortho_height = (float)can_height/can_width; + }else{ + ortho_width = (float)can_width/can_height * 0.5; + ortho_height = 0.5; + } + + ortho_width /= m_size; + ortho_height /= m_size; + + glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); + + if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) + glPolygonMode(GL_FRONT, GL_LINE); + else + glPolygonMode(GL_FRONT, GL_FILL); + + glShadeModel(GL_SMOOTH); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glEnable(GL_TEXTURE_2D); + glColor3f(1.0,1.0,1.0); + + if (dlistSupported){ + for(i=0;i<m_numfaces;i++){ + glBindTexture(GL_TEXTURE_2D, domefacesId[i]); + glCallList(dlistId+i); + } + } + else { + // domefacesId[4] => (top) + glBindTexture(GL_TEXTURE_2D, domefacesId[0]); + GLDrawTriangles(cubetop, nfacestop); + + // domefacesId[5] => (bottom) + glBindTexture(GL_TEXTURE_2D, domefacesId[1]); + GLDrawTriangles(cubebottom, nfacesbottom); + + // domefacesId[1] => -45º (left) + glBindTexture(GL_TEXTURE_2D, domefacesId[2]); + GLDrawTriangles(cubeleft, nfacesleft); + + // domefacesId[2] => 45º (right) + glBindTexture(GL_TEXTURE_2D, domefacesId[3]); + GLDrawTriangles(cuberight, nfacesright); + + // domefacesId[0] => -135º (leftback) + glBindTexture(GL_TEXTURE_2D, domefacesId[4]); + GLDrawTriangles(cubeleftback, nfacesleftback); + + // domefacesId[3] => 135º (rightback) + glBindTexture(GL_TEXTURE_2D, domefacesId[5]); + GLDrawTriangles(cuberightback, nfacesrightback); + } + glDisable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); +} + +void KX_Dome::DrawDomeWarped(void) +{ + int i,j; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Making the viewport always square + int can_width = m_viewport.GetRight(); + int can_height = m_viewport.GetTop(); + + double screen_ratio = can_width/ (double) can_height; + screen_ratio /= m_size; + + glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0); + + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 1.0, 0.0,0.0,0.0, 0.0,1.0,0.0); + + if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) + glPolygonMode(GL_FRONT, GL_LINE); + else + glPolygonMode(GL_FRONT, GL_FILL); + + glShadeModel(GL_SMOOTH); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glEnable(GL_TEXTURE_2D); + glColor3f(1.0,1.0,1.0); + + + float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth; + float uv_height = (float)(warp.bufferheight-1) / warp.imageheight; + + if (dlistSupported){ + glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); + glCallList(dlistId + m_numfaces); + } + else{ + glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); + GLDrawWarpQuads(); + } + glDisable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); +} + +void KX_Dome::BindImages(int i) +{ + glBindTexture(GL_TEXTURE_2D, domefacesId[i]); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), m_buffersize, m_buffersize); +} + +void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) +{ + if (!cam) + return; + + m_canvas->SetViewPort(0,0,m_buffersize-1,m_buffersize-1); + +// m_rasterizer->SetAmbient(); + m_rasterizer->DisplayFog(); + + CalculateFrustum(cam); //calculates m_projmat + cam->SetProjectionMatrix(m_projmat); + m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix()); +// Dome_RotateCamera(cam,i); + + MT_Matrix3x3 camori = cam->GetSGNode()->GetLocalOrientation(); + + cam->NodeSetLocalOrientation(camori*m_locRot[i]); + cam->NodeUpdateGS(0.f); + + MT_Transform camtrans(cam->GetWorldToCamera()); + MT_Matrix4x4 viewmat(camtrans); + m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), + cam->GetCameraLocation(), cam->GetCameraOrientation()); + cam->SetModelviewMatrix(viewmat); + + scene->CalculateVisibleMeshes(m_rasterizer,cam); + scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); + + // restore the original orientation + cam->NodeSetLocalOrientation(camori); + cam->NodeUpdateGS(0.f); +}
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h new file mode 100644 index 00000000000..786e04b4385 --- /dev/null +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -0,0 +1,183 @@ +/* $Id$ +----------------------------------------------------------------------------- + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA, or go to +http://www.gnu.org/copyleft/lesser.txt. + +Contributor(s): Dalai Felinto + +This source uses some of the ideas and code from Paul Bourke. +Developed as part of a Research and Development project for SAT - La Société des arts technologiques. +----------------------------------------------------------------------------- +*/ + +#if !defined KX_DOME_H +#define KX_DOME_H + +#include "KX_Scene.h" +#include "KX_Camera.h" +#include "DNA_screen_types.h" +#include "RAS_ICanvas.h" +#include "RAS_IRasterizer.h" +#include "RAS_IRenderTools.h" +#include "KX_KetsjiEngine.h" + +#include "GL/glew.h" +#include <vector> + +#include "MEM_guardedalloc.h" +#include "BKE_text.h" +//#include "BLI_blenlib.h" + +//Dome modes: limit hardcoded in buttons_scene.c +#define DOME_FISHEYE 1 +#define DOME_TRUNCATED 2 +#define DOME_PANORAM_SPH 3 +#define DOME_NUM_MODES 4 + + +/// class for render 3d scene +class KX_Dome +{ +public: + /// constructor + KX_Dome ( + RAS_ICanvas* m_canvas, + /// rasterizer + RAS_IRasterizer* m_rasterizer, + /// render tools + RAS_IRenderTools* m_rendertools, + /// engine + KX_KetsjiEngine* m_engine, + + float size, + short res, + short mode, + short angle, + float resbuf, + struct Text* warptext + ); + + /// destructor + virtual ~KX_Dome (void); + + //openGL checks: + bool dlistSupported; + + //openGL names: + GLuint domefacesId[7]; // ID of the images -- room for 7 images, using only 4 for 180º x 360º dome, 6 for panoramic and +1 for warp mesh + GLuint dlistId; // ID of the Display Lists of the images (used as an offset) + + typedef struct { + double u[3], v[3]; + MT_Vector3 verts[3]; //three verts + } DomeFace; + + //mesh warp functions + typedef struct { + double x, y, u, v, i; + } WarpMeshNode; + + struct { + bool usemesh; + int mode; + int n_width, n_height; //nodes width and height + int imagewidth, imageheight; + int bufferwidth, bufferheight; + vector <vector <WarpMeshNode> > nodes; + } warp; + + bool ParseWarpMesh(STR_String text); + + vector <DomeFace> cubetop, cubebottom, cuberight, cubeleft, cubefront, cubeback; //for fisheye + vector <DomeFace> cubeleftback, cuberightback; //for panorama + + int nfacestop, nfacesbottom, nfacesleft, nfacesright, nfacesfront, nfacesback; + int nfacesleftback, nfacesrightback; + + int GetNumberRenders(){return m_numfaces;}; + + void RenderDome(void); + void RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i); + void BindImages(int i); + + void SetViewPort(GLuint viewport[4]); + void CalculateFrustum(KX_Camera* cam); + void RotateCamera(KX_Camera* cam, int i); + + //Mesh Creating Functions + void CreateMeshDome180(void); + void CreateMeshDome250(void); + void CreateMeshPanorama(void); + + void SplitFace(vector <DomeFace>& face, int *nfaces); + + void FlattenDome(MT_Vector3 verts[3]); + void FlattenPanorama(MT_Vector3 verts[3]); + + //Draw functions + void GLDrawTriangles(vector <DomeFace>& face, int nfaces); + void GLDrawWarpQuads(void); + void Draw(void); + void DrawDomeFisheye(void); + void DrawPanorama(void); + void DrawDomeWarped(void); + + //setting up openGL + void CreateGLImages(void); + void ClearGLImages(void);//called on resize + bool CreateDL(void); //create Display Lists + void ClearDL(void); //remove Display Lists + + void CalculateCameraOrientation(); + void CalculateImageSize(); //set m_imagesize + + int canvaswidth; + int canvasheight; + +protected: + int m_drawingmode; + + int m_imagesize; + int m_buffersize; // canvas small dimension + int m_numfaces; // 4 to 6 depending on the kind of dome image + int m_numimages; //numfaces +1 if we have warp mesh + + float m_size; // size to adjust + short m_resolution; //resolution to tesselate the mesh + short m_mode; // the mode (truncated, warped, panoramic,...) + short m_angle; //the angle of the fisheye + float m_radangle; //the angle of the fisheye in radians + float m_resbuffer; //the resolution of the buffer + + RAS_Rect m_viewport; + + MT_Matrix4x4 m_projmat; + + MT_Matrix3x3 m_locRot [6];// the rotation matrix + + /// rendered scene + KX_Scene * m_scene; + + /// canvas + RAS_ICanvas* m_canvas; + /// rasterizer + RAS_IRasterizer* m_rasterizer; + /// render tools + RAS_IRenderTools* m_rendertools; + /// engine + KX_KetsjiEngine* m_engine; +}; + +#endif diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 3c0695b5952..8b587c6f7de 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -208,22 +208,22 @@ bool KX_GameActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_GameActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_GameActuator", - sizeof(KX_GameActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -241,21 +241,38 @@ PyParentObject KX_GameActuator::Parents[] = PyMethodDef KX_GameActuator::Methods[] = { + // Deprecated -----> {"getFile", (PyCFunction) KX_GameActuator::sPyGetFile, METH_VARARGS, (PY_METHODCHAR)GetFile_doc}, {"setFile", (PyCFunction) KX_GameActuator::sPySetFile, METH_VARARGS, (PY_METHODCHAR)SetFile_doc}, + // <----- {NULL,NULL} //Sentinel }; PyAttributeDef KX_GameActuator::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW("file",0,100,false,KX_GameActuator,m_filename), { NULL } //Sentinel }; +PyObject* +KX_GameActuator::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_IActuator); +} + +int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_IActuator); +} + + +// Deprecated -----> /* getFile */ const char KX_GameActuator::GetFile_doc[] = "getFile()\n" "get the name of the file to start.\n"; -PyObject* KX_GameActuator::PyGetFile(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_GameActuator::PyGetFile(PyObject* args, PyObject* kwds) { + ShowDeprecationWarning("getFile()", "the file property"); return PyString_FromString(m_filename); } @@ -263,11 +280,13 @@ PyObject* KX_GameActuator::PyGetFile(PyObject* self, PyObject* args, PyObject* k const char KX_GameActuator::SetFile_doc[] = "setFile(name)\n" "set the name of the file to start.\n"; -PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_GameActuator::PySetFile(PyObject* args, PyObject* kwds) { char* new_file; + + ShowDeprecationWarning("setFile()", "the file property"); - if (!PyArg_ParseTuple(args, "s", &new_file)) + if (!PyArg_ParseTuple(args, "s:setFile", &new_file)) { return NULL; } @@ -277,12 +296,4 @@ PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* k Py_RETURN_NONE; } - - - -PyObject* KX_GameActuator::_getattr(const char *attr) -{ - _getattr_up(SCA_IActuator); -} - - +// <----- diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index 856fa0c24e9..570cb2e68ef 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -77,9 +77,13 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + + // Deprecated functions -----> KX_PYMETHOD_DOC(KX_GameActuator,GetFile); KX_PYMETHOD_DOC(KX_GameActuator,SetFile); + // <----- }; /* end of class KX_GameActuator */ diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 95df9d51a26..bea0fcff2af 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -55,6 +55,7 @@ typedef unsigned long uint_ptr; #include <stdio.h> // printf #include "SG_Controller.h" #include "KX_IPhysicsController.h" +#include "PHY_IGraphicController.h" #include "SG_Node.h" #include "SG_Controller.h" #include "KX_ClientObjectInfo.h" @@ -64,6 +65,8 @@ typedef unsigned long uint_ptr; #include "KX_PyMath.h" #include "SCA_IActuator.h" #include "SCA_ISensor.h" +#include "SCA_IController.h" +#include "NG_NetworkScene.h" //Needed for sendMessage() #include "PyObjectPlus.h" /* python stuff */ @@ -72,6 +75,12 @@ typedef unsigned long uint_ptr; #include "KX_SG_NodeRelationships.h" +static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0); +static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0); +static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0); + KX_GameObject::KX_GameObject( void* sgReplicationInfo, SG_Callbacks callbacks, @@ -87,11 +96,14 @@ KX_GameObject::KX_GameObject( m_bIsNegativeScaling(false), m_bVisible(true), m_bCulled(true), + m_bOccluder(false), m_pPhysicsController1(NULL), + m_pGraphicController(NULL), m_pPhysicsEnvironment(NULL), m_xray(false), m_pHitObject(NULL), - m_isDeformable(false) + m_isDeformable(false), + m_attr_dict(NULL) { m_ignore_activity_culling = false; m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR); @@ -129,9 +141,23 @@ KX_GameObject::~KX_GameObject() } m_pSGNode->SetSGClientObject(NULL); } + if (m_pGraphicController) + { + delete m_pGraphicController; + } + + if (m_attr_dict) { + PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */ + Py_DECREF(m_attr_dict); + } } - +KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info) +{ + if (!info) + return NULL; + return info->m_gameobject; +} CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) { @@ -154,7 +180,7 @@ const STR_String & KX_GameObject::GetText() -float KX_GameObject::GetNumber() +double KX_GameObject::GetNumber() { return 0; } @@ -246,7 +272,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) NodeSetLocalScale(scale1); NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); NodeSetLocalOrientation(invori*NodeGetWorldOrientation()); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); // object will now be a child, it must be removed from the parent list CListValue* rootlist = scene->GetRootParentList(); if (rootlist->RemoveValue(this)) @@ -266,6 +292,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1); } } + // graphically, the object hasn't change place, no need to update m_pGraphicController } } @@ -283,7 +310,7 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) // Remove us from our parent GetSGNode()->DisconnectFromParent(); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); // the object is now a root object, add it to the parentlist CListValue* rootlist = scene->GetRootParentList(); if (!rootlist->SearchValue(this)) @@ -300,16 +327,21 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) } m_pPhysicsController1->RestoreDynamics(); } + // graphically, the object hasn't change place, no need to update m_pGraphicController } } void KX_GameObject::ProcessReplica(KX_GameObject* replica) { replica->m_pPhysicsController1 = NULL; + replica->m_pGraphicController = NULL; replica->m_pSGNode = NULL; replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); replica->m_pClient_info->m_gameobject = replica; replica->m_state = 0; + if(m_attr_dict) + replica->m_attr_dict= PyDict_Copy(m_attr_dict); + } @@ -345,11 +377,14 @@ void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local) void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local) { - if (m_pPhysicsController1) // (IsDynamic()) + if (GetSGNode()) { - m_pPhysicsController1->RelativeTranslate(dloc,local); + if (m_pPhysicsController1) // (IsDynamic()) + { + m_pPhysicsController1->RelativeTranslate(dloc,local); + } + GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local); } - GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local); } @@ -357,11 +392,13 @@ void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local) void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local) { MT_Matrix3x3 rotmat(drot); + + if (GetSGNode()) { + GetSGNode()->RelativeRotate(rotmat,local); - GetSGNode()->RelativeRotate(rotmat,local); - - if (m_pPhysicsController1) { // (IsDynamic()) - m_pPhysicsController1->RelativeRotate(rotmat,local); + if (m_pPhysicsController1) { // (IsDynamic()) + m_pPhysicsController1->RelativeRotate(rotmat,local); + } } } @@ -374,16 +411,17 @@ double* KX_GameObject::GetOpenGLMatrix() { // todo: optimize and only update if necessary double* fl = m_OpenGL_4x4Matrix.getPointer(); - MT_Transform trans; + if (GetSGNode()) { + MT_Transform trans; - trans.setOrigin(GetSGNode()->GetWorldPosition()); - trans.setBasis(GetSGNode()->GetWorldOrientation()); + trans.setOrigin(GetSGNode()->GetWorldPosition()); + trans.setBasis(GetSGNode()->GetWorldOrientation()); - MT_Vector3 scaling = GetSGNode()->GetWorldScaling(); - m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false; - trans.scale(scaling[0], scaling[1], scaling[2]); - trans.getValue(fl); - + MT_Vector3 scaling = GetSGNode()->GetWorldScaling(); + m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false; + trans.scale(scaling[0], scaling[1], scaling[2]); + trans.getValue(fl); + } return fl; } @@ -414,13 +452,15 @@ static void UpdateBuckets_recursive(SG_Node* node) void KX_GameObject::UpdateBuckets( bool recursive ) { - double* fl = GetOpenGLMatrix(); + if (GetSGNode()) { + double* fl = GetOpenGLMatrixPtr()->getPointer(); - for (size_t i=0;i<m_meshes.size();i++) - m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); + for (size_t i=0;i<m_meshes.size();i++) + m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); - if (recursive) { - UpdateBuckets_recursive(m_pSGNode); + if (recursive) { + UpdateBuckets_recursive(GetSGNode()); + } } } @@ -434,22 +474,18 @@ void KX_GameObject::RemoveMeshes() m_meshes.clear(); } - - -void KX_GameObject::UpdateNonDynas() +void KX_GameObject::UpdateTransform() { if (m_pPhysicsController1) - { + // only update the transform of static object, dynamic object are handled differently + // note that for bullet, this does not even update the transform of static object + // but merely sets there collision flag to "kinematic" because the synchronization is + // done differently during physics simulation m_pPhysicsController1->SetSumoTransform(true); - } -} - - + if (m_pGraphicController) + // update the culling tree + m_pGraphicController->SetGraphicTransform(); -void KX_GameObject::UpdateTransform() -{ - if (m_pPhysicsController1) - m_pPhysicsController1->SetSumoTransform(false); } void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene) @@ -575,28 +611,43 @@ KX_GameObject::SetVisible( bool recursive ) { - m_bVisible = v; - if (recursive) - setVisible_recursive(m_pSGNode, v); + if (GetSGNode()) { + m_bVisible = v; + if (recursive) + setVisible_recursive(GetSGNode(), v); + } } -bool -KX_GameObject::GetCulled( - void - ) +static void setOccluder_recursive(SG_Node* node, bool v) { - return m_bCulled; + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->SetOccluder(v, false); + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + setOccluder_recursive(childnode, v); + } } void -KX_GameObject::SetCulled( - bool c +KX_GameObject::SetOccluder( + bool v, + bool recursive ) { - m_bCulled = c; + if (GetSGNode()) { + m_bOccluder = v; + if (recursive) + setOccluder_recursive(GetSGNode(), v); + } } - void KX_GameObject::SetLayer( int l @@ -764,6 +815,16 @@ MT_Scalar KX_GameObject::GetMass() return 0.0; } +MT_Vector3 KX_GameObject::GetLocalInertia() +{ + MT_Vector3 local_inertia(0.0,0.0,0.0); + if (m_pPhysicsController1) + { + local_inertia = m_pPhysicsController1->GetLocalInertia(); + } + return local_inertia; +} + MT_Vector3 KX_GameObject::GetLinearVelocity(bool local) { MT_Vector3 velocity(0.0,0.0,0.0), locvel; @@ -829,6 +890,7 @@ void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) } GetSGNode()->SetLocalPosition(trans); + } @@ -883,7 +945,9 @@ void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale) void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans) { - SG_Node* parent = m_pSGNode->GetSGParent(); + if (!GetSGNode()) + return; + SG_Node* parent = GetSGNode()->GetSGParent(); if (parent != NULL) { // Make sure the objects have some scale @@ -908,7 +972,7 @@ void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans) } -void KX_GameObject::NodeUpdateGS(double time,bool bInitiator) +void KX_GameObject::NodeUpdateGS(double time) { if (GetSGNode()) GetSGNode()->UpdateWorldData(time); @@ -918,13 +982,9 @@ void KX_GameObject::NodeUpdateGS(double time,bool bInitiator) const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const { - static MT_Matrix3x3 defaultOrientation = MT_Matrix3x3( 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0); - // check on valid node in case a python controller holds a reference to a deleted object if (!GetSGNode()) - return defaultOrientation; + return dummy_orientation; return GetSGNode()->GetWorldOrientation(); } @@ -932,11 +992,9 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const { - static MT_Vector3 defaultScaling = MT_Vector3(1.0, 1.0, 1.0); - // check on valid node in case a python controller holds a reference to a deleted object if (!GetSGNode()) - return defaultScaling; + return dummy_scaling; return GetSGNode()->GetWorldScaling(); } @@ -949,7 +1007,7 @@ const MT_Point3& KX_GameObject::NodeGetWorldPosition() const if (GetSGNode()) return GetSGNode()->GetWorldPosition(); else - return MT_Point3(0.0, 0.0, 0.0); + return dummy_point; } /* Suspend/ resume: for the dynamic behaviour, there is a simple @@ -963,7 +1021,8 @@ void KX_GameObject::Resume(void) { if (m_suspended) { SCA_IObject::Resume(); - GetPhysicsController()->RestoreDynamics(); + if(GetPhysicsController()) + GetPhysicsController()->RestoreDynamics(); m_suspended = false; } @@ -974,22 +1033,54 @@ void KX_GameObject::Suspend() if ((!m_ignore_activity_culling) && (!m_suspended)) { SCA_IObject::Suspend(); - GetPhysicsController()->SuspendDynamics(); + if(GetPhysicsController()) + GetPhysicsController()->SuspendDynamics(); m_suspended = true; } } +static void walk_children(SG_Node* node, CListValue* list, bool recursive) +{ + if (!node) + return; + NodeList& children = node->GetSGChildren(); + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + CValue* childobj = (CValue*)childnode->GetSGClientObject(); + if (childobj != NULL) // This is a GameObject + { + // add to the list + list->Add(childobj->AddRef()); + } + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + if (recursive || childobj==NULL) { + walk_children(childnode, list, recursive); + } + } +} +CListValue* KX_GameObject::GetChildren() +{ + CListValue* list = new CListValue(); + walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */ + return list; +} -/* ------- python stuff ---------------------------------------------------*/ - +CListValue* KX_GameObject::GetChildrenRecursive() +{ + CListValue* list = new CListValue(); + walk_children(GetSGNode(), list, 1); + return list; +} +/* ------- python stuff ---------------------------------------------------*/ PyMethodDef KX_GameObject::Methods[] = { - {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, - {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"applyForce", (PyCFunction) KX_GameObject::sPyApplyForce, METH_VARARGS}, {"applyTorque", (PyCFunction) KX_GameObject::sPyApplyTorque, METH_VARARGS}, @@ -1000,14 +1091,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS}, {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS}, - {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS}, {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, - {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, - {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, - {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS}, - {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, - {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS}, - {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, @@ -1016,25 +1100,66 @@ PyMethodDef KX_GameObject::Methods[] = { {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS}, {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O}, - {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS}, {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O}, + {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, + {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS}, {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS}, {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS}, {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS}, - {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS}, {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS}, {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS}, {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O}, {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS}, + KX_PYMETHODTABLE(KX_GameObject, rayCastTo), KX_PYMETHODTABLE(KX_GameObject, rayCast), KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), + KX_PYMETHODTABLE(KX_GameObject, sendMessage), + + // deprecated + {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, + {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, + {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, + {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, + {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS}, + {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O}, + {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS}, + {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS}, + {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS}, + {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS}, {NULL,NULL} //Sentinel }; PyAttributeDef KX_GameObject::Attributes[] = { - { NULL } //Sentinel + KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), + KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), + KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), + KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), + KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), + KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), + KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), + KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_worldPosition, pyattr_set_localPosition), + KX_PYATTRIBUTE_RO_FUNCTION("localInertia", KX_GameObject, pyattr_get_localInertia), + KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation), + KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling), + KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset), + KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state), + KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes), + KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation), + KX_PYATTRIBUTE_RO_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation), + KX_PYATTRIBUTE_RW_FUNCTION("localPosition", KX_GameObject, pyattr_get_localPosition, pyattr_set_localPosition), + KX_PYATTRIBUTE_RW_FUNCTION("worldPosition", KX_GameObject, pyattr_get_worldPosition, pyattr_set_worldPosition), + KX_PYATTRIBUTE_RW_FUNCTION("localScaling", KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling), + KX_PYATTRIBUTE_RO_FUNCTION("worldScaling", KX_GameObject, pyattr_get_worldScaling), + + KX_PYATTRIBUTE_RO_FUNCTION("__dict__", KX_GameObject, pyattr_get_dir_dict), + + /* Experemental, dont rely on these yet */ + KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors), + KX_PYATTRIBUTE_RO_FUNCTION("controllers", KX_GameObject, pyattr_get_controllers), + KX_PYATTRIBUTE_RO_FUNCTION("actuators", KX_GameObject, pyattr_get_actuators), + {NULL} //Sentinel }; @@ -1054,29 +1179,19 @@ bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args, } */ -PyObject* KX_GameObject::PyReplaceMesh(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PyReplaceMesh(PyObject* value) { KX_Scene *scene = KX_GetActiveScene(); - char* meshname; - void* mesh_pt; - - meshname = PyString_AsString(value); - if (meshname==NULL) { - PyErr_SetString(PyExc_ValueError, "Expected a mesh name"); - return NULL; - } - mesh_pt = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); + RAS_MeshObject* new_mesh; - if (mesh_pt==NULL) { - PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist"); + if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject")) return NULL; - } - scene->ReplaceMesh(this, (class RAS_MeshObject*)mesh_pt); + scene->ReplaceMesh(this, new_mesh); Py_RETURN_NONE; } -PyObject* KX_GameObject::PyEndObject(PyObject* self) +PyObject* KX_GameObject::PyEndObject() { KX_Scene *scene = KX_GetActiveScene(); @@ -1087,34 +1202,183 @@ PyObject* KX_GameObject::PyEndObject(PyObject* self) } -PyObject* KX_GameObject::PyGetPosition(PyObject* self) +PyObject* KX_GameObject::PyGetPosition() { + ShowDeprecationWarning("getPosition()", "the position property"); return PyObjectFrom(NodeGetWorldPosition()); } +Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v) +{ + KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); + + if (self==NULL) /* not sure what to do here */ + return 0; + + Py_ssize_t len= self->GetPropertyCount(); + if(self->m_attr_dict) + len += PyDict_Size(self->m_attr_dict); + return len; +} + + +PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) +{ + KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); + const char *attr_str= PyString_AsString(item); + CValue* resultattr; + PyObject* pyconvert; + + if (self==NULL) { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + /* first see if the attributes a string and try get the cvalue attribute */ + if(attr_str && (resultattr=self->GetProperty(attr_str))) { + pyconvert = resultattr->ConvertValueToPython(); + return pyconvert ? pyconvert:resultattr->GetProxy(); + } + /* no CValue attribute, try get the python only m_attr_dict attribute */ + else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) { + + if (attr_str) + PyErr_Clear(); + Py_INCREF(pyconvert); + return pyconvert; + } + else { + if(attr_str) PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str); + else PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist"); + return NULL; + } + +} + + +int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) +{ + KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); + const char *attr_str= PyString_AsString(key); + if(attr_str==NULL) + PyErr_Clear(); + + if (self==NULL) { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + return -1; + } + + if (val==NULL) { /* del ob["key"] */ + int del= 0; + + /* try remove both just incase */ + if(attr_str) + del |= (self->RemoveProperty(attr_str)==true) ? 1:0; + + if(self->m_attr_dict) + del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0; + + if (del==0) { + if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str); + else PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key could not be set"); + return -1; + } + else if (self->m_attr_dict) { + PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */ + } + } + else { /* ob["key"] = value */ + int set= 0; + + /* as CValue */ + if(attr_str) + { + CValue* vallie = self->ConvertPythonToValue(val); + + if(vallie) + { + CValue* oldprop = self->GetProperty(attr_str); + + if (oldprop) + oldprop->SetValue(vallie); + else + self->SetProperty(attr_str, vallie); + + vallie->Release(); + set= 1; + + /* try remove dict value to avoid double ups */ + if (self->m_attr_dict){ + if (PyDict_DelItem(self->m_attr_dict, key) != 0) + PyErr_Clear(); + } + } + else { + PyErr_Clear(); + } + } + + if(set==0) + { + if (self->m_attr_dict==NULL) /* lazy init */ + self->m_attr_dict= PyDict_New(); + + + if(PyDict_SetItem(self->m_attr_dict, key, val)==0) + { + if(attr_str) + self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */ + set= 1; + } + else { + if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str); + else PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary"); + } + } + + if(set==0) + return -1; /* pythons error value */ + + } + + return 0; /* success */ +} + + +PyMappingMethods KX_GameObject::Mapping = { + (lenfunc)KX_GameObject::Map_Len, /*inquiry mp_length */ + (binaryfunc)KX_GameObject::Map_GetItem, /*binaryfunc mp_subscript */ + (objobjargproc)KX_GameObject::Map_SetItem, /*objobjargproc mp_ass_subscript */ +}; + PyTypeObject KX_GameObject::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_GameObject", - sizeof(KX_GameObject), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0, + &Mapping, + 0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; + + + PyParentObject KX_GameObject::Parents[] = { &KX_GameObject::Type, &SCA_IObject::Type, @@ -1122,181 +1386,448 @@ PyParentObject KX_GameObject::Parents[] = { NULL }; +PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + return PyString_FromString(self->GetName().ReadPtr()); +} +PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_GameObject* parent = self->GetParent(); + if (parent) + return parent->GetProxy(); + Py_RETURN_NONE; +} +PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f); +} -PyObject* KX_GameObject::_getattr(const char *attr) +int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - if (m_pPhysicsController1) - { - if (!strcmp(attr, "mass")) - return PyFloat_FromDouble(m_pPhysicsController1->GetMass()); + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above"); + return 1; } - if (!strcmp(attr, "parent")) - { - KX_GameObject* parent = GetParent(); - if (parent) - return parent->AddRef(); - Py_RETURN_NONE; + if (spc) + spc->SetMass(val); + + return 0; +} + +PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); +} + +int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above"); + return 1; } - if (!strcmp(attr, "visible")) - return PyInt_FromLong(m_bVisible); - - if (!strcmp(attr, "position")) - return PyObjectFrom(NodeGetWorldPosition()); - - if (!strcmp(attr, "orientation")) - return PyObjectFrom(NodeGetWorldOrientation()); + if (spc) + spc->SetLinVelocityMin(val); + + return 0; +} + +PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); +} + +int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above"); + return 1; + } + + if (spc) + spc->SetLinVelocityMax(val); + + return 0; +} + + +PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + return PyBool_FromLong(self->GetVisible()); +} + +int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + int param = PyObject_IsTrue( value ); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False"); + return 1; + } + + self->SetVisible(param, false); + self->UpdateBuckets(false); + return 0; +} + +PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + return PyObjectFrom(self->NodeGetWorldPosition()); +} + +int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + MT_Point3 pos; + if (!PyVecTo(value, pos)) + return 1; - if (!strcmp(attr, "scaling")) - return PyObjectFrom(NodeGetWorldScaling()); - - if (!strcmp(attr, "name")) - return PyString_FromString(m_name.ReadPtr()); + self->NodeSetWorldPosition(pos); + self->NodeUpdateGS(0.f); + return 0; +} + +PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + if (self->GetSGNode()) + return PyObjectFrom(self->GetSGNode()->GetLocalPosition()); + else + return PyObjectFrom(dummy_point); +} + +int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + MT_Point3 pos; + if (!PyVecTo(value, pos)) + return 1; - if (!strcmp(attr, "timeOffset")) + self->NodeSetLocalPosition(pos); + self->NodeUpdateGS(0.f); + return 0; +} + +PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + if (self->GetPhysicsController()) { - if (m_pSGNode->GetSGParent()->IsSlowParent()) { - return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset()); - } else { - return PyFloat_FromDouble(0.0); - } + return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia()); } + return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); +} + +PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + return PyObjectFrom(self->NodeGetWorldOrientation()); +} + +PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + if (self->GetSGNode()) + return PyObjectFrom(self->GetSGNode()->GetLocalOrientation()); + else + return PyObjectFrom(dummy_orientation); +} + +int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); - - _getattr_up(SCA_IObject); + /* if value is not a sequence PyOrientationTo makes an error */ + MT_Matrix3x3 rot; + if (!PyOrientationTo(value, rot, "gameOb.orientation = sequence: KX_GameObject, ")) + return NULL; + + self->NodeSetLocalOrientation(rot); + self->NodeUpdateGS(0.f); + return 0; +} + +PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + return PyObjectFrom(self->NodeGetWorldScaling()); +} + +PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + if (self->GetSGNode()) + return PyObjectFrom(self->GetSGNode()->GetLocalScale()); + else + return PyObjectFrom(dummy_scaling); +} + +int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + MT_Vector3 scale; + if (!PyVecTo(value, scale)) + return 1; + + self->NodeSetLocalScale(scale); + self->NodeUpdateGS(0.f); + return 0; +} + +PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + SG_Node* sg_parent; + if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) { + return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset()); + } else { + return PyFloat_FromDouble(0.0); + } +} + +int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + if (self->GetSGNode()) { + MT_Scalar val = PyFloat_AsDouble(value); + SG_Node* sg_parent= self->GetSGNode()->GetSGParent(); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above"); + return 1; + } + if (sg_parent && sg_parent->IsSlowParent()) + static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val); + } + return 0; } -int KX_GameObject::_setattr(const char *attr, PyObject *value) // _setattr method +PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + int state = 0; + state |= self->GetState(); + return PyInt_FromLong(state); +} + +int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + int state_i = PyInt_AsLong(value); + unsigned int state = 0; - if (!strcmp(attr, "parent")) { - PyErr_SetString(PyExc_AttributeError, "attribute \"parent\" is read only\nUse setParent()"); + if (state_i == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field"); return 1; } - - if (PyInt_Check(value)) + + state |= state_i; + if ((state & ((1<<30)-1)) == 0) { + PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)"); + return 1; + } + self->SetState(state); + return 0; +} + +PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + PyObject *meshes= PyList_New(self->m_meshes.size()); + int i; + + for(i=0; i < self->m_meshes.size(); i++) { - int val = PyInt_AsLong(value); - if (!strcmp(attr, "visible")) - { - SetVisible(val != 0, false); - UpdateBuckets(false); - return 0; - } + KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]); + PyList_SET_ITEM(meshes, i, meshproxy->GetProxy()); } + + return meshes; +} - if (PyFloat_Check(value)) +/* experemental! */ +PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + SCA_SensorList& sensors= self->GetSensors(); + PyObject* resultlist = PyList_New(sensors.size()); + + for (unsigned int index=0;index<sensors.size();index++) + PyList_SET_ITEM(resultlist, index, sensors[index]->GetProxy()); + + return resultlist; +} + +PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + SCA_ControllerList& controllers= self->GetControllers(); + PyObject* resultlist = PyList_New(controllers.size()); + + for (unsigned int index=0;index<controllers.size();index++) + PyList_SET_ITEM(resultlist, index, controllers[index]->GetProxy()); + + return resultlist; +} + +PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + SCA_ActuatorList& actuators= self->GetActuators(); + PyObject* resultlist = PyList_New(actuators.size()); + + for (unsigned int index=0;index<actuators.size();index++) + PyList_SET_ITEM(resultlist, index, actuators[index]->GetProxy()); + + return resultlist; +} + +/* __dict__ only for the purpose of giving useful dir() results */ +PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + PyObject *dict_str = PyString_FromString("__dict__"); + PyObject *dict= py_getattr_dict(self->SCA_IObject::py_getattro(dict_str), Type.tp_dict); + Py_DECREF(dict_str); + + if(dict==NULL) + return NULL; + + /* Not super fast getting as a list then making into dict keys but its only for dir() */ + PyObject *list= self->ConvertKeysToPython(); + if(list) { - MT_Scalar val = PyFloat_AsDouble(value); - if (!strcmp(attr, "timeOffset")) { - if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) { - static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val); - return 0; - } else { - return 0; - } - } - if (!strcmp(attr, "mass")) { - if (m_pPhysicsController1) - m_pPhysicsController1->SetMass(val); - return 0; - } + int i; + for(i=0; i<PyList_Size(list); i++) + PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None); } + else + PyErr_Clear(); + + Py_DECREF(list); - if (PySequence_Check(value)) + /* Add m_attr_dict if we have it */ + if(self->m_attr_dict) + PyDict_Update(dict, self->m_attr_dict); + + return dict; +} + +/* We need these because the macros have a return in them */ +PyObject* KX_GameObject::py_getattro__internal(PyObject *attr) +{ + py_getattro_up(SCA_IObject); +} + +int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value) // py_setattro method +{ + py_setattro_up(SCA_IObject); +} + + +PyObject* KX_GameObject::py_getattro(PyObject *attr) +{ + PyObject *object= py_getattro__internal(attr); + + if (object==NULL && m_attr_dict) { - if (!strcmp(attr, "orientation")) - { - MT_Matrix3x3 rot; - if (PyObject_IsMT_Matrix(value, 3)) - { - if (PyMatTo(value, rot)) - { - NodeSetLocalOrientation(rot); - NodeUpdateGS(0.f,true); - return 0; - } - return 1; - } - - if (PySequence_Size(value) == 4) - { - MT_Quaternion qrot; - if (PyVecTo(value, qrot)) - { - rot.setRotation(qrot); - NodeSetLocalOrientation(rot); - NodeUpdateGS(0.f,true); - return 0; - } - return 1; - } + /* backup the exception incase the attr doesnt exist in the dict either */ + PyObject *err_type, *err_value, *err_tb; + PyErr_Fetch(&err_type, &err_value, &err_tb); + + object= PyDict_GetItem(m_attr_dict, attr); + if (object) { + Py_INCREF(object); - if (PySequence_Size(value) == 3) - { - MT_Vector3 erot; - if (PyVecTo(value, erot)) - { - rot.setEuler(erot); - NodeSetLocalOrientation(rot); - NodeUpdateGS(0.f,true); - return 0; - } - return 1; - } - PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence"); - return 1; + PyErr_Clear(); + Py_XDECREF( err_type ); + Py_XDECREF( err_value ); + Py_XDECREF( err_tb ); } - - if (!strcmp(attr, "position")) - { - MT_Point3 pos; - if (PyVecTo(value, pos)) - { - NodeSetLocalPosition(pos); - NodeUpdateGS(0.f,true); - return 0; - } - return 1; + else { + PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */ } - - if (!strcmp(attr, "scaling")) - { - MT_Vector3 scale; - if (PyVecTo(value, scale)) - { - NodeSetLocalScale(scale); - NodeUpdateGS(0.f,true); - return 0; - } - return 1; + } + return object; +} + +int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method +{ + int ret; + + ret= py_setattro__internal(attr, value); + + if (ret==PY_SET_ATTR_SUCCESS) { + /* remove attribute in our own dict to avoid double ups */ + /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */ + if (m_attr_dict) { + if (PyDict_DelItem(m_attr_dict, attr) != 0) + PyErr_Clear(); } } - if (PyString_Check(value)) - { - if (!strcmp(attr, "name")) - { -#if 0 // was added in revision 2832, but never took into account Object name mappings from revision 2 - // unlikely anyone ever used this successfully , removing. - m_name = PyString_AsString(value); - return 0; -#else - PyErr_SetString(PyExc_AttributeError, "object name readonly"); - return 1; -#endif + if (ret==PY_SET_ATTR_COERCE_FAIL) { + /* CValue attribute exists, remove CValue and add PyDict value */ + RemoveProperty(STR_String(PyString_AsString(attr))); + ret= PY_SET_ATTR_MISSING; + } + + if (ret==PY_SET_ATTR_MISSING) { + /* Lazy initialization */ + if (m_attr_dict==NULL) + m_attr_dict = PyDict_New(); + + if (PyDict_SetItem(m_attr_dict, attr, value)==0) { + PyErr_Clear(); + ret= PY_SET_ATTR_SUCCESS; + } + else { + PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary"); + ret= PY_SET_ATTR_FAIL; } } - /* Need to have parent settable here too */ + return ret; +} + + +int KX_GameObject::py_delattro(PyObject *attr) +{ + char *attr_str= PyString_AsString(attr); + + if (RemoveProperty(STR_String(attr_str))) // XXX - should call CValues instead but its only 2 lines here + return 0; + + if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0)) + return 0; - return SCA_IObject::_setattr(attr, value); + PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str); + return 1; } -PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args) + +PyObject* KX_GameObject::PyApplyForce(PyObject* args) { int local = 0; PyObject* pyvect; @@ -1311,7 +1842,7 @@ PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyApplyTorque(PyObject* args) { int local = 0; PyObject* pyvect; @@ -1326,7 +1857,7 @@ PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyApplyRotation(PyObject* args) { int local = 0; PyObject* pyvect; @@ -1341,7 +1872,7 @@ PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyApplyMovement(PyObject* args) { int local = 0; PyObject* pyvect; @@ -1356,7 +1887,7 @@ PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -1370,7 +1901,7 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) } } -PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args) { int local = 0; PyObject* pyvect; @@ -1385,7 +1916,7 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -1399,7 +1930,7 @@ PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) } } -PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args) { int local = 0; PyObject* pyvect; @@ -1414,7 +1945,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PySetVisible(PyObject* args) { int visible, recursive = 0; if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive)) @@ -1426,20 +1957,33 @@ PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) } -PyObject* KX_GameObject::PyGetVisible(PyObject* self) +PyObject* KX_GameObject::PySetOcclusion(PyObject* args) { + int occlusion, recursive = 0; + if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive)) + return NULL; + + SetOccluder(occlusion ? true:false, recursive ? true:false); + Py_RETURN_NONE; +} + +PyObject* KX_GameObject::PyGetVisible() +{ + ShowDeprecationWarning("getVisible()", "the visible property"); return PyInt_FromLong(m_bVisible); } -PyObject* KX_GameObject::PyGetState(PyObject* self) +PyObject* KX_GameObject::PyGetState() { + ShowDeprecationWarning("getState()", "the state property"); int state = 0; state |= GetState(); return PyInt_FromLong(state); } -PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PySetState(PyObject* value) { + ShowDeprecationWarning("setState()", "the state property"); int state_i = PyInt_AsLong(value); unsigned int state = 0; @@ -1458,9 +2002,7 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value) Py_RETURN_NONE; } - - -PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetVelocity(PyObject* args) { // only can get the velocity if we have a physics object connected to us... MT_Point3 point(0.0,0.0,0.0); @@ -1486,110 +2028,89 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) -PyObject* KX_GameObject::PyGetMass(PyObject* self) +PyObject* KX_GameObject::PyGetMass() { - return PyFloat_FromDouble(GetPhysicsController()->GetMass()); + ShowDeprecationWarning("getMass()", "the mass property"); + return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f); } - - -PyObject* KX_GameObject::PyGetReactionForce(PyObject* self) +PyObject* KX_GameObject::PyGetReactionForce() { // only can get the velocity if we have a physics object connected to us... - return PyObjectFrom(GetPhysicsController()->getReactionForce()); + + // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce + /* + if (GetPhysicsController()) + return PyObjectFrom(GetPhysicsController()->getReactionForce()); + return PyObjectFrom(dummy_point); + */ + + return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); + } -PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self) +PyObject* KX_GameObject::PyEnableRigidBody() { - GetPhysicsController()->setRigidBody(true); + if(GetPhysicsController()) + GetPhysicsController()->setRigidBody(true); Py_RETURN_NONE; } -PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self) +PyObject* KX_GameObject::PyDisableRigidBody() { - GetPhysicsController()->setRigidBody(false); + if(GetPhysicsController()) + GetPhysicsController()->setRigidBody(false); Py_RETURN_NONE; } -PyObject* KX_GameObject::PyGetParent(PyObject* self) +PyObject* KX_GameObject::PyGetParent() { + ShowDeprecationWarning("getParent()", "the parent property"); KX_GameObject* parent = this->GetParent(); if (parent) - return parent->AddRef(); + return parent->GetProxy(); Py_RETURN_NONE; } -PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PySetParent(PyObject* value) { - if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) { - PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type"); + KX_GameObject *obj; + if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject")) return NULL; - } - - // The object we want to set as parent - CValue *m_ob = (CValue*)value; - KX_GameObject *obj = ((KX_GameObject*)m_ob); - KX_Scene *scene = KX_GetActiveScene(); - this->SetParent(scene, obj); - + this->SetParent(KX_GetActiveScene(), obj); Py_RETURN_NONE; } -PyObject* KX_GameObject::PyRemoveParent(PyObject* self) +PyObject* KX_GameObject::PyRemoveParent() { KX_Scene *scene = KX_GetActiveScene(); this->RemoveParent(scene); Py_RETURN_NONE; } - -static void walk_children(SG_Node* node, CListValue* list, bool recursive) -{ - NodeList& children = node->GetSGChildren(); - - for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) - { - SG_Node* childnode = (*childit); - CValue* childobj = (CValue*)childnode->GetSGClientObject(); - if (childobj != NULL) // This is a GameObject - { - // add to the list - list->Add(childobj->AddRef()); - } - - // if the childobj is NULL then this may be an inverse parent link - // so a non recursive search should still look down this node. - if (recursive || childobj==NULL) { - walk_children(childnode, list, recursive); - } - } -} - -PyObject* KX_GameObject::PyGetChildren(PyObject* self) +PyObject* KX_GameObject::PyGetChildren() { - CListValue* list = new CListValue(); - walk_children(m_pSGNode, list, 0); - return list; + return GetChildren()->NewProxy(true); } -PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self) +PyObject* KX_GameObject::PyGetChildrenRecursive() { - CListValue* list = new CListValue(); - walk_children(m_pSGNode, list, 1); - return list; + return GetChildrenRecursive()->NewProxy(true); } -PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetMesh(PyObject* args) { + ShowDeprecationWarning("getMesh()", "the meshes property"); + int mesh = 0; if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh)) @@ -1598,7 +2119,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]); - return meshproxy; + return meshproxy->NewProxy(true); // XXX Todo Python own. } Py_RETURN_NONE; @@ -1608,7 +2129,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) -PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value) { float collisionMargin = PyFloat_AsDouble(value); @@ -1628,7 +2149,7 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyApplyImpulse(PyObject* args) { PyObject* pyattach; PyObject* pyimpulse; @@ -1655,7 +2176,7 @@ PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) -PyObject* KX_GameObject::PySuspendDynamics(PyObject* self) +PyObject* KX_GameObject::PySuspendDynamics() { SuspendDynamics(); Py_RETURN_NONE; @@ -1663,7 +2184,7 @@ PyObject* KX_GameObject::PySuspendDynamics(PyObject* self) -PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self) +PyObject* KX_GameObject::PyRestoreDynamics() { RestoreDynamics(); Py_RETURN_NONE; @@ -1671,20 +2192,22 @@ PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self) -PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords +PyObject* KX_GameObject::PyGetOrientation() //keywords { + ShowDeprecationWarning("getOrientation()", "the orientation property"); return PyObjectFrom(NodeGetWorldOrientation()); } -PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PySetOrientation(PyObject* value) { + ShowDeprecationWarning("setOrientation()", "the orientation property"); MT_Matrix3x3 matrix; if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix)) { NodeSetLocalOrientation(matrix); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); Py_RETURN_NONE; } @@ -1693,13 +2216,13 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value) { matrix.setRotation(quat); NodeSetLocalOrientation(matrix); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); Py_RETURN_NONE; } return NULL; } -PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args) { PyObject* pyvect; int axis = 2; //z axis is the default @@ -1714,14 +2237,14 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) if (fac> 1.0) fac= 1.0; AlignAxisToVect(vect,axis,fac); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); Py_RETURN_NONE; } } return NULL; } -PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PyGetAxisVect(PyObject* value) { MT_Vector3 vect; if (PyVecTo(value, vect)) @@ -1731,33 +2254,34 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value) return NULL; } -PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PySetPosition(PyObject* value) { + ShowDeprecationWarning("setPosition()", "the position property"); MT_Point3 pos; if (PyVecTo(value, pos)) { NodeSetLocalPosition(pos); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); Py_RETURN_NONE; } return NULL; } -PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PySetWorldPosition(PyObject* value) { MT_Point3 pos; if (PyVecTo(value, pos)) { NodeSetWorldPosition(pos); - NodeUpdateGS(0.f,true); + NodeUpdateGS(0.f); Py_RETURN_NONE; } return NULL; } -PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self) +PyObject* KX_GameObject::PyGetPhysicsId() { KX_IPhysicsController* ctrl = GetPhysicsController(); uint_ptr physid=0; @@ -1768,9 +2292,19 @@ PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self) return PyInt_FromLong((long)physid); } -PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self) +PyObject* KX_GameObject::PyGetPropertyNames() { - return ConvertKeysToPython(); + PyObject *list= ConvertKeysToPython(); + + if(m_attr_dict) { + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(m_attr_dict, &pos, &key, &value)) { + PyList_Append(list, key); + } + } + return list; } KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, @@ -1784,7 +2318,7 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, PyErr_Clear(); KX_GameObject *other; - if (ConvertPythonToGameObject(value, &other, false)) + if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject")) { return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition())); } @@ -1807,12 +2341,12 @@ KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo, PyErr_Clear(); KX_GameObject *other; - if (ConvertPythonToGameObject(value, &other, false)) + if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */ { toPoint = other->NodeGetWorldPosition(); } else { - PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type"); + PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type"); return NULL; } } @@ -1901,12 +2435,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, KX_GameObject *other; PyErr_Clear(); - if (ConvertPythonToGameObject(pyarg, &other, false)) + if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */ { toPoint = other->NodeGetWorldPosition(); } else { - PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject"); + PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject"); return NULL; } } @@ -1935,7 +2469,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) - return m_pHitObject->AddRef(); + return m_pHitObject->GetProxy(); Py_RETURN_NONE; } @@ -1977,7 +2511,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { PyErr_Clear(); - if (ConvertPythonToGameObject(pyto, &other, false)) + if (ConvertPythonToGameObject(pyto, &other, false, "")) /* error will be overwritten */ { toPoint = other->NodeGetWorldPosition(); } else @@ -1994,12 +2528,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { PyErr_Clear(); - if (ConvertPythonToGameObject(pyfrom, &other, false)) + if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */ { fromPoint = other->NodeGetWorldPosition(); } else { - PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject"); + PyErr_SetString(PyExc_TypeError, "gameOb.rayCast(to,from,dist,prop,face,xray,poly): KX_GameObject, the second optional argument to rayCast must be a vector or a KX_GameObject"); return NULL; } } @@ -2037,7 +2571,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3); if (returnValue) { // unlikely this would ever fail, if it does python sets an error - PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); + PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy()); PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal)); if (poly) @@ -2047,7 +2581,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, // if this field is set, then we can trust that m_hitPolygon is a valid polygon RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon); - PyTuple_SET_ITEM(returnValue, 3, polyproxy); + PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true)); } else { @@ -2065,6 +2599,26 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } +KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, + "sendMessage(subject, [body, to])\n" +"sends a message in same manner as a message actuator" +"subject = Subject of the message (string)" +"body = Message body (string)" +"to = Name of object to send the message to") +{ + char* subject; + char* body = (char *)""; + char* to = (char *)""; + const STR_String& from = GetName(); + + if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to)) + return NULL; + + KX_GetActiveScene()->GetNetworkScene()->SendMessage(to, from, subject, body); + + Py_RETURN_NONE; +} + /* --------------------------------------------------------------------- * Some stuff taken from the header * --------------------------------------------------------------------- */ @@ -2087,10 +2641,10 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter) } } -bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok) +bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix) { if (value==NULL) { - PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen"); + PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); *object = NULL; return false; } @@ -2101,33 +2655,40 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py if (py_none_ok) { return true; } else { - PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid"); + PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix); return false; } } if (PyString_Check(value)) { - *object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) )); + *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) )); if (*object) { return true; } else { - PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject"); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value)); return false; } } if (PyObject_TypeCheck(value, &KX_GameObject::Type)) { - *object = static_cast<KX_GameObject*>(value); + *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value); + + /* sets the error */ + if (*object==NULL) { + PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + return false; + } + return true; } *object = NULL; if (py_none_ok) { - PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None"); + PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix); } else { - PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string"); + PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix); } return false; diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 211c9b7ca7d..ec02dc17b75 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -51,15 +51,18 @@ #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */ #define KX_OB_DYNAMIC 1 - //Forward declarations. struct KX_ClientObjectInfo; class KX_RayCast; class RAS_MeshObject; class KX_IPhysicsController; +class PHY_IGraphicController; class PHY_IPhysicsEnvironment; struct Object; +/* utility conversion function */ +bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix); + /** * KX_GameObject is the main class for dynamic objects. */ @@ -86,8 +89,10 @@ protected: // culled = while rendering, depending on camera bool m_bVisible; bool m_bCulled; + bool m_bOccluder; KX_IPhysicsController* m_pPhysicsController1; + PHY_IGraphicController* m_pGraphicController; // used for ray casting PHY_IPhysicsEnvironment* m_pPhysicsEnvironment; STR_String m_testPropName; @@ -101,6 +106,28 @@ protected: public: bool m_isDeformable; + /** + * Helper function for modules that can't include KX_ClientObjectInfo.h + */ + static KX_GameObject* GetClientObject(KX_ClientObjectInfo* info); + + // Python attributes that wont convert into CValue + // + // there are 2 places attributes can be stored, in the CValue, + // where attributes are converted into BGE's CValue types + // these can be used with property actuators + // + // For the python API, For types that cannot be converted into CValues (lists, dicts, GameObjects) + // these will be put into "m_attr_dict", logic bricks cannot access them. + // + // rules for setting attributes. + // + // * there should NEVER be a CValue and a m_attr_dict attribute with matching names. get/sets make sure of this. + // * if CValue conversion fails, use a PyObject in "m_attr_dict" + // * when assigning a value, first see if it can be a CValue, if it can remove the "m_attr_dict" and set the CValue + // + PyObject* m_attr_dict; + virtual void /* This function should be virtual - derived classed override it */ Relink( GEN_Map<GEN_HashedPtr, void*> *map @@ -206,7 +233,7 @@ public: /** * Inherited from CValue -- does nothing! */ - float + double GetNumber( ); @@ -279,6 +306,12 @@ public: MT_Scalar GetMass(); + /** + * Return the local inertia vector of the object + */ + MT_Vector3 + GetLocalInertia(); + /** * Return the angular velocity of the game object. */ @@ -351,6 +384,19 @@ public: } /** + * @return a pointer to the graphic controller owner by this class + */ + PHY_IGraphicController* GetGraphicController() + { + return m_pGraphicController; + } + + void SetGraphicController(PHY_IGraphicController* graphiccontroller) + { + m_pGraphicController = graphiccontroller; + } + + /** * @section Coordinate system manipulation functions */ @@ -367,8 +413,7 @@ public: void NodeUpdateGS( - double time, - bool bInitiator + double time ); const @@ -525,13 +570,6 @@ public: static void UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene); /** - * Only update the transform if it's a non-dynamic object - */ - void - UpdateNonDynas( - ); - - /** * Function to set IPO option at start of IPO */ void @@ -665,20 +703,37 @@ public: /** * Was this object culled? */ - bool + inline bool GetCulled( void - ); + ) { return m_bCulled; } /** * Set culled flag of this object */ - void + inline void SetCulled( bool c - ); + ) { m_bCulled = c; } + + /** + * Is this object an occluder? + */ + inline bool + GetOccluder( + void + ) { return m_bOccluder; } /** + * Set occluder flag of this object + */ + void + SetOccluder( + bool v, + bool recursive + ); + + /** * Change the layer of the object (when it is added in another layer * than the original layer) */ @@ -752,14 +807,29 @@ public: } KX_ClientObjectInfo* getClientInfo() { return m_pClient_info; } + + CListValue* GetChildren(); + CListValue* GetChildrenRecursive(); + /** * @section Python interface functions. */ - - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *value); // _setattr method - virtual PyObject* _repr(void) { return PyString_FromString(GetName().ReadPtr()); } + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method + virtual int py_delattro(PyObject *attr); + virtual PyObject* py_repr(void) + { + return PyString_FromString(GetName().ReadPtr()); + } + + + /* quite annoying that we need these but the bloody + * py_getattro_up and py_setattro_up macro's have a returns in them! */ + PyObject* py_getattro__internal(PyObject *attr); + int py_setattro__internal(PyObject *attr, PyObject *value); // py_setattro method + + KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); @@ -778,6 +848,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetOrientation); KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible); KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible); + KX_PYMETHOD_VARARGS(KX_GameObject,SetOcclusion); KX_PYMETHOD_NOARGS(KX_GameObject,GetState); KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); @@ -802,6 +873,50 @@ public: KX_PYMETHOD_DOC(KX_GameObject,rayCast); KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo); KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo); + KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage); + /* attributes */ + static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_meshes(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + /* for dir(), python3 uses __dir__() */ + static PyObject* pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + /* Experemental! */ + static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + /* getitem/setitem */ + static Py_ssize_t Map_Len(PyObject* self); + static PyMappingMethods Mapping; + static PyObject* Map_GetItem(PyObject *self_v, PyObject *item); + static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val); private : @@ -820,8 +935,7 @@ private : }; -/* utility conversion function */ -bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok); + #endif //__KX_GAMEOBJECT diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 13501f1fbbd..10b66da7b76 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -79,6 +79,13 @@ public: virtual void setScaling(const MT_Vector3& scaling)=0; virtual MT_Scalar GetMass()=0; virtual void SetMass(MT_Scalar newmass)=0; + + virtual float GetLinVelocityMin()=0; + virtual void SetLinVelocityMin(float newmass)=0; + virtual float GetLinVelocityMax()=0; + virtual void SetLinVelocityMax(float newmass)=0; + + virtual MT_Vector3 GetLocalInertia()=0; virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; virtual void AddCompoundChild(KX_IPhysicsController* child) = 0; diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 623a939bf62..f04e3c79a8e 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -84,7 +84,7 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj, m_ipo_as_force(ipo_as_force), m_ipo_add(ipo_add), m_ipo_local(ipo_local), - m_type((IpoActType)acttype) + m_type(acttype) { m_starttime = -2.0*fabs(m_endframe - m_startframe) - 1.0; m_bIpoPlaying = false; @@ -190,7 +190,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) } } - switch (m_type) + switch ((IpoActType)m_type) { case KX_ACT_IPO_PLAY: @@ -383,7 +383,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) return result; } -KX_IpoActuator::IpoActType KX_IpoActuator::string2mode(char* modename) { +int KX_IpoActuator::string2mode(char* modename) { IpoActType res = KX_ACT_IPO_NODEF; if (modename == S_KX_ACT_IPO_PLAY_STRING) { @@ -413,22 +413,22 @@ KX_IpoActuator::IpoActType KX_IpoActuator::string2mode(char* modename) { /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_IpoActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_IpoActuator", - sizeof(KX_IpoActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_IpoActuator::Parents[] = { @@ -441,6 +441,8 @@ PyParentObject KX_IpoActuator::Parents[] = { PyMethodDef KX_IpoActuator::Methods[] = { {"set", (PyCFunction) KX_IpoActuator::sPySet, METH_VARARGS, (PY_METHODCHAR)Set_doc}, + + // deprecated {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc}, {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart, METH_NOARGS, (PY_METHODCHAR)GetStart_doc}, @@ -450,22 +452,35 @@ PyMethodDef KX_IpoActuator::Methods[] = { {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce, METH_NOARGS, (PY_METHODCHAR)GetIpoAsForce_doc}, {"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd, METH_VARARGS, (PY_METHODCHAR)SetIpoAdd_doc}, {"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd, METH_NOARGS, (PY_METHODCHAR)GetIpoAdd_doc}, - {"setType", (PyCFunction) KX_IpoActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, - {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, METH_NOARGS, (PY_METHODCHAR)GetType_doc}, {"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal, METH_VARARGS, (PY_METHODCHAR)SetForceIpoActsLocal_doc}, {"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal, METH_NOARGS, (PY_METHODCHAR)GetForceIpoActsLocal_doc}, + {"setType", (PyCFunction) KX_IpoActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc}, + {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, METH_NOARGS, (PY_METHODCHAR)GetType_doc}, {NULL,NULL} //Sentinel }; PyAttributeDef KX_IpoActuator::Attributes[] = { + KX_PYATTRIBUTE_FLOAT_RW("startFrame", 0, 300000, KX_IpoActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("endFrame", 0, 300000, KX_IpoActuator, m_endframe), + KX_PYATTRIBUTE_STRING_RW("propName", 0, 64, false, KX_IpoActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 64, false, KX_IpoActuator, m_framepropname), + KX_PYATTRIBUTE_INT_RW("type", KX_ACT_IPO_NODEF+1, KX_ACT_IPO_MAX-1, true, KX_IpoActuator, m_type), + KX_PYATTRIBUTE_BOOL_RW("useIpoAsForce", KX_IpoActuator, m_ipo_as_force), + KX_PYATTRIBUTE_BOOL_RW("useIpoAdd", KX_IpoActuator, m_ipo_add), + KX_PYATTRIBUTE_BOOL_RW("useIpoLocal", KX_IpoActuator, m_ipo_local), + KX_PYATTRIBUTE_BOOL_RW("useChildren", KX_IpoActuator, m_recurse), + { NULL } //Sentinel }; -PyObject* KX_IpoActuator::_getattr(const char *attr) { - _getattr_up(SCA_IActuator); +PyObject* KX_IpoActuator::py_getattro(PyObject *attr) { + py_getattro_up(SCA_IActuator); } - +int KX_IpoActuator::py_setattro(PyObject *attr, PyObject *value) // py_setattro method +{ + py_setattro_up(SCA_IActuator); +} /* set --------------------------------------------------------------------- */ const char KX_IpoActuator::Set_doc[] = @@ -475,17 +490,18 @@ const char KX_IpoActuator::Set_doc[] = "\t - endframe : last frame to use (int)\n" "\t - mode? : special mode (0=normal, 1=interpret location as force, 2=additive)" "\tSet the properties of the actuator.\n"; -PyObject* KX_IpoActuator::PySet(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySet(PyObject* args) { + + ShowDeprecationWarning("set()", "a number properties"); + /* sets modes PLAY, PINGPONG, FLIPPER, LOOPSTOP, LOOPEND */ /* arg 1 = mode string, arg 2 = startframe, arg3 = stopframe, */ /* arg4 = force toggle */ char* mode; int forceToggle; - IpoActType modenum; + int modenum; int startFrame, stopFrame; - if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame, + if(!PyArg_ParseTuple(args, "siii:set", &mode, &startFrame, &stopFrame, &forceToggle)) { return NULL; } @@ -515,13 +531,14 @@ const char KX_IpoActuator::SetProperty_doc[] = "setProperty(propname)\n" "\t - propname: name of the property (string)\n" "\tSet the property to be used in FromProp mode.\n"; -PyObject* KX_IpoActuator::PySetProperty(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetProperty(PyObject* args) { + + ShowDeprecationWarning("setProperty()", "the propName property"); + /* mode is implicit here, but not supported yet... */ /* args: property */ char *propertyName; - if(!PyArg_ParseTuple(args, "s", &propertyName)) { + if(!PyArg_ParseTuple(args, "s:setProperty", &propertyName)) { return NULL; } @@ -535,11 +552,12 @@ const char KX_IpoActuator::SetStart_doc[] = "setStart(frame)\n" "\t - frame: first frame to use (int)\n" "\tSet the frame from which the ipo starts playing.\n"; -PyObject* KX_IpoActuator::PySetStart(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetStart(PyObject* args) { + + ShowDeprecationWarning("setStart()", "the startFrame property"); + float startArg; - if(!PyArg_ParseTuple(args, "f", &startArg)) { + if(!PyArg_ParseTuple(args, "f:setStart", &startArg)) { return NULL; } @@ -551,7 +569,8 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self, const char KX_IpoActuator::GetStart_doc[] = "getStart()\n" "\tReturns the frame from which the ipo starts playing.\n"; -PyObject* KX_IpoActuator::PyGetStart(PyObject* self) { +PyObject* KX_IpoActuator::PyGetStart() { + ShowDeprecationWarning("getStart()", "the startFrame property"); return PyFloat_FromDouble(m_startframe); } @@ -560,11 +579,10 @@ const char KX_IpoActuator::SetEnd_doc[] = "setEnd(frame)\n" "\t - frame: last frame to use (int)\n" "\tSet the frame at which the ipo stops playing.\n"; -PyObject* KX_IpoActuator::PySetEnd(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetEnd(PyObject* args) { + ShowDeprecationWarning("setEnd()", "the endFrame property"); float endArg; - if(!PyArg_ParseTuple(args, "f", &endArg)) { + if(!PyArg_ParseTuple(args, "f:setEnd", &endArg)) { return NULL; } @@ -576,7 +594,8 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self, const char KX_IpoActuator::GetEnd_doc[] = "getEnd()\n" "\tReturns the frame at which the ipo stops playing.\n"; -PyObject* KX_IpoActuator::PyGetEnd(PyObject* self) { +PyObject* KX_IpoActuator::PyGetEnd() { + ShowDeprecationWarning("getEnd()", "the endFrame property"); return PyFloat_FromDouble(m_endframe); } @@ -585,12 +604,11 @@ const char KX_IpoActuator::SetIpoAsForce_doc[] = "setIpoAsForce(force?)\n" "\t - force? : interpret this ipo as a force? (KX_TRUE, KX_FALSE)\n" "\tSet whether to interpret the ipo as a force rather than a displacement.\n"; -PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* args) { + ShowDeprecationWarning("setIpoAsForce()", "the useIpoAsForce property"); int boolArg; - if (!PyArg_ParseTuple(args, "i", &boolArg)) { + if (!PyArg_ParseTuple(args, "i:setIpoAsForce", &boolArg)) { return NULL; } @@ -604,7 +622,8 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, const char KX_IpoActuator::GetIpoAsForce_doc[] = "getIpoAsForce()\n" "\tReturns whether to interpret the ipo as a force rather than a displacement.\n"; -PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self) { +PyObject* KX_IpoActuator::PyGetIpoAsForce() { + ShowDeprecationWarning("getIpoAsForce()", "the useIpoAsForce property"); return BoolToPyArg(m_ipo_as_force); } @@ -613,12 +632,11 @@ const char KX_IpoActuator::SetIpoAdd_doc[] = "setIpoAdd(add?)\n" "\t - add? : add flag (KX_TRUE, KX_FALSE)\n" "\tSet whether to interpret the ipo as additive rather than absolute.\n"; -PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* args) { + ShowDeprecationWarning("setIpoAdd()", "the useIpoAdd property"); int boolArg; - if (!PyArg_ParseTuple(args, "i", &boolArg)) { + if (!PyArg_ParseTuple(args, "i:setIpoAdd", &boolArg)) { return NULL; } @@ -632,7 +650,8 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, const char KX_IpoActuator::GetIpoAdd_doc[] = "getIpoAsAdd()\n" "\tReturns whether to interpret the ipo as additive rather than absolute.\n"; -PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self) { +PyObject* KX_IpoActuator::PyGetIpoAdd() { + ShowDeprecationWarning("getIpoAdd()", "the useIpoAdd property"); return BoolToPyArg(m_ipo_add); } @@ -641,18 +660,17 @@ const char KX_IpoActuator::SetType_doc[] = "setType(mode)\n" "\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n" "\tSet the operation mode of the actuator.\n"; -PyObject* KX_IpoActuator::PySetType(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetType(PyObject* args) { + ShowDeprecationWarning("setType()", "the type property"); int typeArg; - if (!PyArg_ParseTuple(args, "i", &typeArg)) { + if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) { return NULL; } if ( (typeArg > KX_ACT_IPO_NODEF) - && (typeArg < KX_ACT_IPO_KEY2KEY) ) { - m_type = (IpoActType) typeArg; + && (typeArg < KX_ACT_IPO_MAX) ) { + m_type = typeArg; } Py_RETURN_NONE; @@ -661,7 +679,8 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self, const char KX_IpoActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; -PyObject* KX_IpoActuator::PyGetType(PyObject* self) { +PyObject* KX_IpoActuator::PyGetType() { + ShowDeprecationWarning("getType()", "the type property"); return PyInt_FromLong(m_type); } @@ -672,12 +691,11 @@ const char KX_IpoActuator::SetForceIpoActsLocal_doc[] = "\t coordinates? (KX_TRUE, KX_FALSE)\n" "\tSet whether to apply the force in the object's local\n" "\tcoordinates rather than the world global coordinates.\n"; -PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* args) { + ShowDeprecationWarning("setForceIpoActsLocal()", "the useIpoLocal property"); int boolArg; - if (!PyArg_ParseTuple(args, "i", &boolArg)) { + if (!PyArg_ParseTuple(args, "i:setForceIpoActsLocal", &boolArg)) { return NULL; } @@ -690,7 +708,8 @@ const char KX_IpoActuator::GetForceIpoActsLocal_doc[] = "getForceIpoActsLocal()\n" "\tReturn whether to apply the force in the object's local\n" "\tcoordinates rather than the world global coordinates.\n"; -PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self) { +PyObject* KX_IpoActuator::PyGetForceIpoActsLocal() { + ShowDeprecationWarning("getForceIpoActsLocal()", "the useIpoLocal property"); return BoolToPyArg(m_ipo_local); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 12e1835ab49..184ad5512de 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -108,9 +108,9 @@ public: static STR_String S_KX_ACT_IPO_KEY2KEY_STRING; static STR_String S_KX_ACT_IPO_FROM_PROP_STRING; - IpoActType string2mode(char* modename); + int string2mode(char* modename); - IpoActType m_type; + int m_type; KX_IpoActuator(SCA_IObject* gameobj, const STR_String& propname, @@ -141,22 +141,24 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + //KX_PYMETHOD_DOC - KX_PYMETHOD_DOC(KX_IpoActuator,Set); - KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,Set); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetProperty); /* KX_PYMETHOD_DOC(KX_IpoActuator,SetKey2Key); */ - KX_PYMETHOD_DOC(KX_IpoActuator,SetStart); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetStart); KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetStart); - KX_PYMETHOD_DOC(KX_IpoActuator,SetEnd); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetEnd); KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetEnd); - KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetIpoAsForce); KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAsForce); - KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAdd); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetIpoAdd); KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAdd); - KX_PYMETHOD_DOC(KX_IpoActuator,SetType); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetType); KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetType); - KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal); + KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,SetForceIpoActsLocal); KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetForceIpoActsLocal); }; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 97b4213b8bd..83a2fa8a448 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -55,6 +55,7 @@ #include "KX_Scene.h" #include "MT_CmMatrix4x4.h" #include "KX_Camera.h" +#include "KX_Dome.h" #include "KX_Light.h" #include "KX_PythonInit.h" #include "KX_PyConstraintBinding.h" @@ -144,6 +145,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_stereo(false), m_curreye(0), + m_usedome(false), + m_logger(NULL), // Set up timing info display variables @@ -179,6 +182,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) KX_KetsjiEngine::~KX_KetsjiEngine() { delete m_logger; + if(m_usedome) + delete m_dome; } @@ -256,7 +261,129 @@ void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter) m_sceneconverter = sceneconverter; } +void KX_KetsjiEngine::InitDome(float size, short res, short mode, short angle, float resbuf, struct Text* text) +{ + m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, size, res, mode, angle, resbuf, text); + m_usedome = true; +} + +void KX_KetsjiEngine::RenderDome() +{ + GLuint viewport[4]={0}; + glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); +// unsigned int m_viewport[4] = {viewport[0], viewport[1], viewport[2], viewport[3]}; + + m_dome->SetViewPort(viewport); + + KX_Scene* firstscene = *m_scenes.begin(); + const RAS_FrameSettings &framesettings = firstscene->GetFramingType(); + + m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true); + + // hiding mouse cursor each frame + // (came back when going out of focus and then back in again) + if (m_hideCursor) + m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); + + // clear the entire game screen with the border color + // only once per frame + + m_canvas->BeginDraw(); + + // BeginFrame() sets the actual drawing area. You can use a part of the window + if (!BeginFrame()) + return; + + KX_SceneList::iterator sceneit; + for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) + { + // do this only once per scene + (*sceneit)->UpdateMeshTransformations(); + } + + int n_renders=m_dome->GetNumberRenders();// usually 4 or 6 + for (int i=0;i<n_renders;i++){ + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); + for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) + // for each scene, call the proceed functions + { + KX_Scene* scene = *sceneit; + KX_Camera* cam = scene->GetActiveCamera(); + + m_rendertools->BeginFrame(m_rasterizer); + // pass the scene's worldsettings to the rasterizer + SetWorldSettings(scene->GetWorldInfo()); + + // shadow buffers + if (i == 0){ + RenderShadowBuffers(scene); + } + // Avoid drawing the scene with the active camera twice when it's viewport is enabled + if(cam && !cam->GetViewport()) + { + if (scene->IsClearingZBuffer()) + m_rasterizer->ClearDepthBuffer(); + + m_rendertools->SetAuxilaryClientInfo(scene); + + // do the rendering + m_dome->RenderDomeFrame(scene,cam, i); + } + + list<class KX_Camera*>* cameras = scene->GetCameras(); + + // Draw the scene once for each camera with an enabled viewport + list<KX_Camera*>::iterator it = cameras->begin(); + while(it != cameras->end()) + { + if((*it)->GetViewport()) + { + if (scene->IsClearingZBuffer()) + m_rasterizer->ClearDepthBuffer(); + + m_rendertools->SetAuxilaryClientInfo(scene); + + // do the rendering + m_dome->RenderDomeFrame(scene, (*it),i); + } + + it++; + } + } + m_dome->BindImages(i); + } + +// m_dome->Dome_PostRender(scene, cam, stereomode); + m_canvas->EndFrame();//XXX do we really need that? + m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); + + if (m_overrideFrameColor) //XXX why do we want + { + // Do not use the framing bar color set in the Blender scenes + m_canvas->ClearColor( + m_overrideFrameColorR, + m_overrideFrameColorG, + m_overrideFrameColorB, + 1.0 + ); + } + else + { + // Use the framing bar color set in the Blender scenes + m_canvas->ClearColor( + framesettings.BarRed(), + framesettings.BarGreen(), + framesettings.BarBlue(), + 1.0 + ); + } + + m_dome->Draw(); + + //run 2dfilters + EndFrame(); +} /** * Ketsji Init(), Initializes datastructures and converts data from @@ -412,7 +539,7 @@ else // Compute the number of logic frames to do each update (fixed tic bricks) - int frames =int(deltatime*m_ticrate); + int frames =int(deltatime*m_ticrate+1e-6); // if (frames>1) // printf("****************************************"); // printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames); @@ -465,12 +592,15 @@ else m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_NETWORK); scene->GetNetworkScene()->proceed(m_frameTime); - m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); - scene->UpdateParents(m_frameTime); + //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE); + //scene->UpdateParents(m_frameTime); m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_PHYSICS1); // set Python hooks for each scene PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); KX_SetActiveScene(scene); @@ -479,31 +609,37 @@ else // Update scenegraph after physics step. This maps physics calculations // into node positions. - m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); - scene->UpdateParents(m_frameTime); + //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE); + //scene->UpdateParents(m_frameTime); // Process sensors, and controllers m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_CONTROLLER); scene->LogicBeginFrame(m_frameTime); // Scenegraph needs to be updated again, because Logic Controllers // can affect the local matrices. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE); scene->UpdateParents(m_frameTime); // Process actuators // Do some cleanup work for this logic frame m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_ACTUATOR); scene->LogicUpdateFrame(m_frameTime, true); scene->LogicEndFrame(); // Actuators can affect the scenegraph m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE); scene->UpdateParents(m_frameTime); m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->GetPhysicsEnvironment()->beginFrame(); // Perform physics calculations on the scene. This can involve @@ -511,6 +647,7 @@ else scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,1.0/m_ticrate);//m_deltatimerealDeltaTime); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE); scene->UpdateParents(m_frameTime); @@ -574,6 +711,7 @@ else KX_SetActiveScene(scene); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_PHYSICS1); scene->UpdateParents(m_clockTime); // Perform physics calculations on the scene. This can involve @@ -583,6 +721,7 @@ else // Update scenegraph after physics step. This maps physics calculations // into node positions. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->UpdateParents(m_clockTime); // Do some cleanup work for this logic frame @@ -591,6 +730,7 @@ else // Actuators can affect the scenegraph m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_ACTUATOR); scene->UpdateParents(m_clockTime); scene->setSuspendedTime(0.0); @@ -618,10 +758,15 @@ else void KX_KetsjiEngine::Render() { + if(m_usedome){ + RenderDome(); + return; + } KX_Scene* firstscene = *m_scenes.begin(); const RAS_FrameSettings &framesettings = firstscene->GetFramingType(); m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_RENDER); // hiding mouse cursor each frame // (came back when going out of focus and then back in again) @@ -672,6 +817,9 @@ void KX_KetsjiEngine::Render() // pass the scene's worldsettings to the rasterizer SetWorldSettings(scene->GetWorldInfo()); + // do this only once per scene + scene->UpdateMeshTransformations(); + // shadow buffers RenderShadowBuffers(scene); @@ -758,6 +906,9 @@ void KX_KetsjiEngine::Render() } } // if(m_rasterizer->Stereo()) + // run the 2dfilters and motion blur once for all the scenes + PostRenderFrame(); + EndFrame(); } @@ -997,7 +1148,6 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) light->BindShadowBuffer(m_rasterizer, cam, camtrans); /* update scene */ - scene->UpdateMeshTransformations(); scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer()); /* render */ @@ -1102,30 +1252,34 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) cam->GetCameraLocation(), cam->GetCameraOrientation()); cam->SetModelviewMatrix(viewmat); - scene->UpdateMeshTransformations(); + //redundant, already done in Render() + //scene->UpdateMeshTransformations(); // The following actually reschedules all vertices to be // redrawn. There is a cache between the actual rescheduling // and this call though. Visibility is imparted when this call // runs through the individual objects. + + m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_CULLING); + scene->CalculateVisibleMeshes(m_rasterizer,cam); + m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_RENDER); + scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); if (scene->GetPhysicsEnvironment()) scene->GetPhysicsEnvironment()->debugDrawWorld(); m_rasterizer->FlushDebugLines(); - - PostRenderFrame(); } void KX_KetsjiEngine::PostRenderFrame() { - m_rendertools->PushMatrix(); m_rendertools->Render2DFilters(m_canvas); m_rendertools->MotionBlur(m_rasterizer); - m_rendertools->PopMatrix(); } void KX_KetsjiEngine::StopEngine() @@ -1166,15 +1320,17 @@ void KX_KetsjiEngine::AddScene(KX_Scene* scene) void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene) { bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName)); - - // if there is no activecamera, or the camera is being - // overridden we need to construct a temporarily camera + + SG_SetActiveStage(SG_STAGE_SCENE); + + // if there is no activecamera, or the camera is being + // overridden we need to construct a temporarily camera if (!scene->GetActiveCamera() || override_camera) { KX_Camera* activecam = NULL; RAS_CameraData camdata = RAS_CameraData(); - activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata, false); + activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata); activecam->SetName("__default__cam__"); // set transformation @@ -1186,11 +1342,11 @@ void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene) activecam->NodeSetLocalPosition(camtrans.getOrigin()); activecam->NodeSetLocalOrientation(camtrans.getBasis()); - activecam->NodeUpdateGS(0,true); + activecam->NodeUpdateGS(0); } else { activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0)); activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0)); - activecam->NodeUpdateGS(0,true); + activecam->NodeUpdateGS(0); } scene->AddCamera(activecam); @@ -1675,4 +1831,3 @@ void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const } - diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 8516049f6d8..a8ccd6100d7 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -74,6 +74,7 @@ private: PyObject* m_pythondictionary; class SCA_IInputDevice* m_keyboarddevice; class SCA_IInputDevice* m_mousedevice; + class KX_Dome* m_dome; // dome stereo mode /** Lists of scenes scheduled to be removed at the end of the frame. */ std::set<STR_String> m_removingScenes; @@ -208,6 +209,12 @@ public: RAS_ICanvas* GetCanvas(){return m_canvas;}; RAS_IRenderTools* GetRenderTools(){return m_rendertools;}; + /// Dome functions + void InitDome(float size, short res, short mode, short angle, float resbuf, struct Text* text); + void EndDome(); + void RenderDome(); + bool m_usedome; + ///returns true if an update happened to indicate -> Render bool NextFrame(); void Render(); @@ -234,6 +241,8 @@ public: void GetSceneViewport(KX_Scene* scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); void SetDrawType(int drawingtype); + int GetDrawType(){return m_drawingmode;}; + void SetCameraZoom(float camzoom); void EnableCameraOverride(const STR_String& forscene); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index a2e93ecdd36..713838c88ec 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -57,6 +57,7 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, { m_lightobj = lightobj; m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr(); + m_lightobj.m_scene = sgReplicationInfo; m_rendertools->AddLight(&m_lightobj); m_glsl = glsl; m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene(); @@ -158,7 +159,7 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T cam->NodeSetLocalPosition(camtrans.getOrigin()); cam->NodeSetLocalOrientation(camtrans.getBasis()); - cam->NodeUpdateGS(0,true); + cam->NodeUpdateGS(0); /* setup rasterizer transformations */ ras->SetProjectionMatrix(projectionmat); @@ -172,109 +173,114 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) GPU_lamp_shadow_buffer_unbind(lamp); } -PyObject* KX_LightObject::_getattr(const char *attr) +PyObject* KX_LightObject::py_getattro(PyObject *attr) { - if (!strcmp(attr, "layer")) + char *attr_str= PyString_AsString(attr); + + if (!strcmp(attr_str, "layer")) return PyInt_FromLong(m_lightobj.m_layer); - if (!strcmp(attr, "energy")) + if (!strcmp(attr_str, "energy")) return PyFloat_FromDouble(m_lightobj.m_energy); - if (!strcmp(attr, "distance")) + if (!strcmp(attr_str, "distance")) return PyFloat_FromDouble(m_lightobj.m_distance); - if (!strcmp(attr, "colour") || !strcmp(attr, "color")) + if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color")) return Py_BuildValue("[fff]", m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue); - if (!strcmp(attr, "lin_attenuation")) + if (!strcmp(attr_str, "lin_attenuation")) return PyFloat_FromDouble(m_lightobj.m_att1); - if (!strcmp(attr, "quad_attenuation")) + if (!strcmp(attr_str, "quad_attenuation")) return PyFloat_FromDouble(m_lightobj.m_att2); - if (!strcmp(attr, "spotsize")) + if (!strcmp(attr_str, "spotsize")) return PyFloat_FromDouble(m_lightobj.m_spotsize); - if (!strcmp(attr, "spotblend")) + if (!strcmp(attr_str, "spotblend")) return PyFloat_FromDouble(m_lightobj.m_spotblend); - if (!strcmp(attr, "SPOT")) + if (!strcmp(attr_str, "SPOT")) return PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); - if (!strcmp(attr, "SUN")) + if (!strcmp(attr_str, "SUN")) return PyInt_FromLong(RAS_LightObject::LIGHT_SUN); - if (!strcmp(attr, "NORMAL")) + if (!strcmp(attr_str, "NORMAL")) return PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); - if (!strcmp(attr, "type")) + if (!strcmp(attr_str, "type")) return PyInt_FromLong(m_lightobj.m_type); - _getattr_up(KX_GameObject); + py_getattro_up(KX_GameObject); } -int KX_LightObject::_setattr(const char *attr, PyObject *pyvalue) -{ + +int KX_LightObject::py_setattro(PyObject *attr, PyObject *pyvalue) +{ + char *attr_str= PyString_AsString(attr); + if (PyInt_Check(pyvalue)) { int value = PyInt_AsLong(pyvalue); - if (!strcmp(attr, "layer")) + if (!strcmp(attr_str, "layer")) { m_lightobj.m_layer = value; - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "type")) + if (!strcmp(attr_str, "type")) { if (value >= RAS_LightObject::LIGHT_SPOT && value <= RAS_LightObject::LIGHT_NORMAL) m_lightobj.m_type = (RAS_LightObject::LightType) value; - return 0; + return PY_SET_ATTR_SUCCESS; } } - if (PyFloat_Check(pyvalue)) + if (PyFloat_Check(pyvalue) || PyInt_Check(pyvalue)) { float value = PyFloat_AsDouble(pyvalue); - if (!strcmp(attr, "energy")) + if (!strcmp(attr_str, "energy")) { m_lightobj.m_energy = value; - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "distance")) + if (!strcmp(attr_str, "distance")) { m_lightobj.m_distance = value; - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "lin_attenuation")) + if (!strcmp(attr_str, "lin_attenuation")) { m_lightobj.m_att1 = value; - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "quad_attenuation")) + if (!strcmp(attr_str, "quad_attenuation")) { m_lightobj.m_att2 = value; - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "spotsize")) + if (!strcmp(attr_str, "spotsize")) { m_lightobj.m_spotsize = value; - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "spotblend")) + if (!strcmp(attr_str, "spotblend")) { m_lightobj.m_spotblend = value; - return 0; + return PY_SET_ATTR_SUCCESS; } } if (PySequence_Check(pyvalue)) { - if (!strcmp(attr, "colour") || !strcmp(attr, "color")) + if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color")) { MT_Vector3 color; if (PyVecTo(pyvalue, color)) @@ -282,19 +288,19 @@ int KX_LightObject::_setattr(const char *attr, PyObject *pyvalue) m_lightobj.m_red = color[0]; m_lightobj.m_green = color[1]; m_lightobj.m_blue = color[2]; - return 0; + return PY_SET_ATTR_SUCCESS; } - return 1; + return PY_SET_ATTR_FAIL; } } - if (!strcmp(attr, "SPOT") || !strcmp(attr, "SUN") || !strcmp(attr, "NORMAL")) + if (!strcmp(attr_str, "SPOT") || !strcmp(attr_str, "SUN") || !strcmp(attr_str, "NORMAL")) { - PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr); - return 1; + PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr_str); + return PY_SET_ATTR_FAIL; } - return KX_GameObject::_setattr(attr, pyvalue); + return KX_GameObject::py_setattro(attr, pyvalue); } PyMethodDef KX_LightObject::Methods[] = { @@ -302,51 +308,41 @@ PyMethodDef KX_LightObject::Methods[] = { }; PyAttributeDef KX_LightObject::Attributes[] = { + KX_PYATTRIBUTE_DUMMY("layer"), + KX_PYATTRIBUTE_DUMMY("energy"), + KX_PYATTRIBUTE_DUMMY("distance"), + KX_PYATTRIBUTE_DUMMY("colour"), + KX_PYATTRIBUTE_DUMMY("color"), + KX_PYATTRIBUTE_DUMMY("lin_attenuation"), + KX_PYATTRIBUTE_DUMMY("quad_attenuation"), + KX_PYATTRIBUTE_DUMMY("spotsize"), + KX_PYATTRIBUTE_DUMMY("spotblend"), + KX_PYATTRIBUTE_DUMMY("SPOT"), + KX_PYATTRIBUTE_DUMMY("SUN"), + KX_PYATTRIBUTE_DUMMY("NORMAL"), + KX_PYATTRIBUTE_DUMMY("type"), { NULL } //Sentinel }; -char KX_LightObject::doc[] = "Module KX_LightObject\n\n" -"Constants:\n" -"\tSPOT\n" -"\tSUN\n" -"\tNORMAL\n" -"Attributes:\n" -"\ttype -> SPOT, SUN or NORMAL\n" -"\t\tThe type of light.\n" -"\tlayer -> integer bit field.\n" -"\t\tThe layers this light applies to.\n" -"\tenergy -> float.\n" -"\t\tThe brightness of the light.\n" -"\tdistance -> float.\n" -"\t\tThe effect radius of the light.\n" -"\tcolour -> list [r, g, b].\n" -"\tcolor -> list [r, g, b].\n" -"\t\tThe color of the light.\n" -"\tlin_attenuation -> float.\n" -"\t\tThe attenuation factor for the light.\n" -"\tspotsize -> float.\n" -"\t\tThe size of the spot.\n" -"\tspotblend -> float.\n" -"\t\tThe blend? of the spot.\n"; - PyTypeObject KX_LightObject::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_LightObject", - sizeof(KX_LightObject), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - doc + py_base_repr, + 0,0, + &KX_GameObject::Mapping, + 0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_LightObject::Parents[] = { diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 47edd09b5b9..4559954c8d7 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -47,7 +47,6 @@ protected: class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj bool m_glsl; Scene* m_blenderscene; - static char doc[]; public: KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type); @@ -63,8 +62,8 @@ public: void UnbindShadowBuffer(class RAS_IRasterizer *ras); void Update(); - virtual PyObject* _getattr(const char *attr); /* lens, near, far, projection_matrix */ - virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ + virtual int py_setattro(PyObject *attr, PyObject *pyvalue); virtual bool IsLight(void) { return true; } }; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index a0c0a496c06..6be1da55ff8 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -46,22 +46,22 @@ #include "PyObjectPlus.h" PyTypeObject KX_MeshProxy::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_MeshProxy", - sizeof(KX_MeshProxy), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_MeshProxy::Parents[] = { @@ -73,8 +73,11 @@ PyParentObject KX_MeshProxy::Parents[] = { }; PyMethodDef KX_MeshProxy::Methods[] = { +// Deprecated -----> {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS}, {"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS}, +// <----- + {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, @@ -87,6 +90,10 @@ KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh), }; PyAttributeDef KX_MeshProxy::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("materials", KX_MeshProxy, pyattr_get_materials), + KX_PYATTRIBUTE_RO_FUNCTION("numPolygons", KX_MeshProxy, pyattr_get_numPolygons), + KX_PYATTRIBUTE_RO_FUNCTION("numMaterials", KX_MeshProxy, pyattr_get_numMaterials), + { NULL } //Sentinel }; @@ -96,35 +103,19 @@ void KX_MeshProxy::SetMeshModified(bool v) } -PyObject* -KX_MeshProxy::_getattr(const char *attr) +PyObject* KX_MeshProxy::py_getattro(PyObject *attr) { - if (!strcmp(attr, "materials")) - { - PyObject *materials = PyList_New(0); - list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial(); - for(; mit != m_meshobj->GetLastMaterial(); ++mit) - { - RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); - - if(polymat->GetFlag() & RAS_BLENDERMAT) - { - KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat); - PyList_Append(materials, mat); - }else - { - PyList_Append(materials, static_cast<KX_PolygonMaterial*>(polymat)); - } - } - return materials; - } - _getattr_up(SCA_IObject); + py_getattro_up(SCA_IObject); } +int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IObject); +} KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh) - : m_meshobj(mesh) + : SCA_IObject(&Type), m_meshobj(mesh) { } @@ -139,7 +130,7 @@ CValue* KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;} CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;} const STR_String & KX_MeshProxy::GetText() {return m_meshobj->GetName();}; -float KX_MeshProxy::GetNumber() { return -1;} +double KX_MeshProxy::GetNumber() { return -1;} STR_String KX_MeshProxy::GetName() { return m_meshobj->GetName();} void KX_MeshProxy::SetName(STR_String name) { }; CValue* KX_MeshProxy::GetReplica() { return NULL;} @@ -148,28 +139,26 @@ void KX_MeshProxy::ReplicaSetName(STR_String name) {}; // stuff for python integration -PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds) { int num = m_meshobj->NumMaterials(); + ShowDeprecationWarning("getNumMaterials()", "the numMaterials property"); return PyInt_FromLong(num); } -PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self) +PyObject* KX_MeshProxy::PyGetNumPolygons() { int num = m_meshobj->NumPolygons(); + ShowDeprecationWarning("getNumPolygons()", "the numPolygons property"); return PyInt_FromLong(num); } -PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) { int matid= 1; STR_String matname; - if (PyArg_ParseTuple(args,"i",&matid)) + if (PyArg_ParseTuple(args,"i:getMaterialName",&matid)) { matname = m_meshobj->GetMaterialName(matid); } @@ -182,14 +171,12 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, } -PyObject* KX_MeshProxy::PyGetTextureName(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) { int matid= 1; STR_String matname; - if (PyArg_ParseTuple(args,"i",&matid)) + if (PyArg_ParseTuple(args,"i:getTextureName",&matid)) { matname = m_meshobj->GetTextureName(matid); } @@ -201,45 +188,41 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* self, } -PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) { - int matid= -1; - int length = -1; + int matid= 0; + int length = 0; - if (PyArg_ParseTuple(args,"i",&matid)) + if (!PyArg_ParseTuple(args,"i:getVertexArrayLength",&matid)) + return NULL; + + + RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); /* can be NULL*/ + + if (mmat) { - RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial(); - if (mat) length = m_meshobj->NumVertices(mat); } - else { - return NULL; - } - + return PyInt_FromLong(length); - } -PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds) { int vertexindex= 1; int matindex= 1; PyObject* vertexob = NULL; - if (PyArg_ParseTuple(args,"ii",&matindex,&vertexindex)) + if (PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex)) { RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex); if (vertex) { - vertexob = new KX_VertexProxy(this, vertex); + vertexob = (new KX_VertexProxy(this, vertex))->NewProxy(true); } } else { @@ -250,24 +233,28 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, } -PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds) { int polyindex= 1; PyObject* polyob = NULL; - if (!PyArg_ParseTuple(args,"i",&polyindex)) + if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex)) + return NULL; + + if (polyindex<0 || polyindex >= m_meshobj->NumPolygons()) + { + PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, invalid polygon index"); return NULL; + } + RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex); if (polygon) { - polyob = new KX_PolyProxy(m_meshobj, polygon); + polyob = (new KX_PolyProxy(m_meshobj, polygon))->NewProxy(true); } - else - { - PyErr_SetString(PyExc_AttributeError, "Invalid polygon index"); + else { + PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, polygon is NULL, unknown reason"); } return polyob; } @@ -278,3 +265,97 @@ KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh, //this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ? Py_RETURN_NONE;//(KX_ReInstanceShapeFromMesh(m_meshobj)) ? Py_RETURN_TRUE : Py_RETURN_FALSE; } + +PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MeshProxy* self= static_cast<KX_MeshProxy*>(self_v); + + int tot= self->m_meshobj->NumMaterials(); + int i; + + PyObject *materials = PyList_New( tot ); + + list<RAS_MeshMaterial>::iterator mit= self->m_meshobj->GetFirstMaterial(); + + + for(i=0; i<tot; mit++, i++) { + RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); + + /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */ + if(polymat->GetFlag() & RAS_BLENDERMAT) + { + KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat); + PyList_SET_ITEM(materials, i, mat->GetProxy()); + } + else { + KX_PolygonMaterial *mat = static_cast<KX_PolygonMaterial*>(polymat); + PyList_SET_ITEM(materials, i, mat->GetProxy()); + } + } + return materials; +} + +PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { + KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv); + return PyInt_FromLong(self->m_meshobj->NumMaterials()); +} + +PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { + KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv); + return PyInt_FromLong(self->m_meshobj->NumPolygons()); +} + +/* a close copy of ConvertPythonToGameObject but for meshes */ +bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix) +{ + if (value==NULL) { + PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); + *object = NULL; + return false; + } + + if (value==Py_None) { + *object = NULL; + + if (py_none_ok) { + return true; + } else { + PyErr_Format(PyExc_TypeError, "%s, expected KX_MeshProxy or a KX_MeshProxy name, None is invalid", error_prefix); + return false; + } + } + + if (PyString_Check(value)) { + *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) )); + + if (*object) { + return true; + } else { + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value)); + return false; + } + } + + if (PyObject_TypeCheck(value, &KX_MeshProxy::Type)) { + KX_MeshProxy *kx_mesh = static_cast<KX_MeshProxy*>BGE_PROXY_REF(value); + + /* sets the error */ + if (*object==NULL) { + PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + return false; + } + + *object = kx_mesh->GetMesh(); + return true; + } + + *object = NULL; + + if (py_none_ok) { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy, a string or None", error_prefix); + } else { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy or a string", error_prefix); + } + + return false; +} diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 34f60a54a3a..aeecefc09e6 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -31,6 +31,9 @@ #include "SCA_IObject.h" +/* utility conversion function */ +bool ConvertPythonToMesh(PyObject * value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix); + class KX_MeshProxy : public SCA_IObject { Py_Header; @@ -46,24 +49,31 @@ public: virtual CValue* Calc(VALUE_OPERATOR op, CValue *val) ; virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); virtual const STR_String & GetText(); - virtual float GetNumber(); + virtual double GetNumber(); + virtual RAS_MeshObject* GetMesh() { return m_meshobj; } virtual STR_String GetName(); virtual void SetName(STR_String name); // Set the name of the value virtual void ReplicaSetName(STR_String name); virtual CValue* GetReplica(); // stuff for python integration - virtual PyObject* _getattr(const char *attr); - KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); + + KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); // Deprecated KX_PYMETHOD(KX_MeshProxy,GetMaterialName); KX_PYMETHOD(KX_MeshProxy,GetTextureName); - KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons); + KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons); // Deprecated // both take materialid (int) KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); KX_PYMETHOD(KX_MeshProxy,GetPolygon); KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh); + + static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject * pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef); + static PyObject * pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef); }; #endif //__KX_MESHPROXY diff --git a/source/gameengine/Ketsji/KX_MotionState.cpp b/source/gameengine/Ketsji/KX_MotionState.cpp index 15f100af915..b4d58dccfdf 100644 --- a/source/gameengine/Ketsji/KX_MotionState.cpp +++ b/source/gameengine/Ketsji/KX_MotionState.cpp @@ -44,7 +44,7 @@ KX_MotionState::~KX_MotionState() void KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ) { - MT_Point3 pos = m_node->GetWorldPosition(); + const MT_Point3& pos = m_node->GetWorldPosition(); posX = pos[0]; posY = pos[1]; posZ = pos[2]; @@ -52,7 +52,7 @@ void KX_MotionState::getWorldPosition(float& posX,float& posY,float& posZ) void KX_MotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ) { - MT_Vector3 scale = m_node->GetWorldScaling(); + const MT_Vector3& scale = m_node->GetWorldScaling(); scaleX = scale[0]; scaleY = scale[1]; scaleZ = scale[2]; @@ -67,10 +67,16 @@ void KX_MotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatReal = orn[3]; } +void KX_MotionState::getWorldOrientation(float* ori) +{ + const MT_Matrix3x3& mat = m_node->GetWorldOrientation(); + mat.getValue(ori); +} + void KX_MotionState::setWorldPosition(float posX,float posY,float posZ) { m_node->SetLocalPosition(MT_Point3(posX,posY,posZ)); - m_node->SetWorldPosition(MT_Point3(posX,posY,posZ)); + //m_node->SetWorldPosition(MT_Point3(posX,posY,posZ)); } void KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal) @@ -82,13 +88,15 @@ void KX_MotionState::setWorldOrientation(float quatIma0,float quatIma1,float qua orn[3] = quatReal; m_node->SetLocalOrientation(orn); - m_node->SetWorldOrientation(orn); + //m_node->SetWorldOrientation(orn); } void KX_MotionState::calculateWorldTransformations() { - m_node->ComputeWorldTransforms(NULL); + //Not needed, will be done in KX_Scene::UpdateParents() after the physics simulation + //bool parentUpdated = false; + //m_node->ComputeWorldTransforms(NULL, parentUpdated); } diff --git a/source/gameengine/Ketsji/KX_MotionState.h b/source/gameengine/Ketsji/KX_MotionState.h index c83af664817..7ba3ca2f85c 100644 --- a/source/gameengine/Ketsji/KX_MotionState.h +++ b/source/gameengine/Ketsji/KX_MotionState.h @@ -44,6 +44,7 @@ public: virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal); virtual void setWorldPosition(float posX,float posY,float posZ); virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal); + virtual void getWorldOrientation(float* ori); virtual void calculateWorldTransformations(); }; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 384034485e7..87b5c81392d 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -61,14 +61,12 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, int starty, short int mousemode, int focusmode, - RAS_ICanvas* canvas, KX_Scene* kxscene, KX_KetsjiEngine *kxengine, SCA_IObject* gameobj, PyTypeObject* T) : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T), m_focusmode(focusmode), - m_gp_canvas(canvas), m_kxscene(kxscene), m_kxengine(kxengine) { @@ -81,6 +79,11 @@ void KX_MouseFocusSensor::Init() m_positive_event = false; m_hitObject = 0; m_reset = true; + + m_hitPosition.setValue(0,0,0); + m_prevTargetPoint.setValue(0,0,0); + m_prevSourcePoint.setValue(0,0,0); + m_hitNormal.setValue(0,0,1); } bool KX_MouseFocusSensor::Evaluate(CValue* event) @@ -150,12 +153,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* r -bool KX_MouseFocusSensor::ParentObjectHasFocus(void) +bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) { - m_hitObject = 0; - m_hitPosition = MT_Vector3(0,0,0); - m_hitNormal = MT_Vector3(1,0,0); - /* All screen handling in the gameengine is done by GL, * specifically the model/view and projection parts. The viewport * part is in the creator. @@ -187,6 +186,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) * = 1.0 - 2(y_blender - y_lb)/height * * */ + /* Because we don't want to worry about resize events, camera * changes and all that crap, we just determine this over and @@ -195,15 +195,18 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) * canvas, the test is irrelevant. The 1.0 makes sure the * calculations don't bomb. Maybe we should explicitly guard for * division by 0.0...*/ - - KX_Camera* cam = m_kxscene->GetActiveCamera(); - - /* get the scenes current viewport. we recompute it because there - * may be multiple cameras and m_kxscene->GetSceneViewport() only - * has the one that was last drawn */ - + RAS_Rect area, viewport; m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport); + + /* Check if the mouse is in the viewport */ + if (( m_x < viewport.m_x2 && // less then right + m_x > viewport.m_x1 && // more then then left + m_y < viewport.m_y2 && // below top + m_y > viewport.m_y1) == 0) // above bottom + { + return false; + } float height = float(viewport.m_y2 - viewport.m_y1 + 1); float width = float(viewport.m_x2 - viewport.m_x1 + 1); @@ -211,14 +214,13 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) float x_lb = float(viewport.m_x1); float y_lb = float(viewport.m_y1); + MT_Vector4 frompoint; + MT_Vector4 topoint; + /* There's some strangeness I don't fully get here... These values - * _should_ be wrong! */ + * _should_ be wrong! - see from point Z values */ + - - /* old: */ - float nearclip = 0.0; - float farclip = 1.0; - /* build the from and to point in normalized device coordinates * Looks like normailized device coordinates are [-1,1] in x [-1,1] in y * [0,-1] in z @@ -226,18 +228,15 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) * The actual z coordinates used don't have to be exact just infront and * behind of the near and far clip planes. */ - MT_Vector4 frompoint = MT_Vector4( - (2 * (m_x-x_lb) / width) - 1.0, - 1.0 - (2 * (m_y - y_lb) / height), - nearclip, - 1.0 - ); - MT_Vector4 topoint = MT_Vector4( - (2 * (m_x-x_lb) / width) - 1.0, - 1.0 - (2 * (m_y-y_lb) / height), - farclip, - 1.0 - ); + frompoint.setValue( (2 * (m_x-x_lb) / width) - 1.0, + 1.0 - (2 * (m_y - y_lb) / height), + 0.0, /* nearclip, see above comments */ + 1.0 ); + + topoint.setValue( (2 * (m_x-x_lb) / width) - 1.0, + 1.0 - (2 * (m_y-y_lb) / height), + 1.0, /* farclip, see above comments */ + 1.0 ); /* camera to world */ MT_Transform wcs_camcs_tranform = cam->GetWorldToCamera(); @@ -260,31 +259,74 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) topoint = camcs_wcs_matrix * topoint; /* from hom wcs to 3d wcs: */ - MT_Point3 frompoint3 = MT_Point3(frompoint[0]/frompoint[3], - frompoint[1]/frompoint[3], - frompoint[2]/frompoint[3]); - MT_Point3 topoint3 = MT_Point3(topoint[0]/topoint[3], - topoint[1]/topoint[3], - topoint[2]/topoint[3]); - m_prevTargetPoint = topoint3; - m_prevSourcePoint = frompoint3; + m_prevSourcePoint.setValue( frompoint[0]/frompoint[3], + frompoint[1]/frompoint[3], + frompoint[2]/frompoint[3]); + + m_prevTargetPoint.setValue( topoint[0]/topoint[3], + topoint[1]/topoint[3], + topoint[2]/topoint[3]); /* 2. Get the object from PhysicsEnvironment */ /* Shoot! Beware that the first argument here is an * ignore-object. We don't ignore anything... */ - KX_IPhysicsController* physics_controller = cam->GetPhysicsController(); PHY_IPhysicsEnvironment* physics_environment = m_kxscene->GetPhysicsEnvironment(); - bool result = false; - KX_RayCast::Callback<KX_MouseFocusSensor> callback(this,physics_controller); - KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback); + + KX_RayCast::RayTest(physics_environment, m_prevSourcePoint, m_prevTargetPoint, callback); + + if (m_hitObject) + return true; - result = (m_hitObject!=0); + return false; +} - return result; +bool KX_MouseFocusSensor::ParentObjectHasFocus() +{ + m_hitObject = 0; + m_hitPosition.setValue(0,0,0); + m_hitNormal.setValue(1,0,0); + + KX_Camera *cam= m_kxscene->GetActiveCamera(); + + if(ParentObjectHasFocusCamera(cam)) + return true; + + list<class KX_Camera*>* cameras = m_kxscene->GetCameras(); + list<KX_Camera*>::iterator it = cameras->begin(); + + while(it != cameras->end()) + { + if(((*it) != cam) && (*it)->GetViewport()) + if (ParentObjectHasFocusCamera(*it)) + return true; + + it++; + } + + return false; +} + +const MT_Point3& KX_MouseFocusSensor::RaySource() const +{ + return m_prevSourcePoint; +} + +const MT_Point3& KX_MouseFocusSensor::RayTarget() const +{ + return m_prevTargetPoint; +} + +const MT_Point3& KX_MouseFocusSensor::HitPosition() const +{ + return m_hitPosition; +} +const MT_Vector3& KX_MouseFocusSensor::HitNormal() const +{ + return m_hitNormal; } /* ------------------------------------------------------------------------- */ @@ -293,22 +335,22 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_MouseFocusSensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_MouseFocusSensor", - sizeof(KX_MouseFocusSensor), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_MouseFocusSensor::Parents[] = { @@ -328,26 +370,33 @@ PyMethodDef KX_MouseFocusSensor::Methods[] = { {"getHitNormal",(PyCFunction) KX_MouseFocusSensor::sPyGetHitNormal,METH_NOARGS, (PY_METHODCHAR)GetHitNormal_doc}, {"getRayDirection",(PyCFunction) KX_MouseFocusSensor::sPyGetRayDirection,METH_NOARGS, (PY_METHODCHAR)GetRayDirection_doc}, - {NULL,NULL} //Sentinel }; PyAttributeDef KX_MouseFocusSensor::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("raySource", KX_MouseFocusSensor, pyattr_get_ray_source), + KX_PYATTRIBUTE_RO_FUNCTION("rayTarget", KX_MouseFocusSensor, pyattr_get_ray_target), + KX_PYATTRIBUTE_RO_FUNCTION("rayDirection", KX_MouseFocusSensor, pyattr_get_ray_direction), + KX_PYATTRIBUTE_RO_FUNCTION("hitObject", KX_MouseFocusSensor, pyattr_get_hit_object), + KX_PYATTRIBUTE_RO_FUNCTION("hitPosition", KX_MouseFocusSensor, pyattr_get_hit_position), + KX_PYATTRIBUTE_RO_FUNCTION("hitNormal", KX_MouseFocusSensor, pyattr_get_hit_normal), { NULL } //Sentinel }; -PyObject* KX_MouseFocusSensor::_getattr(const char *attr) { - _getattr_up(SCA_MouseSensor); +PyObject* KX_MouseFocusSensor::py_getattro(PyObject *attr) { + py_getattro_up(SCA_MouseSensor); } const char KX_MouseFocusSensor::GetHitObject_doc[] = "getHitObject()\n" -"\tReturns the name of the object that was hit by this ray.\n"; -PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self) +"\tReturns the object that was hit by this ray.\n"; +PyObject* KX_MouseFocusSensor::PyGetHitObject() { + ShowDeprecationWarning("GetHitObject()", "the hitObject property"); + if (m_hitObject) - return m_hitObject->AddRef(); + return m_hitObject->GetProxy(); Py_RETURN_NONE; } @@ -356,27 +405,33 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self) const char KX_MouseFocusSensor::GetHitPosition_doc[] = "getHitPosition()\n" "\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n"; -PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self) +PyObject* KX_MouseFocusSensor::PyGetHitPosition() { + ShowDeprecationWarning("getHitPosition()", "the hitPosition property"); + return PyObjectFrom(m_hitPosition); } const char KX_MouseFocusSensor::GetRayDirection_doc[] = "getRayDirection()\n" "\tReturns the direction from the ray (in worldcoordinates) .\n"; -PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self) +PyObject* KX_MouseFocusSensor::PyGetRayDirection() { - + ShowDeprecationWarning("getRayDirection()", "the rayDirection property"); + MT_Vector3 dir = m_prevTargetPoint - m_prevSourcePoint; - dir.normalize(); + if(MT_fuzzyZero(dir)) dir.setValue(0,0,0); + else dir.normalize(); return PyObjectFrom(dir); } const char KX_MouseFocusSensor::GetHitNormal_doc[] = "getHitNormal()\n" -"\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n"; -PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self) +"\tReturns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray.\n"; +PyObject* KX_MouseFocusSensor::PyGetHitNormal() { + ShowDeprecationWarning("getHitNormal()", "the hitNormal property"); + return PyObjectFrom(m_hitNormal); } @@ -386,7 +441,10 @@ const char KX_MouseFocusSensor::GetRayTarget_doc[] = "getRayTarget()\n" "\tReturns the target of the ray that seeks the focus object,\n" "\tin worldcoordinates."; -PyObject* KX_MouseFocusSensor::PyGetRayTarget(PyObject* self) { +PyObject* KX_MouseFocusSensor::PyGetRayTarget() +{ + ShowDeprecationWarning("getRayTarget()", "the rayTarget property"); + return PyObjectFrom(m_prevTargetPoint); } @@ -395,9 +453,58 @@ const char KX_MouseFocusSensor::GetRaySource_doc[] = "getRaySource()\n" "\tReturns the source of the ray that seeks the focus object,\n" "\tin worldcoordinates."; -PyObject* KX_MouseFocusSensor::PyGetRaySource(PyObject* self) { +PyObject* KX_MouseFocusSensor::PyGetRaySource() +{ + ShowDeprecationWarning("getRaySource()", "the raySource property"); + return PyObjectFrom(m_prevSourcePoint); } +/* Attributes */ +PyObject* KX_MouseFocusSensor::pyattr_get_ray_source(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); + return PyObjectFrom(self->RaySource()); +} + +PyObject* KX_MouseFocusSensor::pyattr_get_ray_target(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); + return PyObjectFrom(self->RayTarget()); +} + +PyObject* KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); + MT_Vector3 dir = self->RayTarget() - self->RaySource(); + if(MT_fuzzyZero(dir)) dir.setValue(0,0,0); + else dir.normalize(); + return PyObjectFrom(dir); +} + +PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); + + if(self->m_hitObject) + return self->m_hitObject->GetProxy(); + + Py_RETURN_NONE; +} + +PyObject* KX_MouseFocusSensor::pyattr_get_hit_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); + return PyObjectFrom(self->HitPosition()); +} + +PyObject* KX_MouseFocusSensor::pyattr_get_hit_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); + return PyObjectFrom(self->HitNormal()); +} + + + /* eof */ diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 4979783032c..8de1f88c5c3 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -54,7 +54,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor int starty, short int mousemode, int focusmode, - RAS_ICanvas* canvas, KX_Scene* kxscene, KX_KetsjiEngine* kxengine, SCA_IObject* gameobj, @@ -82,12 +81,15 @@ class KX_MouseFocusSensor : public SCA_MouseSensor bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } - + const MT_Point3& RaySource() const; + const MT_Point3& RayTarget() const; + const MT_Point3& HitPosition() const; + const MT_Vector3& HitNormal() const; /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource); @@ -97,6 +99,14 @@ class KX_MouseFocusSensor : public SCA_MouseSensor KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetHitNormal); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayDirection); + /* attributes */ + static PyObject* pyattr_get_ray_source(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_ray_target(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_ray_direction(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hit_object(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hit_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hit_normal(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + /* --------------------------------------------------------------------- */ SCA_IObject* m_hitObject; @@ -116,9 +126,13 @@ class KX_MouseFocusSensor : public SCA_MouseSensor */ bool m_positive_event; + /** + * Tests whether the object is in mouse focus for this camera + */ + bool ParentObjectHasFocusCamera(KX_Camera *cam); /** - * Tests whether the object is in mouse focus in this frame. + * Tests whether the object is in mouse focus in this scene. */ bool ParentObjectHasFocus(void); @@ -142,12 +156,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor * the object was hit. */ MT_Vector3 m_hitNormal; - - /** - * The active canvas. The size of this canvas determines a part of - * the start position of the picking ray. */ - RAS_ICanvas* m_gp_canvas; - /** * The KX scene that holds the camera. The camera position * determines a part of the start location of the picking ray. */ diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 993a6b3d86c..0489b7090e9 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -127,13 +127,10 @@ CValue* KX_NearSensor::GetReplica() } } - //static_cast<KX_TouchEventManager*>(m_eventmgr)->RegisterSensor(this); - //todo: make sure replication works fine - //>m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL); - //replica->m_sumoObj->setMargin(m_Margin); - //replica->m_sumoObj->setClientObject(replica->m_client_info); - - ((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL); + //Wrong: the parent object could be a child, this code works only if it is a root parent. + //Anyway, at this stage, the parent object is already synchronized, nothing to do. + //bool parentUpdated = false; + //((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL, parentUpdated); replica->SynchronizeTransform(); return replica; @@ -154,8 +151,10 @@ void KX_NearSensor::ReParent(SCA_IObject* parent) client_info->m_sensors.push_back(this); SCA_ISensor::ReParent(parent); */ - ((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL); - SynchronizeTransform(); + //Not needed, was done in GetReplica() already + //bool parentUpdated = false; + //((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL,parentUpdated); + //SynchronizeTransform(); SCA_ISensor::ReParent(parent); } @@ -287,22 +286,22 @@ bool KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData /* ------------------------------------------------------------------------- */ PyTypeObject KX_NearSensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_NearSensor", - sizeof(KX_NearSensor), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -330,20 +329,12 @@ PyAttributeDef KX_NearSensor::Attributes[] = { }; -PyObject* KX_NearSensor::_getattr(const char *attr) +PyObject* KX_NearSensor::py_getattro(PyObject *attr) { - PyObject* object = _getattr_self(Attributes, this, attr); - if (object != NULL) - return object; - - _getattr_up(KX_TouchSensor); + py_getattro_up(KX_TouchSensor); } -int KX_NearSensor::_setattr(const char *attr, PyObject* value) +int KX_NearSensor::py_setattro(PyObject*attr, PyObject* value) { - int ret = _setattr_self(Attributes, this, attr, value); - if (ret >= 0) - return ret; - - return KX_TouchSensor::_setattr(attr, value); + py_setattro_up(KX_TouchSensor); } diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index ee03992e734..26c5feb4e67 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -82,8 +82,8 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject* value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); //No methods diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 0666261b470..861c5757971 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -277,22 +277,22 @@ bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_ObjectActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_ObjectActuator", - sizeof(KX_ObjectActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_ObjectActuator::Parents[] = { @@ -336,15 +336,15 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ObjectActuator::_getattr(const char *attr) { - _getattr_up(SCA_IActuator); +PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) { + py_getattro_up(SCA_IActuator); }; /* 1. set ------------------------------------------------------------------ */ /* Removed! */ /* 2. getForce */ -PyObject* KX_ObjectActuator::PyGetForce(PyObject* self) +PyObject* KX_ObjectActuator::PyGetForce() { PyObject *retVal = PyList_New(4); @@ -356,13 +356,11 @@ PyObject* KX_ObjectActuator::PyGetForce(PyObject* self) return retVal; } /* 3. setForce */ -PyObject* KX_ObjectActuator::PySetForce(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetForce(PyObject* args) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], + if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { return NULL; } @@ -373,7 +371,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self, } /* 4. getTorque */ -PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self) +PyObject* KX_ObjectActuator::PyGetTorque() { PyObject *retVal = PyList_New(4); @@ -385,13 +383,11 @@ PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self) return retVal; } /* 5. setTorque */ -PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetTorque(PyObject* args) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], + if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { return NULL; } @@ -402,7 +398,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, } /* 6. getDLoc */ -PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self) +PyObject* KX_ObjectActuator::PyGetDLoc() { PyObject *retVal = PyList_New(4); @@ -414,13 +410,11 @@ PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self) return retVal; } /* 7. setDLoc */ -PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args) { float vecArg[3]; int bToggle = 0; - if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], + if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { return NULL; } @@ -431,7 +425,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, } /* 8. getDRot */ -PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self) +PyObject* KX_ObjectActuator::PyGetDRot() { PyObject *retVal = PyList_New(4); @@ -443,13 +437,11 @@ PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self) return retVal; } /* 9. setDRot */ -PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetDRot(PyObject* args) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], + if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { return NULL; } @@ -460,7 +452,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, } /* 10. getLinearVelocity */ -PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self) { +PyObject* KX_ObjectActuator::PyGetLinearVelocity() { PyObject *retVal = PyList_New(4); PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); @@ -472,12 +464,10 @@ PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self) { } /* 11. setLinearVelocity */ -PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], + if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { return NULL; } @@ -489,7 +479,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, /* 12. getAngularVelocity */ -PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self) { +PyObject* KX_ObjectActuator::PyGetAngularVelocity() { PyObject *retVal = PyList_New(4); PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); @@ -500,12 +490,10 @@ PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self) { return retVal; } /* 13. setAngularVelocity */ -PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) { float vecArg[3]; int bToggle = 0; - if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], + if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { return NULL; } @@ -516,11 +504,9 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, } /* 13. setDamping */ -PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) { int damping = 0; - if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) { + if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) { return NULL; } m_damping = damping; @@ -528,11 +514,11 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, } /* 13. getVelocityDamping */ -PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self) { +PyObject* KX_ObjectActuator::PyGetDamping() { return Py_BuildValue("i",m_damping); } /* 6. getForceLimitX */ -PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self) +PyObject* KX_ObjectActuator::PyGetForceLimitX() { PyObject *retVal = PyList_New(3); @@ -543,13 +529,11 @@ PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self) return retVal; } /* 7. setForceLimitX */ -PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args) { float vecArg[2]; int bToggle = 0; - if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) { + if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) { return NULL; } m_drot[0] = vecArg[0]; @@ -559,7 +543,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, } /* 6. getForceLimitY */ -PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self) +PyObject* KX_ObjectActuator::PyGetForceLimitY() { PyObject *retVal = PyList_New(3); @@ -570,13 +554,11 @@ PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self) return retVal; } /* 7. setForceLimitY */ -PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args) { float vecArg[2]; int bToggle = 0; - if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) { + if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) { return NULL; } m_drot[1] = vecArg[0]; @@ -586,7 +568,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, } /* 6. getForceLimitZ */ -PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self) +PyObject* KX_ObjectActuator::PyGetForceLimitZ() { PyObject *retVal = PyList_New(3); @@ -597,13 +579,11 @@ PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self) return retVal; } /* 7. setForceLimitZ */ -PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args) { float vecArg[2]; int bToggle = 0; - if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) { + if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) { return NULL; } m_drot[2] = vecArg[0]; @@ -613,7 +593,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, } /* 4. getPID */ -PyObject* KX_ObjectActuator::PyGetPID(PyObject* self) +PyObject* KX_ObjectActuator::PyGetPID() { PyObject *retVal = PyList_New(3); @@ -624,12 +604,10 @@ PyObject* KX_ObjectActuator::PyGetPID(PyObject* self) return retVal; } /* 5. setPID */ -PyObject* KX_ObjectActuator::PySetPID(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PySetPID(PyObject* args) { float vecArg[3]; - if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) { + if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) { return NULL; } m_torque.setValue(vecArg); diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 0331c67617c..a812942a0ae 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -153,30 +153,30 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); - KX_PYMETHOD(KX_ObjectActuator,SetForce); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForce); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetTorque); - KX_PYMETHOD(KX_ObjectActuator,SetTorque); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetTorque); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDLoc); - KX_PYMETHOD(KX_ObjectActuator,SetDLoc); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetDLoc); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDRot); - KX_PYMETHOD(KX_ObjectActuator,SetDRot); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetDRot); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetLinearVelocity); - KX_PYMETHOD(KX_ObjectActuator,SetLinearVelocity); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetLinearVelocity); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetAngularVelocity); - KX_PYMETHOD(KX_ObjectActuator,SetAngularVelocity); - KX_PYMETHOD(KX_ObjectActuator,SetDamping); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetAngularVelocity); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetDamping); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDamping); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitX); - KX_PYMETHOD(KX_ObjectActuator,SetForceLimitX); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitX); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitY); - KX_PYMETHOD(KX_ObjectActuator,SetForceLimitY); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitY); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitZ); - KX_PYMETHOD(KX_ObjectActuator,SetForceLimitZ); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitZ); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetPID); - KX_PYMETHOD(KX_ObjectActuator,SetPID); + KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetPID); }; #endif //__KX_OBJECTACTUATOR diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h index e3b5336c0b5..21b7e632d83 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h @@ -82,6 +82,10 @@ public: virtual SG_Controller* GetReplica(class SG_Node* destnode); + virtual float GetLinVelocityMin() { return ODEPhysicsController::GetLinVelocityMin(); } + virtual void SetLinVelocityMin(float val) { ODEPhysicsController::SetLinVelocityMin(val); } + virtual float GetLinVelocityMax() { return ODEPhysicsController::GetLinVelocityMax(); } + virtual void SetLinVelocityMax(float val) { ODEPhysicsController::SetLinVelocityMax(val); } virtual void SetSumoTransform(bool nondynaonly); // todo: remove next line ! diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 84d7ccb9c05..0093cf5f313 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -1,7 +1,7 @@ /** * Set or remove an objects parent * - * $Id: SCA_ParentActuator.cpp 13932 2008-03-01 19:05:41Z ben2610 $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -139,22 +139,22 @@ bool KX_ParentActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_ParentActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_ParentActuator", - sizeof(KX_ParentActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_ParentActuator::Parents[] = { @@ -166,59 +166,67 @@ PyParentObject KX_ParentActuator::Parents[] = { }; PyMethodDef KX_ParentActuator::Methods[] = { - // ---> deprecated (all) - {"setObject", (PyCFunction) KX_ParentActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, - {"getObject", (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + // Deprecated -----> + {"setObject", (PyCFunction) KX_ParentActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, + {"getObject", (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, + // <----- {NULL,NULL} //Sentinel }; PyAttributeDef KX_ParentActuator::Attributes[] = { + KX_PYATTRIBUTE_RW_FUNCTION("object", KX_ParentActuator, pyattr_get_object, pyattr_set_object), { NULL } //Sentinel }; -PyObject* KX_ParentActuator::_getattr(const char *attr) { - - if (!strcmp(attr, "object")) { - if (!m_ob) Py_RETURN_NONE; - else return m_ob->AddRef(); - } - - _getattr_up(SCA_IActuator); +PyObject* KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_ParentActuator* actuator = static_cast<KX_ParentActuator*>(self); + if (!actuator->m_ob) + Py_RETURN_NONE; + else + return actuator->m_ob->GetProxy(); } -int KX_ParentActuator::_setattr(const char *attr, PyObject* value) { - - if (!strcmp(attr, "object")) { - KX_GameObject *gameobj; +int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ParentActuator* actuator = static_cast<KX_ParentActuator*>(self); + KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) - return 1; // ConvertPythonToGameObject sets the error + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_ParentActuator")) + return 1; // ConvertPythonToGameObject sets the error - if (m_ob != NULL) - m_ob->UnregisterActuator(this); + if (actuator->m_ob != NULL) + actuator->m_ob->UnregisterActuator(actuator); - m_ob = (SCA_IObject*)gameobj; + actuator->m_ob = (SCA_IObject*) gameobj; - if (m_ob) - m_ob->RegisterActuator(this); + if (actuator->m_ob) + actuator->m_ob->RegisterActuator(actuator); - return 0; - } - - return SCA_IActuator::_setattr(attr, value); + return 0; +} + + +PyObject* KX_ParentActuator::py_getattro(PyObject *attr) { + py_getattro_up(SCA_IActuator); +} + +int KX_ParentActuator::py_setattro(PyObject *attr, PyObject* value) { + py_setattro_up(SCA_IActuator); } +/* Deprecated -----> */ /* 1. setObject */ const char KX_ParentActuator::SetObject_doc[] = "setObject(object)\n" "\t- object: KX_GameObject, string or None\n" "\tSet the object to set as parent.\n"; -PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* value) { +PyObject* KX_ParentActuator::PySetObject(PyObject* value) { KX_GameObject *gameobj; ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_ParentActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_ob != NULL) @@ -238,13 +246,13 @@ const char KX_ParentActuator::GetObject_doc[] = "getObject(name_only = 1)\n" "name_only - optional arg, when true will return the KX_GameObject rather then its name\n" "\tReturns the object that is set to.\n"; -PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args) +PyObject* KX_ParentActuator::PyGetObject(PyObject* args) { int ret_name_only = 1; ShowDeprecationWarning("getObject()", "the object property"); - if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) + if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only)) return NULL; if (!m_ob) @@ -253,7 +261,8 @@ PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_ob->GetName()); else - return m_ob->AddRef(); + return m_ob->GetProxy(); } +/* <----- */ /* eof */ diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index c974001c0d0..f9f0b73b876 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -2,7 +2,7 @@ * Set or remove an objects parent * * - * $Id: KX_ParentActuator.h 3271 2004-10-16 11:41:50Z kester $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -76,13 +76,17 @@ class KX_ParentActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject* value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); - /* 1. setObject */ + /* These are used to get and set m_ob */ + static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + + // Deprecated -----> KX_PYMETHOD_DOC_O(KX_ParentActuator,SetObject); - /* 2. getObject */ KX_PYMETHOD_DOC_VARARGS(KX_ParentActuator,GetObject); + // <----- }; /* end of class KX_ParentActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index 246c63feb21..fda639c09e0 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -51,12 +51,10 @@ KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper() } -PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* args) { float x,y,z; - if (PyArg_ParseTuple(args,"fff",&x,&y,&z)) + if (PyArg_ParseTuple(args,"fff:setPosition",&x,&y,&z)) { m_ctrl->setPosition(x,y,z); } @@ -67,13 +65,11 @@ PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* self, } -PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* args) { float x,y,z; int local; - if (PyArg_ParseTuple(args,"fffi",&x,&y,&z,&local)) + if (PyArg_ParseTuple(args,"fffi:setLinearVelocity",&x,&y,&z,&local)) { m_ctrl->SetLinearVelocity(x,y,z,local != 0); } @@ -83,13 +79,11 @@ PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* args) { float x,y,z; int local; - if (PyArg_ParseTuple(args,"fffi",&x,&y,&z,&local)) + if (PyArg_ParseTuple(args,"fffi:setAngularVelocity",&x,&y,&z,&local)) { m_ctrl->SetAngularVelocity(x,y,z,local != 0); } @@ -99,12 +93,10 @@ PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject* args) { int active; - if (PyArg_ParseTuple(args,"i",&active)) + if (PyArg_ParseTuple(args,"i:setActive",&active)) { m_ctrl->SetActive(active!=0); } @@ -115,26 +107,28 @@ PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject* self, } - +PyAttributeDef KX_PhysicsObjectWrapper::Attributes[] = { + { NULL } //Sentinel +}; //python specific stuff PyTypeObject KX_PhysicsObjectWrapper::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_PhysicsObjectWrapper", - sizeof(KX_PhysicsObjectWrapper), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_PhysicsObjectWrapper::Parents[] = { @@ -142,13 +136,13 @@ PyParentObject KX_PhysicsObjectWrapper::Parents[] = { NULL }; -PyObject* KX_PhysicsObjectWrapper::_getattr(const char *attr) +PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr) { - _getattr_up(PyObjectPlus); + py_getattro_up(PyObjectPlus); } -int KX_PhysicsObjectWrapper::_setattr(const char *attr,PyObject *pyobj) +int KX_PhysicsObjectWrapper::py_setattro(PyObject *attr,PyObject *pyobj) { int result = 1; @@ -161,7 +155,7 @@ int KX_PhysicsObjectWrapper::_setattr(const char *attr,PyObject *pyobj) result = 0; } if (result) - result = PyObjectPlus::_setattr(attr,pyobj); + result = PyObjectPlus::py_setattro(attr,pyobj); return result; }; diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index 95560698896..7e10dc3ccf4 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -36,16 +36,16 @@ class KX_PhysicsObjectWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); public: KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_PhysicsObjectWrapper(); - KX_PYMETHOD(KX_PhysicsObjectWrapper , SetPosition); - KX_PYMETHOD(KX_PhysicsObjectWrapper,SetLinearVelocity); - KX_PYMETHOD(KX_PhysicsObjectWrapper,SetAngularVelocity); - KX_PYMETHOD(KX_PhysicsObjectWrapper,SetActive); + KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition); + KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetLinearVelocity); + KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetAngularVelocity); + KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetActive); private: class PHY_IPhysicsController* m_ctrl; diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index b4bdd77fb66..2e5dd72db0e 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -39,22 +39,22 @@ #include "KX_PyMath.h" PyTypeObject KX_PolyProxy::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_PolyProxy", - sizeof(KX_PolyProxy), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_PolyProxy::Parents[] = { @@ -78,42 +78,52 @@ PyMethodDef KX_PolyProxy::Methods[] = { }; PyAttributeDef KX_PolyProxy::Attributes[] = { + /* All dummy's so they come up in a dir() */ + KX_PYATTRIBUTE_DUMMY("matname"), + KX_PYATTRIBUTE_DUMMY("texture"), + KX_PYATTRIBUTE_DUMMY("material"), + KX_PYATTRIBUTE_DUMMY("matid"), + KX_PYATTRIBUTE_DUMMY("v1"), + KX_PYATTRIBUTE_DUMMY("v2"), + KX_PYATTRIBUTE_DUMMY("v3"), + KX_PYATTRIBUTE_DUMMY("v4"), + KX_PYATTRIBUTE_DUMMY("visible"), + KX_PYATTRIBUTE_DUMMY("collide"), { NULL } //Sentinel }; -PyObject* KX_PolyProxy::_getattr(const char *attr) +PyObject* KX_PolyProxy::py_getattro(PyObject *attr) { - if (!strcmp(attr, "matname")) + char *attr_str= PyString_AsString(attr); + if (!strcmp(attr_str, "matname")) { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } - if (!strcmp(attr, "texture")) + if (!strcmp(attr_str, "texture")) { return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } - if (!strcmp(attr, "material")) + if (!strcmp(attr_str, "material")) { RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } else { KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } } - if (!strcmp(attr, "matid")) + if (!strcmp(attr_str, "matid")) { // we'll have to scan through the material bucket of the mes and compare with // the one of the polygon RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial(); unsigned int matid; - for (matid=0; matid<m_mesh->NumMaterials(); matid++) + for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++) { RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid); if (meshMat->m_bucket == polyBucket) @@ -122,31 +132,31 @@ PyObject* KX_PolyProxy::_getattr(const char *attr) } return PyInt_FromLong(matid); } - if (!strcmp(attr, "v1")) + if (!strcmp(attr_str, "v1")) { return PyInt_FromLong(m_polygon->GetVertexOffset(0)); } - if (!strcmp(attr, "v2")) + if (!strcmp(attr_str, "v2")) { return PyInt_FromLong(m_polygon->GetVertexOffset(1)); } - if (!strcmp(attr, "v3")) + if (!strcmp(attr_str, "v3")) { return PyInt_FromLong(m_polygon->GetVertexOffset(2)); } - if (!strcmp(attr, "v4")) + if (!strcmp(attr_str, "v4")) { return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); } - if (!strcmp(attr, "visible")) + if (!strcmp(attr_str, "visible")) { return PyInt_FromLong(m_polygon->IsVisible()); } - if (!strcmp(attr, "collide")) + if (!strcmp(attr_str, "collide")) { return PyInt_FromLong(m_polygon->IsCollider()); } - _getattr_up(SCA_IObject); + py_getattro_up(SCA_IObject); } KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon) @@ -165,7 +175,7 @@ CValue* KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;} CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} STR_String sPolyName="polygone"; const STR_String & KX_PolyProxy::GetText() {return sPolyName;}; -float KX_PolyProxy::GetNumber() { return -1;} +double KX_PolyProxy::GetNumber() { return -1;} STR_String KX_PolyProxy::GetName() { return sPolyName;} void KX_PolyProxy::SetName(STR_String) { }; CValue* KX_PolyProxy::GetReplica() { return NULL;} @@ -179,7 +189,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, { RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial(); unsigned int matid; - for (matid=0; matid<m_mesh->NumMaterials(); matid++) + for (matid=0; matid<(unsigned int)m_mesh->NumMaterials(); matid++) { RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid); if (meshMat->m_bucket == polyBucket) @@ -226,13 +236,13 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, "Note: getVertexIndex(3) on a triangle polygon returns 0\n") { int index; - if (!PyArg_ParseTuple(args,"i",&index)) + if (!PyArg_ParseTuple(args,"i:getVertexIndex",&index)) { return NULL; } if (index < 0 || index > 3) { - PyErr_SetString(PyExc_AttributeError, "Valid range for index is 0-3"); + PyErr_SetString(PyExc_AttributeError, "poly.getVertexIndex(int): KX_PolyProxy, expected an index between 0-3"); return NULL; } if (index < m_polygon->VertexCount()) @@ -246,7 +256,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, "getMesh() : returns a mesh proxy\n") { KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh); - return meshproxy; + return meshproxy->NewProxy(true); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial, @@ -256,13 +266,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial, if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } else { KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } } diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index 9b548f9490d..275e65da810 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -45,7 +45,7 @@ public: CValue* Calc(VALUE_OPERATOR op, CValue *val) ; CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); const STR_String & GetText(); - float GetNumber(); + double GetNumber(); STR_String GetName(); void SetName(STR_String name); // Set the name of the value void ReplicaSetName(STR_String name); @@ -53,7 +53,7 @@ public: // stuff for python integration - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index bbaf697b168..46d04486cc6 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -98,8 +98,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI { PyObject *pyRasty = PyCObject_FromVoidPtr((void*)rasty, NULL); /* new reference */ PyObject *pyCachingInfo = PyCObject_FromVoidPtr((void*) &cachingInfo, NULL); /* new reference */ - - PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this); + PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy); if (ret) { bool value = PyInt_AsLong(ret); @@ -109,6 +108,8 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI else { PyErr_Print(); + PyErr_Clear(); + PySys_SetObject( (char *)"last_traceback", NULL); } } else @@ -181,181 +182,70 @@ PyMethodDef KX_PolygonMaterial::Methods[] = { }; PyAttributeDef KX_PolygonMaterial::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("texture", KX_PolygonMaterial, pyattr_get_texture), + KX_PYATTRIBUTE_RO_FUNCTION("material", KX_PolygonMaterial, pyattr_get_material), /* should probably be .name ? */ + + KX_PYATTRIBUTE_INT_RW("tile", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tile), + KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep), + KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep), + KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode), + KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer), + + KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha), + KX_PYATTRIBUTE_BOOL_RW("zsort", KX_PolygonMaterial, m_zsort), + + KX_PYATTRIBUTE_FLOAT_RW("shininess", 0.0f, 1000.0f, KX_PolygonMaterial, m_shininess), + KX_PYATTRIBUTE_FLOAT_RW("specularity", 0.0f, 1000.0f, KX_PolygonMaterial, m_specularity), + + KX_PYATTRIBUTE_RW_FUNCTION("diffuse", KX_PolygonMaterial, pyattr_get_texture, pyattr_set_diffuse), + KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular), + + KX_PYATTRIBUTE_RO_FUNCTION("tface", KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */ + KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */ + + /* triangle used to be an attribute, removed for 2.49, nobody should be using it */ { NULL } //Sentinel }; PyTypeObject KX_PolygonMaterial::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_PolygonMaterial", - sizeof(KX_PolygonMaterial), + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, 0, - PyDestructor, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0 //&cvalue_as_number, + 0, + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_PolygonMaterial::Parents[] = { - &PyObjectPlus::Type, &KX_PolygonMaterial::Type, + &PyObjectPlus::Type, NULL }; -PyObject* KX_PolygonMaterial::_getattr(const char *attr) -{ - if (!strcmp(attr, "texture")) - return PyString_FromString(m_texturename.ReadPtr()); - if (!strcmp(attr, "material")) - return PyString_FromString(m_materialname.ReadPtr()); - - if (!strcmp(attr, "tface")) - return PyCObject_FromVoidPtr(m_tface, NULL); - - if (!strcmp(attr, "gl_texture")) - { - Image *ima = m_tface->tpage; - int bind = 0; - if (ima) - bind = ima->bindcode; - - return PyInt_FromLong(bind); - } - - if (!strcmp(attr, "tile")) - return PyInt_FromLong(m_tile); - if (!strcmp(attr, "tilexrep")) - return PyInt_FromLong(m_tilexrep); - if (!strcmp(attr, "tileyrep")) - return PyInt_FromLong(m_tileyrep); - - if (!strcmp(attr, "drawingmode")) - return PyInt_FromLong(m_drawingmode); - if (!strcmp(attr, "transparent")) - return PyInt_FromLong(m_alpha); - if (!strcmp(attr, "zsort")) - return PyInt_FromLong(m_zsort); - if (!strcmp(attr, "lightlayer")) - return PyInt_FromLong(m_lightlayer); - if (!strcmp(attr, "triangle")) - // deprecated, triangle/quads shouldn't have been a material property - return 0; - - if (!strcmp(attr, "diffuse")) - return PyObjectFrom(m_diffuse); - if (!strcmp(attr, "shininess")) - return PyFloat_FromDouble(m_shininess); - if (!strcmp(attr, "specular")) - return PyObjectFrom(m_specular); - if (!strcmp(attr, "specularity")) - return PyFloat_FromDouble(m_specularity); - - _getattr_up(PyObjectPlus); +PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr) +{ + py_getattro_up(PyObjectPlus); } -int KX_PolygonMaterial::_setattr(const char *attr, PyObject *pyvalue) +int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value) { - if (PyFloat_Check(pyvalue)) - { - float value = PyFloat_AsDouble(pyvalue); - if (!strcmp(attr, "shininess")) - { - m_shininess = value; - return 0; - } - - if (!strcmp(attr, "specularity")) - { - m_specularity = value; - return 0; - } - } - - if (PyInt_Check(pyvalue)) - { - int value = PyInt_AsLong(pyvalue); - if (!strcmp(attr, "tile")) - { - m_tile = value; - return 0; - } - - if (!strcmp(attr, "tilexrep")) - { - m_tilexrep = value; - return 0; - } - - if (!strcmp(attr, "tileyrep")) - { - m_tileyrep = value; - return 0; - } - - if (!strcmp(attr, "drawingmode")) - { - m_drawingmode = value; - return 0; - } - - if (!strcmp(attr, "transparent")) - { - m_alpha = value; - return 0; - } - - if (!strcmp(attr, "zsort")) - { - m_zsort = value; - return 0; - } - - if (!strcmp(attr, "lightlayer")) - { - m_lightlayer = value; - return 0; - } - - // This probably won't work... - if (!strcmp(attr, "triangle")) - { - // deprecated, triangle/quads shouldn't have been a material property - return 0; - } - } - - if (PySequence_Check(pyvalue)) - { - if (PySequence_Size(pyvalue) == 3) - { - MT_Vector3 value; - if (PyVecTo(pyvalue, value)) - { - if (!strcmp(attr, "diffuse")) - { - m_diffuse = value; - return 0; - } - - if (!strcmp(attr, "specular")) - { - m_specular = value; - return 0; - } - } - } - } - - return PyObjectPlus::_setattr(attr, pyvalue); + py_setattro_up(PyObjectPlus); } KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)") { PyObject *material; - if (PyArg_ParseTuple(args, "O", &material)) + if (PyArg_ParseTuple(args, "O:setCustomMaterial", &material)) { if (m_pymaterial) { Py_DECREF(m_pymaterial); @@ -371,7 +261,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(mat KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rasty)") { PyObject *pyrasty, *pytface; - if (PyArg_ParseTuple(args, "O!O!", &PyCObject_Type, &pytface, &PyCObject_Type, &pyrasty)) + if (PyArg_ParseTuple(args, "O!O!:updateTexture", &PyCObject_Type, &pytface, &PyCObject_Type, &pyrasty)) { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty); @@ -387,7 +277,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") { PyObject *pytface; - if (PyArg_ParseTuple(args, "O!", &PyCObject_Type, &pytface)) + if (PyArg_ParseTuple(args, "O!:setTexture", &PyCObject_Type, &pytface)) { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); GPU_set_tpage(tface); @@ -400,7 +290,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") { PyObject *pyrasty, *pyCachingInfo; - if (PyArg_ParseTuple(args, "O!O!", &PyCObject_Type, &pyrasty, &PyCObject_Type, &pyCachingInfo)) + if (PyArg_ParseTuple(args, "O!O!:activate", &PyCObject_Type, &pyrasty, &PyCObject_Type, &pyCachingInfo)) { RAS_IRasterizer *rasty = static_cast<RAS_IRasterizer*>(PyCObject_AsVoidPtr(pyrasty)); TCachingInfo *cachingInfo = static_cast<TCachingInfo*>(PyCObject_AsVoidPtr(pyCachingInfo)); @@ -413,3 +303,69 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") return NULL; } + +PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + return PyString_FromString(self->m_texturename.ReadPtr()); +} + +PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + return PyString_FromString(self->m_materialname.ReadPtr()); +} + +/* this does not seem useful */ +PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + return PyCObject_FromVoidPtr(self->m_tface, NULL); +} + +PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + int bindcode= 0; + if (self->m_tface && self->m_tface->tpage) + bindcode= self->m_tface->tpage->bindcode; + + return PyInt_FromLong(bindcode); +} + + +PyObject* KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + return PyObjectFrom(self->m_diffuse); +} + +int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + MT_Vector3 vec; + + if (!PyVecTo(value, vec)) + return -1; + + self->m_diffuse= vec; + return 0; +} + +PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + return PyObjectFrom(self->m_specular); +} + +int KX_PolygonMaterial::pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v); + MT_Vector3 vec; + + if (!PyVecTo(value, vec)) + return -1; + + self->m_specular= vec; + return 0; +} diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index a3ef4ca51ef..9865a66e836 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -33,6 +33,7 @@ #include "RAS_MaterialBucket.h" #include "RAS_IRasterizer.h" +#include "DNA_ID.h" struct MTFace; struct Material; @@ -115,8 +116,20 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } + + static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + static PyObject* pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + static PyObject* pyattr_get_diffuse(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_specular(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); }; #endif // __KX_POLYGONMATERIAL_H__ diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index fb37eded450..2c65c184a9c 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -381,7 +381,7 @@ static PyObject* gPyGetVehicleConstraint(PyObject* self, if (vehicle) { KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment()); - return pyWrapper; + return pyWrapper->NewProxy(true); } } @@ -440,7 +440,7 @@ static PyObject* gPyCreateConstraint(PyObject* self, KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); - return wrap; + return wrap->NewProxy(true); } @@ -582,6 +582,7 @@ PyObject* initPythonConstraintBinding() d = PyModule_GetDict(m); ErrorObject = PyString_FromString("PhysicsConstraints.error"); PyDict_SetItemString(d, "error", ErrorObject); + Py_DECREF(ErrorObject); // XXXX Add constants here diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 92f18590a7e..0093a72808e 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -44,6 +44,7 @@ #include "ListValue.h" #include "KX_Python.h" +#include "KX_PyMath.h" bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) { @@ -74,6 +75,39 @@ bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) return false; } +bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix) +{ + MT_Matrix3x3 rot; + int size= PySequence_Size(pyval); + + if (size == 4) + { + MT_Quaternion qrot; + if (PyVecTo(pyval, qrot)) + { + rot.setRotation(qrot); + return true; + } + } + else if (size == 3) { + /* 3x3 matrix or euler */ + MT_Vector3 erot; + if (PyVecTo(pyval, erot)) + { + rot.setEuler(erot); + return true; + } + PyErr_Clear(); + + if (PyMatTo(pyval, rot)) + { + return true; + } + } + + PyErr_Format(PyExc_TypeError, "%s, could not set the orientation from a 3x3 matrix, quaternion or euler sequence", error_prefix); + return false; +} PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) { @@ -93,7 +127,7 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) PyList_SET_ITEM(sublist, 0, PyFloat_FromDouble(mat[i][0])); PyList_SET_ITEM(sublist, 1, PyFloat_FromDouble(mat[i][1])); PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][2])); - PyList_SET_ITEM(sublist, 2, PyFloat_FromDouble(mat[i][3])); + PyList_SET_ITEM(sublist, 3, PyFloat_FromDouble(mat[i][3])); PyList_SET_ITEM(list, i, sublist); } diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 39c9c358792..00f7c5cad93 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -92,18 +92,35 @@ bool PyMatTo(PyObject* pymat, T& mat) } /** - * Converts a python list to a MT class. + * Converts a python sequence to a MT class. */ template<class T> bool PyVecTo(PyObject* pyval, T& vec) { - if (PySequence_Check(pyval)) + + if(PyTuple_Check(pyval)) + { + unsigned int numitems = PyTuple_GET_SIZE(pyval); + if (numitems != Size(vec)) { + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", numitems, Size(vec)); + return false; + } + + for (unsigned int x = 0; x < numitems; x++) + vec[x] = PyFloat_AsDouble(PyTuple_GET_ITEM(pyval, x)); /* borrow ref */ + + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float"); + return false; + } + + return true; + } + else if (PySequence_Check(pyval)) { unsigned int numitems = PySequence_Size(pyval); if (numitems != Size(vec)) { - char err[128]; - sprintf(err, "error setting vector, %d args, should be %d", numitems, Size(vec)); - PyErr_SetString(PyExc_AttributeError, err); + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", numitems, Size(vec)); return false; } @@ -122,14 +139,14 @@ bool PyVecTo(PyObject* pyval, T& vec) return true; } else { - char err[128]; - sprintf(err, "not a sequence type, expected a sequence of numbers size %d", Size(vec)); - PyErr_SetString(PyExc_AttributeError, err); + PyErr_Format(PyExc_AttributeError, "not a sequence type, expected a sequence of numbers size %d", Size(vec)); } return false; } +bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix); + /** * Converts an MT_Matrix4x4 to a python object. */ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index d974d67bf33..ffcf7d7162e 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -48,32 +48,47 @@ #include "KX_KetsjiEngine.h" #include "KX_RadarSensor.h" +#include "KX_RaySensor.h" +#include "KX_SCA_DynamicActuator.h" #include "SCA_IInputDevice.h" #include "SCA_PropertySensor.h" #include "SCA_RandomActuator.h" +#include "SCA_KeyboardSensor.h" /* IsPrintable, ToCharacter */ #include "KX_ConstraintActuator.h" #include "KX_IpoActuator.h" #include "KX_SoundActuator.h" +#include "KX_StateActuator.h" #include "BL_ActionActuator.h" #include "RAS_IRasterizer.h" #include "RAS_ICanvas.h" #include "RAS_BucketManager.h" +#include "RAS_2DFilterManager.h" #include "MT_Vector3.h" #include "MT_Point3.h" #include "ListValue.h" #include "KX_Scene.h" #include "SND_DeviceManager.h" +#include "NG_NetworkScene.h" //Needed for sendMessage() + #include "BL_Shader.h" #include "KX_PyMath.h" -#include "PyObjectPlus.h" +#include "PyObjectPlus.h" + +//XXX +#if 0 + +#include "KX_PythonInitTypes.h" extern "C" { #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. + #include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ + #include "BGL.h" } +#endif #include "marshal.h" /* python header for loading/saving dicts */ @@ -91,7 +106,7 @@ extern "C" { #include "GPU_material.h" static void setSandbox(TPythonSecurityLevel level); - +static void clearGameModules(); // 'local' copy of canvas ptr, for window height/width python scripts static RAS_ICanvas* gp_Canvas = NULL; @@ -108,9 +123,9 @@ void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,cons /* Macro for building the keyboard translation */ //#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name)) -#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(name)) +#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name)); Py_DECREF(item) /* For the defines for types from logic bricks, we do stuff explicitly... */ -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, PyInt_FromLong(name2)) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name2)); Py_DECREF(item) // temporarily python stuff, will be put in another place later ! @@ -153,7 +168,7 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) char expanded[FILE_MAXDIR + FILE_MAXFILE]; char* filename; - if (!PyArg_ParseTuple(args,"s",&filename)) + if (!PyArg_ParseTuple(args,"s:ExpandPath",&filename)) return NULL; BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); @@ -161,6 +176,28 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) return PyString_FromString(expanded); } +static char gPySendMessage_doc[] = +"sendMessage(subject, [body, to, from])\n\ +sends a message in same manner as a message actuator\ +subject = Subject of the message\ +body = Message body\ +to = Name of object to send the message to\ +from = Name of object to sned the string from"; + +static PyObject* gPySendMessage(PyObject*, PyObject* args) +{ + char* subject; + char* body = (char *)""; + char* to = (char *)""; + char* from = (char *)""; + + if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to, &from)) + return NULL; + + gp_KetsjiScene->GetNetworkScene()->SendMessage(to, from, subject, body); + + Py_RETURN_NONE; +} static bool usedsp = false; @@ -237,7 +274,7 @@ static PyObject* gPyStopDSP(PyObject*, PyObject* args) static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) { float ticrate; - if (!PyArg_ParseTuple(args, "f", &ticrate)) + if (!PyArg_ParseTuple(args, "f:setLogicTicRate", &ticrate)) return NULL; KX_KetsjiEngine::SetTicRate(ticrate); @@ -252,7 +289,7 @@ static PyObject* gPyGetLogicTicRate(PyObject*) static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; - if (!PyArg_ParseTuple(args, "f", &ticrate)) + if (!PyArg_ParseTuple(args, "f:setPhysicsTicRate", &ticrate)) return NULL; PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); @@ -262,7 +299,7 @@ static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) { int debugMode; - if (!PyArg_ParseTuple(args, "i", &debugMode)) + if (!PyArg_ParseTuple(args, "i:setPhysicsDebug", &debugMode)) return NULL; PHY_GetActiveEnvironment()->setDebugMode(debugMode); @@ -290,7 +327,7 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) DIR *dp; struct dirent *dirp; - if (!PyArg_ParseTuple(args, "|s", &searchpath)) + if (!PyArg_ParseTuple(args, "|s:getBlendFileList", &searchpath)) return NULL; list = PyList_New(0); @@ -326,8 +363,7 @@ static STR_String gPyGetCurrentScene_doc = "Gets a reference to the current scene.\n"; static PyObject* gPyGetCurrentScene(PyObject* self) { - Py_INCREF(gp_KetsjiScene); - return (PyObject*) gp_KetsjiScene; + return gp_KetsjiScene->GetProxy(); } static STR_String gPyGetSceneList_doc = @@ -336,7 +372,6 @@ static STR_String gPyGetSceneList_doc = static PyObject* gPyGetSceneList(PyObject* self) { KX_KetsjiEngine* m_engine = KX_GetActiveEngine(); - //CListValue* list = new CListValue(); PyObject* list; KX_SceneList* scenes = m_engine->CurrentScenes(); int numScenes = scenes->size(); @@ -347,13 +382,10 @@ static PyObject* gPyGetSceneList(PyObject* self) for (i=0;i<numScenes;i++) { KX_Scene* scene = scenes->at(i); - //list->Add(scene); - PyList_SET_ITEM(list, i, scene); - Py_INCREF(scene); - + PyList_SET_ITEM(list, i, scene->GetProxy()); } - return (PyObject*)list; + return list; } static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) @@ -430,6 +462,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) static struct PyMethodDef game_methods[] = { {"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (PY_METHODCHAR)gPyExpandPath_doc}, + {"sendMessage", (PyCFunction)gPySendMessage, METH_VARARGS, (PY_METHODCHAR)gPySendMessage_doc}, {"getCurrentController", (PyCFunction) SCA_PythonController::sPyGetCurrentController, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::sPyGetCurrentController__doc__}, @@ -475,7 +508,7 @@ bool gUseVisibilityTemp = false; static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) { int visible; - if (!PyArg_ParseTuple(args,"i",&visible)) + if (!PyArg_ParseTuple(args,"i:enableVisibility",&visible)) return NULL; gUseVisibilityTemp = (visible != 0); @@ -487,7 +520,7 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) static PyObject* gPyShowMouse(PyObject*, PyObject* args) { int visible; - if (!PyArg_ParseTuple(args,"i",&visible)) + if (!PyArg_ParseTuple(args,"i:showMouse",&visible)) return NULL; if (visible) @@ -508,7 +541,7 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args) static PyObject* gPySetMousePosition(PyObject*, PyObject* args) { int x,y; - if (!PyArg_ParseTuple(args,"ii",&x,&y)) + if (!PyArg_ParseTuple(args,"ii:setMousePosition",&x,&y)) return NULL; if (gp_Canvas) @@ -520,11 +553,11 @@ static PyObject* gPySetMousePosition(PyObject*, PyObject* args) static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) { float sep; - if (!PyArg_ParseTuple(args, "f", &sep)) + if (!PyArg_ParseTuple(args, "f:setEyeSeparation", &sep)) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setEyeSeparation(float), Rasterizer not available"); return NULL; } @@ -533,10 +566,10 @@ static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*) +static PyObject* gPyGetEyeSeparation(PyObject*) { if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getEyeSeparation(), Rasterizer not available"); return NULL; } @@ -546,11 +579,11 @@ static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*) static PyObject* gPySetFocalLength(PyObject*, PyObject* args) { float focus; - if (!PyArg_ParseTuple(args, "f", &focus)) + if (!PyArg_ParseTuple(args, "f:setFocalLength", &focus)) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setFocalLength(float), Rasterizer not available"); return NULL; } @@ -562,7 +595,7 @@ static PyObject* gPySetFocalLength(PyObject*, PyObject* args) static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) { if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getFocalLength(), Rasterizer not available"); return NULL; } @@ -595,7 +628,7 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* value) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); return NULL; } gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); @@ -609,11 +642,11 @@ static PyObject* gPySetMistStart(PyObject*, PyObject* args) { float miststart; - if (!PyArg_ParseTuple(args,"f",&miststart)) + if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart)) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available"); return NULL; } @@ -628,11 +661,11 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) { float mistend; - if (!PyArg_ParseTuple(args,"f",&mistend)) + if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend)) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available"); return NULL; } @@ -650,7 +683,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available"); return NULL; } gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); @@ -664,7 +697,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) { char* filename; - if (!PyArg_ParseTuple(args,"s",&filename)) + if (!PyArg_ParseTuple(args,"s:makeScreenshot",&filename)) return NULL; if (gp_Canvas) @@ -678,11 +711,11 @@ static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) { float motionblurvalue; - if (!PyArg_ParseTuple(args,"f",&motionblurvalue)) + if (!PyArg_ParseTuple(args,"f:enableMotionBlur",&motionblurvalue)) return NULL; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.enableMotionBlur(float), Rasterizer not available"); return NULL; } @@ -694,7 +727,7 @@ static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args) { if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.disableMotionBlur(), Rasterizer not available"); return NULL; } @@ -728,13 +761,13 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*, char *setting; int enable, flag, fileflags; - if (!PyArg_ParseTuple(args,"si",&setting,&enable)) + if (!PyArg_ParseTuple(args,"si:setGLSLMaterialSetting",&setting,&enable)) return NULL; flag = getGLSLSettingFlag(setting); if (flag==-1) { - PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); + PyErr_SetString(PyExc_ValueError, "Rasterizer.setGLSLMaterialSetting(string): glsl setting is not known"); return NULL; } @@ -769,13 +802,13 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*, char *setting; int enabled = 0, flag; - if (!PyArg_ParseTuple(args,"s",&setting)) + if (!PyArg_ParseTuple(args,"s:getGLSLMaterialSetting",&setting)) return NULL; flag = getGLSLSettingFlag(setting); if (flag==-1) { - PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); + PyErr_SetString(PyExc_ValueError, "Rasterizer.getGLSLMaterialSetting(string): glsl setting is not known"); return NULL; } @@ -793,7 +826,7 @@ static PyObject* gPySetMaterialType(PyObject*, { int flag, type; - if (!PyArg_ParseTuple(args,"i",&type)) + if (!PyArg_ParseTuple(args,"i:setMaterialType",&type)) return NULL; if(type == KX_BLENDER_GLSL_MATERIAL) @@ -803,7 +836,7 @@ static PyObject* gPySetMaterialType(PyObject*, else if(type == KX_TEXFACE_MATERIAL) flag = 0; else { - PyErr_SetString(PyExc_ValueError, "material type is not known"); + PyErr_SetString(PyExc_ValueError, "Rasterizer.setMaterialType(int): material type is not known"); return NULL; } @@ -834,11 +867,11 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args) PyObject* ob_color; if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.drawLine(obFrom, obTo, color): Rasterizer not available"); return NULL; } - if (!PyArg_ParseTuple(args,"OOO",&ob_from,&ob_to,&ob_color)) + if (!PyArg_ParseTuple(args,"OOO:drawLine",&ob_from,&ob_to,&ob_color)) return NULL; MT_Vector3 from; @@ -879,7 +912,7 @@ static struct PyMethodDef rasterizer_methods[] = { {"setEyeSeparation", (PyCFunction) gPySetEyeSeparation, METH_VARARGS, "set the eye separation for stereo mode"}, - {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"}, + {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"}, {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, {"setMaterialMode",(PyCFunction) gPySetMaterialType, @@ -911,7 +944,8 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack { PyObject* m; PyObject* d; - + PyObject* item; /* temp PyObject* storage */ + gp_KetsjiEngine = engine; gp_KetsjiScene = scene; @@ -927,10 +961,12 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack // can be overwritten later for gameEngine instances that can load new blend files and re-initialize this module // for now its safe to make sure it exists for other areas such as the web plugin - PyDict_SetItemString(d, "globalDict", PyDict_New()); + + PyDict_SetItemString(d, "globalDict", item=PyDict_New()); Py_DECREF(item); ErrorObject = PyString_FromString("GameLogic.error"); PyDict_SetItemString(d, "error", ErrorObject); + Py_DECREF(ErrorObject); // XXXX Add constants here /* To use logic bricks, we need some sort of constants. Here, we associate */ @@ -963,6 +999,12 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIY); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIZ); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ); /* 4. Ipo actuator, simple part */ KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY, KX_IpoActuator::KX_ACT_IPO_PLAY); @@ -970,6 +1012,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_IPOACT_FLIPPER, KX_IpoActuator::KX_ACT_IPO_FLIPPER); KX_MACRO_addTypesToDict(d, KX_IPOACT_LOOPSTOP, KX_IpoActuator::KX_ACT_IPO_LOOPSTOP); KX_MACRO_addTypesToDict(d, KX_IPOACT_LOOPEND, KX_IpoActuator::KX_ACT_IPO_LOOPEND); + KX_MACRO_addTypesToDict(d, KX_IPOACT_FROM_PROP,KX_IpoActuator::KX_ACT_IPO_FROM_PROP); /* 5. Random distribution types */ KX_MACRO_addTypesToDict(d, KX_RANDOMACT_BOOL_CONST, SCA_RandomActuator::KX_RANDOMACT_BOOL_CONST); @@ -1069,6 +1112,66 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Y, KX_RadarSensor::KX_RADAR_AXIS_NEG_X); KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Z, KX_RadarSensor::KX_RADAR_AXIS_NEG_Z); + /* Ray Sensor */ + KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_POS_X, KX_RaySensor::KX_RAY_AXIS_POS_X); + KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_POS_Y, KX_RaySensor::KX_RAY_AXIS_POS_Y); + KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_POS_Z, KX_RaySensor::KX_RAY_AXIS_POS_Z); + KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_X, KX_RaySensor::KX_RAY_AXIS_NEG_Y); + KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Y, KX_RaySensor::KX_RAY_AXIS_NEG_X); + KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Z, KX_RaySensor::KX_RAY_AXIS_NEG_Z); + + /* Dynamic actuator */ + KX_MACRO_addTypesToDict(d, KX_DYN_RESTORE_DYNAMICS, KX_SCA_DynamicActuator::KX_DYN_RESTORE_DYNAMICS); + KX_MACRO_addTypesToDict(d, KX_DYN_DISABLE_DYNAMICS, KX_SCA_DynamicActuator::KX_DYN_DISABLE_DYNAMICS); + KX_MACRO_addTypesToDict(d, KX_DYN_ENABLE_RIGID_BODY, KX_SCA_DynamicActuator::KX_DYN_ENABLE_RIGID_BODY); + KX_MACRO_addTypesToDict(d, KX_DYN_DISABLE_RIGID_BODY, KX_SCA_DynamicActuator::KX_DYN_DISABLE_RIGID_BODY); + KX_MACRO_addTypesToDict(d, KX_DYN_SET_MASS, KX_SCA_DynamicActuator::KX_DYN_SET_MASS); + + /* Input & Mouse Sensor */ + KX_MACRO_addTypesToDict(d, KX_INPUT_NONE, SCA_InputEvent::KX_NO_INPUTSTATUS); + KX_MACRO_addTypesToDict(d, KX_INPUT_JUST_ACTIVATED, SCA_InputEvent::KX_JUSTACTIVATED); + KX_MACRO_addTypesToDict(d, KX_INPUT_ACTIVE, SCA_InputEvent::KX_ACTIVE); + KX_MACRO_addTypesToDict(d, KX_INPUT_JUST_RELEASED, SCA_InputEvent::KX_JUSTRELEASED); + + KX_MACRO_addTypesToDict(d, KX_MOUSE_BUT_LEFT, SCA_IInputDevice::KX_LEFTMOUSE); + KX_MACRO_addTypesToDict(d, KX_MOUSE_BUT_MIDDLE, SCA_IInputDevice::KX_MIDDLEMOUSE); + KX_MACRO_addTypesToDict(d, KX_MOUSE_BUT_RIGHT, SCA_IInputDevice::KX_RIGHTMOUSE); + + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_ENABLED, RAS_2DFilterManager::RAS_2DFILTER_ENABLED); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_DISABLED, RAS_2DFilterManager::RAS_2DFILTER_DISABLED); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_NOFILTER, RAS_2DFilterManager::RAS_2DFILTER_NOFILTER); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_MOTIONBLUR, RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_BLUR, RAS_2DFilterManager::RAS_2DFILTER_BLUR); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_SHARPEN, RAS_2DFilterManager::RAS_2DFILTER_SHARPEN); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_DILATION, RAS_2DFilterManager::RAS_2DFILTER_DILATION); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_EROSION, RAS_2DFilterManager::RAS_2DFILTER_EROSION); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_LAPLACIAN, RAS_2DFilterManager::RAS_2DFILTER_LAPLACIAN); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_SOBEL, RAS_2DFilterManager::RAS_2DFILTER_SOBEL); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_PREWITT, RAS_2DFilterManager::RAS_2DFILTER_PREWITT); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_GRAYSCALE, RAS_2DFilterManager::RAS_2DFILTER_GRAYSCALE); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_SEPIA, RAS_2DFilterManager::RAS_2DFILTER_SEPIA); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_INVERT, RAS_2DFilterManager::RAS_2DFILTER_INVERT); + KX_MACRO_addTypesToDict(d, RAS_2DFILTER_CUSTOMFILTER, RAS_2DFilterManager::RAS_2DFILTER_CUSTOMFILTER); + + KX_MACRO_addTypesToDict(d, KX_SOUNDACT_PLAYSTOP, KX_SoundActuator::KX_SOUNDACT_PLAYSTOP); + KX_MACRO_addTypesToDict(d, KX_SOUNDACT_PLAYEND, KX_SoundActuator::KX_SOUNDACT_PLAYEND); + KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPSTOP, KX_SoundActuator::KX_SOUNDACT_LOOPSTOP); + KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPEND, KX_SoundActuator:: KX_SOUNDACT_LOOPEND); + KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL); + KX_MACRO_addTypesToDict(d, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP, KX_SoundActuator::KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP); + + KX_MACRO_addTypesToDict(d, KX_STATE_OP_CPY, KX_StateActuator::OP_CPY); + KX_MACRO_addTypesToDict(d, KX_STATE_OP_SET, KX_StateActuator::OP_SET); + KX_MACRO_addTypesToDict(d, KX_STATE_OP_CLR, KX_StateActuator::OP_CLR); + KX_MACRO_addTypesToDict(d, KX_STATE_OP_NEG, KX_StateActuator::OP_NEG); + + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_NORMAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_NORMAL); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_MATERIAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_PERMANENT, KX_ConstraintActuator::KX_ACT_CONSTRAINT_PERMANENT); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DISTANCE, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DISTANCE); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL); + KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH); + // Check for errors if (PyErr_Occurred()) { @@ -1087,11 +1190,6 @@ PyObject *KXpy_open(PyObject *self, PyObject *args) { return NULL; } -PyObject *KXpy_reload(PyObject *self, PyObject *args) { - PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function."); - return NULL; -} - PyObject *KXpy_file(PyObject *self, PyObject *args) { PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function."); return NULL; @@ -1110,6 +1208,7 @@ PyObject *KXpy_compile(PyObject *self, PyObject *args) { PyObject *KXpy_import(PyObject *self, PyObject *args) { char *name; + int found; PyObject *globals = NULL; PyObject *locals = NULL; PyObject *fromlist = NULL; @@ -1139,14 +1238,46 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) /* quick hack for GamePython modules TODO: register builtin modules properly by ExtendInittab */ if (!strcmp(name, "GameLogic") || !strcmp(name, "GameKeys") || !strcmp(name, "PhysicsConstraints") || - !strcmp(name, "Rasterizer") || !strcmp(name, "Mathutils")) { + !strcmp(name, "Rasterizer") || !strcmp(name, "Mathutils") || !strcmp(name, "BGL")) { return PyImport_ImportModuleEx(name, globals, locals, fromlist); } - - PyErr_Format(PyExc_ImportError, - "Import of external Module %.20s not allowed.", name); + + /* Import blender texts as python modules */ + /* XXX 2.5 + * m= bpy_text_import(name, &found); + if (m) + return m; */ + + if(found==0) /* if its found but could not import then it has its own error */ + PyErr_Format(PyExc_ImportError, "Import of external Module %.20s not allowed.", name); + + return NULL; + +} + +PyObject *KXpy_reload(PyObject *self, PyObject *args) { + + /* Used to be sandboxed, bettet to allow importing of internal text only */ +#if 0 + PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function."); return NULL; +#endif + int found; + PyObject *module = NULL; + PyObject *newmodule = NULL; + /* check for a module arg */ + if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) ) + return NULL; + + /* XXX 2.5 newmodule= bpy_text_reimport( module, &found ); + if (newmodule) + return newmodule; */ + + if (found==0) /* if its found but could not import then it has its own error */ + PyErr_SetString(PyExc_ImportError, "reload(module): failed to reload from blenders internal text"); + + return newmodule; } /* override python file type functions */ @@ -1181,18 +1312,18 @@ void setSandbox(TPythonSecurityLevel level) { PyObject *m = PyImport_AddModule("__builtin__"); PyObject *d = PyModule_GetDict(m); - + PyObject *item; switch (level) { case psl_Highest: //if (!g_security) { //g_oldopen = PyDict_GetItemString(d, "open"); // functions we cant trust - PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL)); - PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL)); - PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL)); - PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL)); - PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL)); + PyDict_SetItemString(d, "open", item=PyCFunction_New(meth_open, NULL)); Py_DECREF(item); + PyDict_SetItemString(d, "reload", item=PyCFunction_New(meth_reload, NULL)); Py_DECREF(item); + PyDict_SetItemString(d, "file", item=PyCFunction_New(meth_file, NULL)); Py_DECREF(item); + PyDict_SetItemString(d, "execfile", item=PyCFunction_New(meth_execfile, NULL)); Py_DECREF(item); + PyDict_SetItemString(d, "compile", item=PyCFunction_New(meth_compile, NULL)); Py_DECREF(item); // our own import PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL)); @@ -1221,6 +1352,9 @@ void setSandbox(TPythonSecurityLevel level) } */ default: + /* Allow importing internal text, from bpy_internal_import.py */ + /* XXX 2.5 PyDict_SetItemString(d, "reload", item=PyCFunction_New(bpy_reload_meth, NULL)); Py_DECREF(item); */ + /* XXX 2.5 PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL)); Py_DECREF(item); */ break; } } @@ -1228,31 +1362,39 @@ void setSandbox(TPythonSecurityLevel level) /** * Python is not initialised. */ -PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level) +PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv) { STR_String pname = progname; Py_SetProgramName(pname.Ptr()); Py_NoSiteFlag=1; Py_FrozenFlag=1; Py_Initialize(); - + + if(argv) /* browser plugins dont currently set this */ + PySys_SetArgv(argc, argv); + //importBlenderModules() setSandbox(level); - + /* XXX 2.5 initPyTypes(); */ + + /* XXX 2.5 bpy_import_main_set(maggie); */ + PyObject* moduleobj = PyImport_AddModule("__main__"); return PyModule_GetDict(moduleobj); } void exitGamePlayerPythonScripting() { + //clearGameModules(); // were closing python anyway Py_Finalize(); + /* XXX 2.5 bpy_import_main_set(NULL); */ } /** * Python is already initialized. */ -PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level) +PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie) { STR_String pname = progname; Py_SetProgramName(pname.Ptr()); @@ -1260,15 +1402,54 @@ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLev Py_FrozenFlag=1; setSandbox(level); + /* XXX 2.5 initPyTypes(); */ + + /* XXX 2.5 bpy_import_main_set(maggie); */ + + /* run this to clear game modules and user modules which + * may contain references to in game data */ + clearGameModules(); PyObject* moduleobj = PyImport_AddModule("__main__"); return PyModule_GetDict(moduleobj); } +static void clearModule(PyObject *modules, const char *name) +{ + PyObject *mod= PyDict_GetItemString(modules, name); + + if (mod==NULL) + return; + + PyDict_Clear(PyModule_GetDict(mod)); /* incase there are any circular refs */ + PyDict_DelItemString(modules, name); +} +static void clearGameModules() +{ + /* Note, user modules could still reference these modules + * but since the dict's are cleared their members wont be accessible */ + + PyObject *modules= PySys_GetObject((char *)"modules"); + clearModule(modules, "Expression"); + clearModule(modules, "CValue"); + clearModule(modules, "PhysicsConstraints"); + clearModule(modules, "GameLogic"); + clearModule(modules, "Rasterizer"); + clearModule(modules, "GameKeys"); + clearModule(modules, "VideoTexture"); + clearModule(modules, "Mathutils"); + clearModule(modules, "BGL"); + PyErr_Clear(); // incase some of these were alredy removed. + + /* clear user defined modules */ + /* XXX 2.5 bpy_text_clear_modules(); */ +} void exitGamePythonScripting() { + clearGameModules(); + /* XXX 2.5 bpy_import_main_set(NULL); */ } @@ -1281,6 +1462,7 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) PyObject* m; PyObject* d; + PyObject* item; // Create the module and add the functions m = Py_InitModule4("Rasterizer", rasterizer_methods, @@ -1291,6 +1473,7 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) d = PyModule_GetDict(m); ErrorObject = PyString_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); + Py_DECREF(ErrorObject); /* needed for get/setMaterialType */ KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); @@ -1319,7 +1502,7 @@ static char GameKeys_module_documentation[] = ; static char gPyEventToString_doc[] = -"Take a valid event from the GameKeys module or Keyboard Sensor and return a name" +"EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name" ; static PyObject* gPyEventToString(PyObject*, PyObject* value) @@ -1342,13 +1525,35 @@ static PyObject* gPyEventToString(PyObject*, PyObject* value) PyErr_Clear(); // incase there was an error clearing Py_DECREF(mod); - if (!ret) PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event"); + if (!ret) PyErr_SetString(PyExc_ValueError, "GameKeys.EventToString(int): expected a valid int keyboard event"); else Py_INCREF(ret); return ret; } +static char gPyEventToCharacter_doc[] = +"EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character" +; + +static PyObject* gPyEventToCharacter(PyObject*, PyObject* args) +{ + int event, shift; + if (!PyArg_ParseTuple(args,"ii:EventToCharacter", &event, &shift)) + return NULL; + + if(IsPrintable(event)) { + char ch[2] = {'\0', '\0'}; + ch[0] = ToCharacter(event, (bool)shift); + return PyString_FromString(ch); + } + else { + return PyString_FromString(""); + } +} + + static struct PyMethodDef gamekeys_methods[] = { + {"EventToCharacter", (PyCFunction)gPyEventToCharacter, METH_VARARGS, (PY_METHODCHAR)gPyEventToCharacter_doc}, {"EventToString", (PyCFunction)gPyEventToString, METH_O, (PY_METHODCHAR)gPyEventToString_doc}, { NULL, (PyCFunction) NULL, 0, NULL } }; @@ -1359,6 +1564,7 @@ PyObject* initGameKeys() { PyObject* m; PyObject* d; + PyObject* item; // Create the module and add the functions m = Py_InitModule4("GameKeys", gamekeys_methods, @@ -1483,7 +1689,6 @@ PyObject* initGameKeys() KX_MACRO_addTypesToDict(d, PAGEDOWNKEY, SCA_IInputDevice::KX_PAGEDOWNKEY); KX_MACRO_addTypesToDict(d, ENDKEY, SCA_IInputDevice::KX_ENDKEY); - // Check for errors if (PyErr_Occurred()) { @@ -1495,7 +1700,12 @@ PyObject* initGameKeys() PyObject* initMathutils() { - return Mathutils_Init("Mathutils"); // Use as a top level module in BGE + return NULL; //XXX Mathutils_Init("Mathutils"); // Use as a top level module in BGE +} + +PyObject* initBGL() +{ + return NULL; // XXX 2.5 BGL_Init("BGL"); // Use as a top level module in BGE } void KX_SetActiveScene(class KX_Scene* scene) diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 57ee0be9400..11360197b95 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -43,11 +43,12 @@ extern bool gUseVisibilityTemp; PyObject* initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene); PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); -PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level); +PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie, int argc, char** argv); PyObject* initMathutils(); +PyObject* initBGL(); PyObject* initVideoTexture(void); void exitGamePlayerPythonScripting(); -PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); +PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie); void exitGamePythonScripting(); void setGamePythonPath(char *path); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp new file mode 100644 index 00000000000..dcd11b551a1 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -0,0 +1,233 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + + + +#ifndef _adr_py_init_types_h_ // only process once, +#define _adr_py_init_types_h_ // even if multiply included + +/* Only for Class::Parents */ +#include "BL_BlenderShader.h" +#include "BL_ShapeActionActuator.h" +#include "KX_BlenderMaterial.h" +#include "KX_CDActuator.h" +#include "KX_CameraActuator.h" +#include "KX_ConstraintActuator.h" +#include "KX_ConstraintWrapper.h" +#include "KX_GameActuator.h" +#include "KX_Light.h" +#include "KX_MeshProxy.h" +#include "KX_MouseFocusSensor.h" +#include "KX_NetworkMessageActuator.h" +#include "KX_NetworkMessageSensor.h" +#include "KX_ObjectActuator.h" +#include "KX_ParentActuator.h" +#include "KX_PhysicsObjectWrapper.h" +#include "KX_PolyProxy.h" +#include "KX_PolygonMaterial.h" +#include "KX_SCA_AddObjectActuator.h" +#include "KX_SCA_EndObjectActuator.h" +#include "KX_SCA_ReplaceMeshActuator.h" +#include "KX_SceneActuator.h" +#include "KX_StateActuator.h" +#include "KX_TrackToActuator.h" +#include "KX_VehicleWrapper.h" +#include "KX_VertexProxy.h" +#include "SCA_2DFilterActuator.h" +#include "SCA_ANDController.h" +#include "SCA_ActuatorSensor.h" +#include "SCA_AlwaysSensor.h" +#include "SCA_DelaySensor.h" +#include "SCA_JoystickSensor.h" +#include "SCA_KeyboardSensor.h" +#include "SCA_MouseSensor.h" +#include "SCA_NANDController.h" +#include "SCA_NORController.h" +#include "SCA_ORController.h" +#include "SCA_RandomSensor.h" +#include "SCA_XNORController.h" +#include "SCA_XORController.h" +#include "KX_IpoActuator.h" +#include "KX_NearSensor.h" +#include "KX_RadarSensor.h" +#include "KX_RaySensor.h" +#include "KX_SCA_DynamicActuator.h" +#include "KX_SoundActuator.h" +#include "KX_TouchSensor.h" +#include "KX_VisibilityActuator.h" +#include "SCA_PropertySensor.h" +#include "SCA_PythonController.h" +#include "SCA_RandomActuator.h" + + +void initPyObjectPlusType(PyTypeObject **parents) +{ + int i; + + for (i=0; parents[i]; i++) { + if(PyType_Ready(parents[i]) < 0) { + /* This is very very unlikely */ + printf("Error, pytype could not initialize, Blender may crash \"%s\"\n", parents[i]->tp_name); + return; + } + +#if 0 + PyObject_Print(reinterpret_cast<PyObject *>parents[i], stderr, 0); + fprintf(stderr, "\n"); + PyObject_Print(parents[i]->tp_dict, stderr, 0); + fprintf(stderr, "\n\n"); +#endif + + } + + PyObject *dict= NULL; + + while(i) { + i--; + + if (dict) { + PyDict_Update(parents[i]->tp_dict, dict); + } + dict= parents[i]->tp_dict; + +#if 1 + PyObject_Print(reinterpret_cast<PyObject *>(parents[i]), stderr, 0); + fprintf(stderr, "\n"); + PyObject_Print(parents[i]->tp_dict, stderr, 0); + fprintf(stderr, "\n\n"); +#endif + + } +} + + + + +static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes) +{ + PyAttributeDef *attr; + PyObject *item; + + PyType_Ready(tp); + PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast<PyObject *>(tp)); + + /* store attr defs in the tp_dict for to avoid string lookups */ + for(attr= attributes; attr->m_name; attr++) { + item= PyCObject_FromVoidPtr(attr, NULL); + PyDict_SetItemString(tp->tp_dict, attr->m_name, item); + Py_DECREF(item); + } + +} + + +#define PyType_Ready_Attr(d, n) PyType_Ready_ADD(d, &n::Type, n::Attributes) + +void initPyTypes(void) +{ + +/* + initPyObjectPlusType(BL_ActionActuator::Parents); + ..... +*/ + + /* For now just do PyType_Ready */ + PyObject *mod= PyModule_New("GameTypes"); + PyObject *dict= PyModule_GetDict(mod); + PyDict_SetItemString(PySys_GetObject((char *)"modules"), (char *)"GameTypes", mod); + Py_DECREF(mod); + + PyType_Ready_Attr(dict, BL_ActionActuator); + PyType_Ready_Attr(dict, BL_Shader); + PyType_Ready_Attr(dict, BL_ShapeActionActuator); + PyType_Ready_Attr(dict, CListValue); + PyType_Ready_Attr(dict, CValue); + PyType_Ready_Attr(dict, KX_BlenderMaterial); + PyType_Ready_Attr(dict, KX_CDActuator); + PyType_Ready_Attr(dict, KX_Camera); + PyType_Ready_Attr(dict, KX_CameraActuator); + PyType_Ready_Attr(dict, KX_ConstraintActuator); + PyType_Ready_Attr(dict, KX_ConstraintWrapper); + PyType_Ready_Attr(dict, KX_GameActuator); + PyType_Ready_Attr(dict, KX_GameObject); + PyType_Ready_Attr(dict, KX_IpoActuator); + PyType_Ready_Attr(dict, KX_LightObject); + PyType_Ready_Attr(dict, KX_MeshProxy); + PyType_Ready_Attr(dict, KX_MouseFocusSensor); + PyType_Ready_Attr(dict, KX_NearSensor); + PyType_Ready_Attr(dict, KX_NetworkMessageActuator); + PyType_Ready_Attr(dict, KX_NetworkMessageSensor); + PyType_Ready_Attr(dict, KX_ObjectActuator); + PyType_Ready_Attr(dict, KX_ParentActuator); + PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper); + PyType_Ready_Attr(dict, KX_PolyProxy); + PyType_Ready_Attr(dict, KX_PolygonMaterial); + PyType_Ready_Attr(dict, KX_RadarSensor); + PyType_Ready_Attr(dict, KX_RaySensor); + PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator); + PyType_Ready_Attr(dict, KX_SCA_DynamicActuator); + PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator); + PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator); + PyType_Ready_Attr(dict, KX_Scene); + PyType_Ready_Attr(dict, KX_SceneActuator); + PyType_Ready_Attr(dict, KX_SoundActuator); + PyType_Ready_Attr(dict, KX_StateActuator); + PyType_Ready_Attr(dict, KX_TouchSensor); + PyType_Ready_Attr(dict, KX_TrackToActuator); + PyType_Ready_Attr(dict, KX_VehicleWrapper); + PyType_Ready_Attr(dict, KX_VertexProxy); + PyType_Ready_Attr(dict, KX_VisibilityActuator); + PyType_Ready_Attr(dict, PyObjectPlus); + PyType_Ready_Attr(dict, SCA_2DFilterActuator); + PyType_Ready_Attr(dict, SCA_ANDController); + PyType_Ready_Attr(dict, SCA_ActuatorSensor); + PyType_Ready_Attr(dict, SCA_AlwaysSensor); + PyType_Ready_Attr(dict, SCA_DelaySensor); + PyType_Ready_Attr(dict, SCA_ILogicBrick); + PyType_Ready_Attr(dict, SCA_IObject); + PyType_Ready_Attr(dict, SCA_ISensor); + PyType_Ready_Attr(dict, SCA_JoystickSensor); + PyType_Ready_Attr(dict, SCA_KeyboardSensor); + PyType_Ready_Attr(dict, SCA_MouseSensor); + PyType_Ready_Attr(dict, SCA_NANDController); + PyType_Ready_Attr(dict, SCA_NORController); + PyType_Ready_Attr(dict, SCA_ORController); + PyType_Ready_Attr(dict, SCA_PropertyActuator); + PyType_Ready_Attr(dict, SCA_PropertySensor); + PyType_Ready_Attr(dict, SCA_PythonController); + PyType_Ready_Attr(dict, SCA_RandomActuator); + PyType_Ready_Attr(dict, SCA_RandomSensor); + PyType_Ready_Attr(dict, SCA_XNORController); + PyType_Ready_Attr(dict, SCA_XORController); + + + +} + +#endif
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h new file mode 100644 index 00000000000..6da79be9301 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _adr_py_init_types_h_ // only process once, +#define _adr_py_init_types_h_ // even if multiply included + +void initPyTypes(void); + +#endif diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index fa8998cd81d..8277e7ef19c 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -100,8 +100,9 @@ CValue* KX_RadarSensor::GetReplica() //>m_sumoObj = new SM_Object(DT_NewCone(m_coneradius, m_coneheight),NULL,NULL,NULL); //replica->m_sumoObj->setMargin(m_Margin); //replica->m_sumoObj->setClientObject(replica->m_client_info); - - ((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL); + //Wrong: see KX_TouchSensor + //bool parentUpdated = false; + //((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL,parentUpdated); replica->SynchronizeTransform(); return replica; @@ -206,7 +207,7 @@ const char KX_RadarSensor::GetConeOrigin_doc[] = "getConeOrigin()\n" "\tReturns the origin of the cone with which to test. The origin\n" "\tis in the middle of the cone."; -PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) { +PyObject* KX_RadarSensor::PyGetConeOrigin() { ShowDeprecationWarning("getConeOrigin()", "the coneOrigin property"); PyObject *retVal = PyList_New(3); @@ -222,7 +223,7 @@ PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self) { const char KX_RadarSensor::GetConeTarget_doc[] = "getConeTarget()\n" "\tReturns the center of the bottom face of the cone with which to test.\n"; -PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) { +PyObject* KX_RadarSensor::PyGetConeTarget() { ShowDeprecationWarning("getConeTarget()", "the coneTarget property"); PyObject *retVal = PyList_New(3); @@ -238,7 +239,7 @@ PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self) { const char KX_RadarSensor::GetConeHeight_doc[] = "getConeHeight()\n" "\tReturns the height of the cone with which to test.\n"; -PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) { +PyObject* KX_RadarSensor::PyGetConeHeight() { ShowDeprecationWarning("getConeHeight()", "the distance property"); @@ -250,22 +251,22 @@ PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self) { /* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ PyTypeObject KX_RadarSensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_RadarSensor", - sizeof(KX_RadarSensor), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_RadarSensor::Parents[] = { @@ -298,20 +299,12 @@ PyAttributeDef KX_RadarSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* KX_RadarSensor::_getattr(const char *attr) +PyObject* KX_RadarSensor::py_getattro(PyObject *attr) { - PyObject* object = _getattr_self(Attributes, this, attr); - if (object != NULL) - return object; - - _getattr_up(KX_NearSensor); + py_getattro_up(KX_NearSensor); } -int KX_RadarSensor::_setattr(const char *attr, PyObject* value) +int KX_RadarSensor::py_setattro(PyObject *attr, PyObject* value) { - int ret = _setattr_self(Attributes, this, attr, value); - if (ret >= 0) - return ret; - - return KX_NearSensor::_setattr(attr, value); + py_setattro_up(KX_NearSensor); } diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index 6dfe0c42f5d..c3a941696ce 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -89,8 +89,8 @@ public: KX_RADAR_AXIS_NEG_Z }; - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject* value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); //Deprecated -----> KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeOrigin); diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp index 974d4b992a6..8c7612bf663 100644 --- a/source/gameengine/Ketsji/KX_RayCast.cpp +++ b/source/gameengine/Ketsji/KX_RayCast.cpp @@ -56,12 +56,15 @@ void KX_RayCast::reportHit(PHY_RayCastResult* result) bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback) { + if(physics_environment==NULL) return false; /* prevents crashing in some cases */ + // Loops over all physics objects between frompoint and topoint, // calling callback.RayHit for each one. // // callback.RayHit should return true to stop looking, or false to continue. // // returns true if an object was found, false if not. + MT_Point3 frompoint(_frompoint); const MT_Vector3 todir( (topoint - frompoint).safe_normalized() ); MT_Point3 prevpoint(_frompoint+todir*(-1.f)); diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index ce12b983147..06c04dbf10d 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -136,8 +136,13 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void { m_rayHit = true; m_hitObject = hitKXObj; - m_hitPosition = result->m_hitPoint; - m_hitNormal = result->m_hitNormal; + m_hitPosition[0] = result->m_hitPoint[0]; + m_hitPosition[1] = result->m_hitPoint[1]; + m_hitPosition[2] = result->m_hitPoint[2]; + + m_hitNormal[0] = result->m_hitNormal[0]; + m_hitNormal[1] = result->m_hitNormal[1]; + m_hitNormal[2] = result->m_hitNormal[2]; } // no multi-hit search yet @@ -180,8 +185,13 @@ bool KX_RaySensor::Evaluate(CValue* event) bool reset = m_reset && m_level; m_rayHit = false; m_hitObject = NULL; - m_hitPosition.setValue(0,0,0); - m_hitNormal.setValue(1,0,0); + m_hitPosition[0] = 0; + m_hitPosition[1] = 0; + m_hitPosition[2] = 0; + + m_hitNormal[0] = 1; + m_hitNormal[1] = 0; + m_hitNormal[2] = 0; KX_GameObject* obj = (KX_GameObject*)GetParent(); MT_Point3 frompoint = obj->NodeGetWorldPosition(); @@ -236,7 +246,9 @@ bool KX_RaySensor::Evaluate(CValue* event) } } todir.normalize(); - m_rayDirection = todir; + m_rayDirection[0] = todir[0]; + m_rayDirection[1] = todir[1]; + m_rayDirection[2] = todir[2]; MT_Point3 topoint = frompoint + (m_distance) * todir; PHY_IPhysicsEnvironment* pe = m_scene->GetPhysicsEnvironment(); @@ -309,22 +321,23 @@ bool KX_RaySensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_RaySensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_RaySensor", - sizeof(KX_RaySensor), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods + }; PyParentObject KX_RaySensor::Parents[] = { @@ -336,25 +349,47 @@ PyParentObject KX_RaySensor::Parents[] = { }; PyMethodDef KX_RaySensor::Methods[] = { + // Deprecated -----> {"getHitObject",(PyCFunction) KX_RaySensor::sPyGetHitObject,METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc}, {"getHitPosition",(PyCFunction) KX_RaySensor::sPyGetHitPosition,METH_NOARGS, (PY_METHODCHAR)GetHitPosition_doc}, {"getHitNormal",(PyCFunction) KX_RaySensor::sPyGetHitNormal,METH_NOARGS, (PY_METHODCHAR)GetHitNormal_doc}, {"getRayDirection",(PyCFunction) KX_RaySensor::sPyGetRayDirection,METH_NOARGS, (PY_METHODCHAR)GetRayDirection_doc}, + // <----- {NULL,NULL} //Sentinel }; PyAttributeDef KX_RaySensor::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("useMaterial", KX_RaySensor, m_bFindMaterial), + KX_PYATTRIBUTE_BOOL_RW("useXRay", KX_RaySensor, m_bXRay), + KX_PYATTRIBUTE_FLOAT_RW("range", 0, 10000, KX_RaySensor, m_distance), + KX_PYATTRIBUTE_STRING_RW("property", 0, 100, false, KX_RaySensor, m_propertyname), + KX_PYATTRIBUTE_INT_RW("axis", 0, 5, true, KX_RaySensor, m_axis), + KX_PYATTRIBUTE_FLOAT_ARRAY_RO("hitPosition", KX_RaySensor, m_hitPosition, 3), + KX_PYATTRIBUTE_FLOAT_ARRAY_RO("rayDirection", KX_RaySensor, m_rayDirection, 3), + KX_PYATTRIBUTE_FLOAT_ARRAY_RO("hitNormal", KX_RaySensor, m_hitNormal, 3), + KX_PYATTRIBUTE_RO_FUNCTION("hitObject", KX_RaySensor, pyattr_get_hitobject), { NULL } //Sentinel }; +PyObject* KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_RaySensor* self = static_cast<KX_RaySensor*>(self_v); + if (self->m_hitObject) + return self->m_hitObject->GetProxy(); + + Py_RETURN_NONE; +} + +// Deprecated -----> const char KX_RaySensor::GetHitObject_doc[] = "getHitObject()\n" "\tReturns the name of the object that was hit by this ray.\n"; -PyObject* KX_RaySensor::PyGetHitObject(PyObject* self) +PyObject* KX_RaySensor::PyGetHitObject() { + ShowDeprecationWarning("getHitObject()", "the hitObject property"); if (m_hitObject) { - return m_hitObject->AddRef(); + return m_hitObject->GetProxy(); } Py_RETURN_NONE; } @@ -363,29 +398,59 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self) const char KX_RaySensor::GetHitPosition_doc[] = "getHitPosition()\n" "\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n"; -PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self) +PyObject* KX_RaySensor::PyGetHitPosition() { - return PyObjectFrom(m_hitPosition); + ShowDeprecationWarning("getHitPosition()", "the hitPosition property"); + + PyObject *retVal = PyList_New(3); + + PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_hitPosition[0])); + PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_hitPosition[1])); + PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_hitPosition[2])); + + return retVal; } const char KX_RaySensor::GetRayDirection_doc[] = "getRayDirection()\n" "\tReturns the direction from the ray (in worldcoordinates) .\n"; -PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self) +PyObject* KX_RaySensor::PyGetRayDirection() { - return PyObjectFrom(m_rayDirection); + ShowDeprecationWarning("getRayDirection()", "the rayDirection property"); + + PyObject *retVal = PyList_New(3); + + PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_rayDirection[0])); + PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_rayDirection[1])); + PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_rayDirection[2])); + + return retVal; } const char KX_RaySensor::GetHitNormal_doc[] = "getHitNormal()\n" "\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n"; -PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self) +PyObject* KX_RaySensor::PyGetHitNormal() { - return PyObjectFrom(m_hitNormal); + ShowDeprecationWarning("getHitNormal()", "the hitNormal property"); + + PyObject *retVal = PyList_New(3); + + PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_hitNormal[0])); + PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_hitNormal[1])); + PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_hitNormal[2])); + + return retVal; } -PyObject* KX_RaySensor::_getattr(const char *attr) { - _getattr_up(SCA_ISensor); +PyObject* KX_RaySensor::py_getattro(PyObject *attr) { + py_getattro_up(SCA_ISensor); } + +int KX_RaySensor::py_setattro(PyObject *attr, PyObject *value) { + py_setattro_up(SCA_ISensor); +} + +// <----- Deprecated diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 09d8bc1369a..a5d7d15c60c 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -44,15 +44,15 @@ class KX_RaySensor : public SCA_ISensor STR_String m_propertyname; bool m_bFindMaterial; bool m_bXRay; - double m_distance; + float m_distance; class KX_Scene* m_scene; bool m_bTriggered; int m_axis; bool m_rayHit; - MT_Point3 m_hitPosition; + float m_hitPosition[3]; SCA_IObject* m_hitObject; - MT_Vector3 m_hitNormal; - MT_Vector3 m_rayDirection; + float m_hitNormal[3]; + float m_rayDirection[3]; public: KX_RaySensor(class SCA_EventManager* eventmgr, @@ -73,13 +73,31 @@ public: bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); bool NeedRayCast(KX_ClientObjectInfo* client); + + + //Python Interface + enum RayAxis { + KX_RAY_AXIS_POS_Y = 0, + KX_RAY_AXIS_POS_X, + KX_RAY_AXIS_POS_Z, + KX_RAY_AXIS_NEG_X, + KX_RAY_AXIS_NEG_Y, + KX_RAY_AXIS_NEG_Z + }; + + + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + // Deprecated -----> KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitObject); KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitPosition); KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitNormal); KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetRayDirection); + // <----- - virtual PyObject* _getattr(const char *attr); + /* Attributes */ + static PyObject* pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 68b704f4889..c45d89a2815 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -38,7 +38,6 @@ #include "SCA_IScene.h" #include "KX_GameObject.h" #include "KX_IPhysicsController.h" - #include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H @@ -53,9 +52,9 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, SCA_IObject *original, int time, SCA_IScene* scene, - const MT_Vector3& linvel, + const float *linvel, bool linv_local, - const MT_Vector3& angvel, + const float *angvel, bool angv_local, PyTypeObject* T) : @@ -63,12 +62,16 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, m_OriginalObject(original), m_scene(scene), - m_linear_velocity(linvel), m_localLinvFlag(linv_local), - - m_angular_velocity(angvel), m_localAngvFlag(angv_local) { + m_linear_velocity[0] = linvel[0]; + m_linear_velocity[1] = linvel[1]; + m_linear_velocity[2] = linvel[2]; + m_angular_velocity[0] = angvel[0]; + m_angular_velocity[1] = angvel[1]; + m_angular_velocity[2] = angvel[2]; + if (m_OriginalObject) m_OriginalObject->RegisterActuator(this); @@ -163,31 +166,33 @@ void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_SCA_AddObjectActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_SCA_AddObjectActuator", - sizeof(KX_SCA_AddObjectActuator), - 0, - PyDestructor, + sizeof(PyObjectPlus_Proxy), 0, - __getattr, - __setattr, - 0, - __repr, + py_base_dealloc, 0, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_SCA_AddObjectActuator::Parents[] = { + &KX_SCA_AddObjectActuator::Type, &SCA_IActuator::Type, &SCA_ILogicBrick::Type, &CValue::Type, NULL }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { + // ---> deprecated {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc}, {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc}, {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, (PY_METHODCHAR)GetLinearVelocity_doc}, @@ -196,8 +201,6 @@ PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {"setAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetAngularVelocity, METH_VARARGS, (PY_METHODCHAR)SetAngularVelocity_doc}, {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_NOARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, - - // ---> deprecated {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, @@ -205,42 +208,60 @@ PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { }; PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = { + KX_PYATTRIBUTE_RW_FUNCTION("object",KX_SCA_AddObjectActuator,pyattr_get_object,pyattr_set_object), + KX_PYATTRIBUTE_RO_FUNCTION("objectLastCreated",KX_SCA_AddObjectActuator,pyattr_get_objectLastCreated), + KX_PYATTRIBUTE_INT_RW("time",0,2000,true,KX_SCA_AddObjectActuator,m_timeProp), + KX_PYATTRIBUTE_FLOAT_ARRAY_RW("linearVelocity",-FLT_MAX,FLT_MAX,KX_SCA_AddObjectActuator,m_linear_velocity,3), + KX_PYATTRIBUTE_FLOAT_ARRAY_RW("angularVelocity",-FLT_MAX,FLT_MAX,KX_SCA_AddObjectActuator,m_angular_velocity,3), { NULL } //Sentinel }; -PyObject* KX_SCA_AddObjectActuator::_getattr(const char *attr) +PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { - if (!strcmp(attr, "object")) { - if (!m_OriginalObject) Py_RETURN_NONE; - else return m_OriginalObject->AddRef(); - } else if (!strcmp(attr, "objectLastCreated")) { - if (!m_OriginalObject) Py_RETURN_NONE; - else return m_lastCreatedObject->AddRef(); - } - - _getattr_up(SCA_IActuator); + KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self); + if (!actuator->m_OriginalObject) + Py_RETURN_NONE; + else + return actuator->m_OriginalObject->GetProxy(); } -int KX_SCA_AddObjectActuator::_setattr(const char *attr, PyObject* value) { - - if (!strcmp(attr, "object")) { - KX_GameObject *gameobj; +int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self); + KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) - return 1; // ConvertPythonToGameObject sets the error + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SCA_AddObjectActuator")) + return 1; // ConvertPythonToGameObject sets the error - if (m_OriginalObject != NULL) - m_OriginalObject->UnregisterActuator(this); + if (actuator->m_OriginalObject != NULL) + actuator->m_OriginalObject->UnregisterActuator(actuator); - m_OriginalObject = (SCA_IObject*)gameobj; + actuator->m_OriginalObject = (SCA_IObject*)gameobj; - if (m_OriginalObject) - m_OriginalObject->RegisterActuator(this); + if (actuator->m_OriginalObject) + actuator->m_OriginalObject->RegisterActuator(actuator); - return 0; - } - - return SCA_IActuator::_setattr(attr, value); + return 0; +} + +PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SCA_AddObjectActuator* actuator = static_cast<KX_SCA_AddObjectActuator*>(self); + if (!actuator->m_lastCreatedObject) + Py_RETURN_NONE; + else + return actuator->m_lastCreatedObject->GetProxy(); +} + + +PyObject* KX_SCA_AddObjectActuator::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_IActuator); +} + +int KX_SCA_AddObjectActuator::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IActuator); } /* 1. setObject */ @@ -249,13 +270,13 @@ const char KX_SCA_AddObjectActuator::SetObject_doc[] = "\t- object: KX_GameObject, string or None\n" "\tSets the object that will be added. There has to be an object\n" "\tof this name. If not, this function does nothing.\n"; -PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* value) +PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* value) { KX_GameObject *gameobj; ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_SCA_AddObjectActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_OriginalObject != NULL) @@ -278,8 +299,9 @@ const char KX_SCA_AddObjectActuator::SetTime_doc[] = "\tIf the duration is negative, it is set to 0.\n"; -PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value) +PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* value) { + ShowDeprecationWarning("setTime()", "the time property"); int deltatime = PyInt_AsLong(value); if (deltatime==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int"); @@ -296,12 +318,13 @@ PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value) /* 3. getTime */ const char KX_SCA_AddObjectActuator::GetTime_doc[] = -"GetTime()\n" +"getTime()\n" "\tReturns the lifetime of the object that will be added.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyGetTime() { + ShowDeprecationWarning("getTime()", "the time property"); return PyInt_FromLong(m_timeProp); } @@ -311,13 +334,13 @@ const char KX_SCA_AddObjectActuator::GetObject_doc[] = "getObject(name_only = 1)\n" "name_only - optional arg, when true will return the KX_GameObject rather then its name\n" "\tReturns the name of the object that will be added.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args) +PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* args) { int ret_name_only = 1; ShowDeprecationWarning("getObject()", "the object property"); - if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) + if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only)) return NULL; if (!m_OriginalObject) @@ -326,7 +349,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_OriginalObject->GetName()); else - return m_OriginalObject->AddRef(); + return m_OriginalObject->GetProxy(); } @@ -337,8 +360,9 @@ const char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = "\tReturns the linear velocity that will be assigned to \n" "\tthe created object.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity() { + ShowDeprecationWarning("getLinearVelocity()", "the linearVelocity property"); PyObject *retVal = PyList_New(3); PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); @@ -359,14 +383,17 @@ const char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = "\t- local: bool\n" "\tAssign this velocity to the created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* args) +PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* args) { + ShowDeprecationWarning("setLinearVelocity()", "the linearVelocity property"); float vecArg[3]; - if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) + if (!PyArg_ParseTuple(args, "fff:setLinearVelocity", &vecArg[0], &vecArg[1], &vecArg[2])) return NULL; - m_linear_velocity.setValue(vecArg); + m_linear_velocity[0] = vecArg[0]; + m_linear_velocity[1] = vecArg[1]; + m_linear_velocity[2] = vecArg[2]; Py_RETURN_NONE; } @@ -376,8 +403,9 @@ const char KX_SCA_AddObjectActuator::GetAngularVelocity_doc[] = "\tReturns the angular velocity that will be assigned to \n" "\tthe created object.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity() { + ShowDeprecationWarning("getAngularVelocity()", "the angularVelocity property"); PyObject *retVal = PyList_New(3); PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); @@ -398,14 +426,17 @@ const char KX_SCA_AddObjectActuator::SetAngularVelocity_doc[] = "\t- local: bool\n" "\tAssign this angular velocity to the created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* args) +PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* args) { + ShowDeprecationWarning("setAngularVelocity()", "the angularVelocity property"); float vecArg[3]; - if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) + if (!PyArg_ParseTuple(args, "fff:setAngularVelocity", &vecArg[0], &vecArg[1], &vecArg[2])) return NULL; - m_angular_velocity.setValue(vecArg); + m_angular_velocity[0] = vecArg[0]; + m_angular_velocity[1] = vecArg[1]; + m_angular_velocity[2] = vecArg[2]; Py_RETURN_NONE; } @@ -417,7 +448,7 @@ void KX_SCA_AddObjectActuator::InstantAddObject() // Now it needs to be added to the current scene. SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp ); KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica); - game_obj->setLinearVelocity(m_linear_velocity,m_localLinvFlag); + game_obj->setLinearVelocity(m_linear_velocity ,m_localLinvFlag); game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag); game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag); @@ -436,7 +467,7 @@ void KX_SCA_AddObjectActuator::InstantAddObject() } } -PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject() { InstantAddObject(); @@ -451,16 +482,16 @@ const char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = "\tReturn the last created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject() { + ShowDeprecationWarning("getLastCreatedObject()", "the objectLastCreated property"); SCA_IObject* result = this->GetLastCreatedObject(); // if result->GetSGNode() is NULL // it means the object has ended, The BGE python api crashes in many places if the object is returned. if (result && (static_cast<KX_GameObject *>(result))->GetSGNode()) { - result->AddRef(); - return result; + return result->GetProxy(); } // don't return NULL to python anymore, it gives trouble in the scripts Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 18298cbcb0c..4ece5a6d83b 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -59,12 +59,12 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator SCA_IScene* m_scene; /// Linear velocity upon creation of the object. - MT_Vector3 m_linear_velocity; + float m_linear_velocity[3]; /// Apply the velocity locally bool m_localLinvFlag; /// Angular velocity upon creation of the object. - MT_Vector3 m_angular_velocity; + float m_angular_velocity[3]; /// Apply the velocity locally bool m_localAngvFlag; @@ -85,9 +85,9 @@ public: SCA_IObject *original, int time, SCA_IScene* scene, - const MT_Vector3& linvel, + const float *linvel, bool linv_local, - const MT_Vector3& angvel, + const float *angvel, bool angv_local, PyTypeObject* T=&Type ); @@ -110,8 +110,8 @@ public: virtual bool Update(); - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject* value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); SCA_IObject* GetLastCreatedObject( @@ -140,6 +140,9 @@ public: /* 10. instantAddObject*/ KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject); + static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); }; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index 394bb667728..83dfdc2484c 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -49,25 +49,23 @@ PyTypeObject -KX_SCA_DynamicActuator:: - -Type = { - PyObject_HEAD_INIT(&PyType_Type) +KX_SCA_DynamicActuator::Type = { + PyObject_HEAD_INIT(NULL) 0, "KX_SCA_DynamicActuator", - sizeof(KX_SCA_DynamicActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, - __repr, - 0, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_SCA_DynamicActuator::Parents[] = { @@ -80,21 +78,28 @@ PyParentObject KX_SCA_DynamicActuator::Parents[] = { PyMethodDef KX_SCA_DynamicActuator::Methods[] = { + // ---> deprecated KX_PYMETHODTABLE(KX_SCA_DynamicActuator, setOperation), KX_PYMETHODTABLE(KX_SCA_DynamicActuator, getOperation), {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = { + KX_PYATTRIBUTE_SHORT_RW("operation",0,4,false,KX_SCA_DynamicActuator,m_dyn_operation), + KX_PYATTRIBUTE_FLOAT_RW("mass",0.0,FLT_MAX,KX_SCA_DynamicActuator,m_setmass), { NULL } //Sentinel }; -PyObject* KX_SCA_DynamicActuator::_getattr(const char *attr) +PyObject* KX_SCA_DynamicActuator::py_getattro(PyObject *attr) { - _getattr_up(SCA_IActuator); + py_getattro_up(SCA_IActuator); } +int KX_SCA_DynamicActuator::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IActuator); +} /* 1. setOperation */ @@ -107,9 +112,10 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, "\t 3 = disable rigid body\n" "Change the dynamic status of the parent object.\n") { + ShowDeprecationWarning("setOperation()", "the operation property"); int dyn_operation; - if (!PyArg_ParseTuple(args, "i", &dyn_operation)) + if (!PyArg_ParseTuple(args, "i:setOperation", &dyn_operation)) { return NULL; } @@ -126,6 +132,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, "Returns the operation type of this actuator.\n" ) { + ShowDeprecationWarning("getOperation()", "the operation property"); return PyInt_FromLong((long)m_dyn_operation); } diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index a82cddd66a7..99855124bdb 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -64,7 +64,18 @@ class KX_SCA_DynamicActuator : public SCA_IActuator virtual bool Update(); - virtual PyObject* _getattr(const char *attr); + //Python Interface + enum DynamicOperation { + KX_DYN_RESTORE_DYNAMICS = 0, + KX_DYN_DISABLE_DYNAMICS, + KX_DYN_ENABLE_RIGID_BODY, + KX_DYN_DISABLE_RIGID_BODY, + KX_DYN_SET_MASS, + }; + + + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. setOperation */ KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation); diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index 9268a1df5f0..3b42577810e 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -94,22 +94,22 @@ CValue* KX_SCA_EndObjectActuator::GetReplica() /* ------------------------------------------------------------------------- */ PyTypeObject KX_SCA_EndObjectActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_SCA_EndObjectActuator", - sizeof(KX_SCA_EndObjectActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -131,9 +131,9 @@ PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_EndObjectActuator::_getattr(const char *attr) +PyObject* KX_SCA_EndObjectActuator::py_getattro(PyObject *attr) { - _getattr_up(SCA_IActuator); + py_getattro_up(SCA_IActuator); } /* eof */ diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h index 12118743f0a..2940246f443 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h @@ -64,7 +64,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 502990b2b27..38f8d581d55 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -36,6 +36,7 @@ // Please look here for revision history. #include "KX_SCA_ReplaceMeshActuator.h" +#include "KX_MeshProxy.h" #include "PyObjectPlus.h" @@ -51,28 +52,27 @@ PyTypeObject -KX_SCA_ReplaceMeshActuator:: - -Type = { - PyObject_HEAD_INIT(&PyType_Type) +KX_SCA_ReplaceMeshActuator::Type = { + PyObject_HEAD_INIT(NULL) 0, "KX_SCA_ReplaceMeshActuator", - sizeof(KX_SCA_ReplaceMeshActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, - __repr, - 0, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { + &KX_SCA_ReplaceMeshActuator::Type, &SCA_IActuator::Type, &SCA_ILogicBrick::Type, &CValue::Type, @@ -82,23 +82,48 @@ PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { - {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_O, (PY_METHODCHAR)SetMesh_doc}, - KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh), + // Deprecated -----> + {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_O, (PY_METHODCHAR)SetMesh_doc}, KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, getMesh), {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = { + KX_PYATTRIBUTE_RW_FUNCTION("mesh", KX_SCA_ReplaceMeshActuator, pyattr_get_mesh, pyattr_set_mesh), { NULL } //Sentinel }; -PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const char *attr) +PyObject* KX_SCA_ReplaceMeshActuator::py_getattro(PyObject *attr) { - _getattr_up(SCA_IActuator); + py_getattro_up(SCA_IActuator); } +int KX_SCA_ReplaceMeshActuator::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IActuator); +} + +PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SCA_ReplaceMeshActuator* actuator = static_cast<KX_SCA_ReplaceMeshActuator*>(self); + if (!actuator->m_mesh) + Py_RETURN_NONE; + KX_MeshProxy* meshproxy = new KX_MeshProxy(actuator->m_mesh); + return meshproxy->NewProxy(true); +} +int KX_SCA_ReplaceMeshActuator::pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_SCA_ReplaceMeshActuator* actuator = static_cast<KX_SCA_ReplaceMeshActuator*>(self); + RAS_MeshObject* new_mesh; + + if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator")) + return 1; + + actuator->m_mesh = new_mesh; + return 0; +} /* 1. setMesh */ const char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] = @@ -106,25 +131,15 @@ const char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] = "\t- name: string or None\n" "\tSet the mesh that will be substituted for the current one.\n"; -PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, PyObject* value) +PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* value) { - if (value == Py_None) { - m_mesh = NULL; - } else { - char* meshname = PyString_AsString(value); - if (!meshname) { - PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None"); - return NULL; - } - void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); - - if (mesh==NULL) { - PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist"); - return NULL; - } - m_mesh= (class RAS_MeshObject*)mesh; - } + ShowDeprecationWarning("setMesh()", "the mesh property"); + RAS_MeshObject* new_mesh; + + if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator")) + return NULL; + m_mesh = new_mesh; Py_RETURN_NONE; } @@ -133,6 +148,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, "Returns the name of the mesh to be substituted.\n" ) { + ShowDeprecationWarning("getMesh()", "the mesh property"); if (!m_mesh) Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 0ba60650683..7a18df2356d 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -69,9 +69,14 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator virtual bool Update(); - virtual PyObject* _getattr(const char *attr); void InstantReplaceMesh(); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); + + static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + /* 1. setMesh */ KX_PYMETHOD_DOC_O(KX_SCA_ReplaceMeshActuator,SetMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,getMesh); diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index 151270cbd68..0e7571031e8 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -57,7 +57,8 @@ New(Bone* bone KX_BoneParentRelation:: UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ){ MT_assert(child != NULL); @@ -67,6 +68,8 @@ UpdateChildCoordinates( const MT_Vector3 & child_scale = child->GetLocalScale(); const MT_Point3 & child_pos = child->GetLocalPosition(); const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation(); + // we don't know if the armature has been updated or not, assume yes + parentUpdated = true; // the childs world locations which we will update. @@ -122,7 +125,7 @@ UpdateChildCoordinates( else { child->SetWorldFromLocalTransform(); } - + child->SetModified(false); return valid_parent_transform; } diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h index 2a19d8a1784..c9baf228855 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h @@ -82,7 +82,8 @@ public : bool UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ); /** diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp index 0729ec8a902..c3b0c21c8e0 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp @@ -51,13 +51,20 @@ New( KX_NormalParentRelation:: UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ){ MT_assert(child != NULL); + if (!parentUpdated && !child->IsModified()) + return false; + + parentUpdated = true; + if (parent==NULL) { /* Simple case */ child->SetWorldFromLocalTransform(); - return false; + child->SetModified(false); + return true; //false; } else { // the childs world locations which we will update. @@ -68,6 +75,7 @@ UpdateChildCoordinates( child->SetWorldScale(p_world_scale * child->GetLocalScale()); child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation()); child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition())); + child->SetModified(false); return true; } } @@ -112,10 +120,15 @@ New( KX_VertexParentRelation:: UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ){ MT_assert(child != NULL); + + if (!parentUpdated && !child->IsModified()) + return false; + child->SetWorldScale(child->GetLocalScale()); if (parent) @@ -124,7 +137,8 @@ UpdateChildCoordinates( child->SetWorldPosition(child->GetLocalPosition()); child->SetWorldOrientation(child->GetLocalOrientation()); - return parent != NULL; + child->SetModified(false); + return true; //parent != NULL; } /** @@ -172,10 +186,14 @@ New( KX_SlowParentRelation:: UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ){ MT_assert(child != NULL); + // the child will move even if the parent is not + parentUpdated = true; + const MT_Vector3 & child_scale = child->GetLocalScale(); const MT_Point3 & child_pos = child->GetLocalPosition(); const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation(); @@ -217,23 +235,12 @@ UpdateChildCoordinates( // now 'interpolate' the normal coordinates with the last // world coordinates to get the new world coordinates. - // problem 1: - // The child world scale needs to be initialized in some way for this - // to make sense - // problem 2: - // This is way of doing interpolation is nonsense - - int i; - MT_Scalar weight = MT_Scalar(1)/(m_relax + 1); - for (i=0;i <3 ;i++) { - child_w_scale[i] = (m_relax * child_w_scale[i] + child_n_scale[i]) * weight; - child_w_pos[i] = (m_relax * child_w_pos[i] + child_n_pos[i]) * weight; - child_w_rotation[0][i] = (m_relax * child_w_rotation[0][i] + child_n_rotation[0][i]) * weight; - child_w_rotation[1][i] = (m_relax * child_w_rotation[1][i] + child_n_rotation[1][i]) * weight; - child_w_rotation[2][i] = (m_relax * child_w_rotation[2][i] + child_n_rotation[2][i]) * weight; - } - + child_w_scale = (m_relax * child_w_scale + child_n_scale) * weight; + child_w_pos = (m_relax * child_w_pos + child_n_pos) * weight; + // for rotation we must go through quaternion + MT_Quaternion child_w_quat = child_w_rotation.getRotation().slerp(child_n_rotation.getRotation(), weight); + child_w_rotation.setRotation(child_w_quat); //FIXME: update physics controller. } else { child_w_scale = child_n_scale; @@ -252,8 +259,9 @@ UpdateChildCoordinates( child->SetWorldScale(child_w_scale); child->SetWorldPosition(child_w_pos); child->SetWorldOrientation(child_w_rotation); + child->SetModified(false); - return parent != NULL; + return true; //parent != NULL; } /** diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h index faa650106c8..d8fb9211f21 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h @@ -71,7 +71,8 @@ public : bool UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ); /** @@ -115,7 +116,8 @@ public : bool UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ); /** @@ -166,7 +168,8 @@ public : bool UpdateChildCoordinates( SG_Spatial * child, - const SG_Spatial * parent + const SG_Spatial * parent, + bool& parentUpdated ); /** diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 0fded15f1a1..aa7bd65f240 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -32,7 +32,6 @@ #pragma warning (disable : 4786) #endif //WIN32 - #include "KX_Scene.h" #include "MT_assert.h" @@ -77,7 +76,9 @@ #include "NG_NetworkScene.h" #include "PHY_IPhysicsEnvironment.h" #include "KX_IPhysicsController.h" +#include "PHY_IGraphicController.h" #include "KX_BlenderSceneConverter.h" +#include "KX_MotionState.h" #include "BL_ShapeDeformer.h" #include "BL_DeformableGameObject.h" @@ -90,6 +91,8 @@ #include "CcdPhysicsController.h" #endif +#include "KX_Light.h" + void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) { KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj); @@ -134,6 +137,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_suspendedtime = 0.0; m_suspendeddelta = 0.0; + m_dbvt_culling = false; + m_dbvt_occlusion_res = 0; m_activity_culling = false; m_suspend = false; m_isclearingZbuffer = true; @@ -191,7 +196,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_canvasDesignWidth = 0; m_canvasDesignHeight = 0; - m_attrlist = PyDict_New(); /* new ref */ + m_attr_dict = PyDict_New(); /* new ref */ } @@ -245,7 +250,8 @@ KX_Scene::~KX_Scene() { delete m_bucketmanager; } - //Py_DECREF(m_attrlist); + PyDict_Clear(m_attr_dict); + Py_DECREF(m_attr_dict); } void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat) @@ -408,6 +414,13 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam // will in any case be deleted. This ensures that the object will not try to use the node // when it is finally deleted (see KX_GameObject destructor) orgobj->SetSGNode(NULL); + PHY_IGraphicController* ctrl = orgobj->GetGraphicController(); + if (ctrl) + { + // a graphic controller is set, we must delete it as the node will be deleted + delete ctrl; + orgobj->SetGraphicController(NULL); + } } if (node) delete node; @@ -486,7 +499,14 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal replicanode->AddSGController(replicacontroller); } } - + // replicate graphic controller + if (orgobj->GetGraphicController()) + { + PHY_IMotionState* motionstate = new KX_MotionState(newobj->GetSGNode()); + PHY_IGraphicController* newctrl = orgobj->GetGraphicController()->GetReplica(motionstate); + newctrl->setNewClientInfo(newobj->getClientInfo()); + newobj->SetGraphicController(newctrl); + } return newobj; } @@ -698,9 +718,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation(); replica->NodeSetLocalOrientation(newori); - + MT_Point3 offset(group->dupli_ofs); MT_Point3 newpos = groupobj->NodeGetWorldPosition() + - newscale*(groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldPosition()); + newscale*(groupobj->NodeGetWorldOrientation() * (gameobj->NodeGetWorldPosition()-offset)); replica->NodeSetLocalPosition(newpos); replica->GetSGNode()->UpdateWorldData(0); @@ -725,6 +745,12 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent (*git)->SetLayer(groupobj->GetLayer()); + // If the object was a light, we need to update it's RAS_LightObject as well + if ((*git)->IsLight()) + { + KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); + lightobj->GetLightData()->m_layer = groupobj->GetLayer(); + } } // replicate crosslinks etc. between logic bricks @@ -793,6 +819,24 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->AddChild(childreplicanode); } + // At this stage all the objects in the hierarchy have been duplicated, + // we can update the scenegraph, we need it for the duplication of logic + MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition(); + replica->NodeSetLocalPosition(newpos); + + MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + + // get the rootnode's scale + MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + + replica->GetSGNode()->UpdateWorldData(0); + replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); + replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius()); + // now replicate logic vector<KX_GameObject*>::iterator git; for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) @@ -807,6 +851,12 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent (*git)->SetLayer(parentobj->GetLayer()); + // If the object was a light, we need to update it's RAS_LightObject as well + if ((*git)->IsLight()) + { + KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); + lightobj->GetLightData()->m_layer = parentobj->GetLayer(); + } } // replicate crosslinks etc. between logic bricks @@ -815,21 +865,6 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, ReplicateLogic((*git)); } - MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition(); - replica->NodeSetLocalPosition(newpos); - - MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation(); - replica->NodeSetLocalOrientation(newori); - - // get the rootnode's scale - MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); - - // set the replica's relative scale with the rootnode's scale - replica->NodeSetRelativeScale(newscale); - - replica->GetSGNode()->UpdateWorldData(0); - replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); - replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius()); // check if there are objects with dupligroup in the hierarchy vector<KX_GameObject*> duplilist; for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) @@ -937,7 +972,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) newobj->RemoveMeshes(); ret = 1; - if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell + if (newobj->IsLight() && m_lightlist->RemoveValue(newobj)) ret = newobj->Release(); if (m_objectlist->RemoveValue(newobj)) ret = newobj->Release(); @@ -963,6 +998,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) if (m_sceneConverter) m_sceneConverter->UnregisterGameObject(newobj); // return value will be 0 if the object is actually deleted (all reference gone) + return ret; } @@ -1164,7 +1200,6 @@ void KX_Scene::UpdateMeshTransformations() { KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i); gameobj->GetOpenGLMatrix(); -// gameobj->UpdateNonDynas(); } } @@ -1299,21 +1334,47 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam } } +void KX_Scene::PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo) +{ + KX_GameObject* gameobj = objectInfo->m_gameobject; + if (!gameobj->GetVisible()) + // ideally, invisible objects should be removed from the culling tree temporarily + return; + if(((CullingInfo*)cullingInfo)->m_layer && !(gameobj->GetLayer() & ((CullingInfo*)cullingInfo)->m_layer)) + // used for shadow: object is not in shadow layer + return; + + // make object visible + gameobj->SetCulled(false); + gameobj->UpdateBuckets(false); +} + void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int layer) { -// FIXME: When tree is operational -#if 1 - // do this incrementally in the future - for (int i = 0; i < m_objectlist->GetCount(); i++) + bool dbvt_culling = false; + if (m_dbvt_culling) { - MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer); + // test culling through Bullet + PHY__Vector4 planes[6]; + // get the clip planes + MT_Vector4* cplanes = cam->GetNormalizedClipPlanes(); + // and convert + planes[0].setValue(cplanes[4].getValue()); // near + planes[1].setValue(cplanes[5].getValue()); // far + planes[2].setValue(cplanes[0].getValue()); // left + planes[3].setValue(cplanes[1].getValue()); // right + planes[4].setValue(cplanes[2].getValue()); // top + planes[5].setValue(cplanes[3].getValue()); // bottom + CullingInfo info(layer); + dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res); + } + if (!dbvt_culling) { + // the physics engine couldn't help us, do it the hard way + for (int i = 0; i < m_objectlist->GetCount(); i++) + { + MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer); + } } -#else - if (cam->GetFrustumCulling()) - MarkVisible(m_objecttree, rasty, cam, layer); - else - MarkSubTreeVisible(m_objecttree, rasty, true, cam, layer); -#endif } // logic stuff @@ -1394,7 +1455,7 @@ void KX_Scene::UpdateParents(double curtime) for (int i=0; i<GetRootParentList()->GetCount(); i++) { KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i); - parentobj->NodeUpdateGS(curtime,true); + parentobj->NodeUpdateGS(curtime); } } @@ -1518,22 +1579,22 @@ double KX_Scene::getSuspendedDelta() //Python PyTypeObject KX_Scene::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_Scene", - sizeof(KX_Scene), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_Scene::Parents[] = { @@ -1551,52 +1612,102 @@ PyMethodDef KX_Scene::Methods[] = { {NULL,NULL} //Sentinel }; +PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self= static_cast<KX_Scene*>(self_v); + return PyString_FromString(self->GetName().ReadPtr()); +} + +PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self= static_cast<KX_Scene*>(self_v); + return self->GetObjectList()->GetProxy(); +} + +PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self= static_cast<KX_Scene*>(self_v); + return self->GetActiveCamera()->GetProxy(); +} + +/* __dict__ only for the purpose of giving useful dir() results */ +PyObject* KX_Scene::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self= static_cast<KX_Scene*>(self_v); + /* Useually done by py_getattro_up but in this case we want to include m_attr_dict dict */ + PyObject *dict_str= PyString_FromString("__dict__"); + PyObject *dict= py_getattr_dict(self->PyObjectPlus::py_getattro(dict_str), Type.tp_dict); + Py_DECREF(dict_str); + + PyDict_Update(dict, self->m_attr_dict); + return dict; +} + PyAttributeDef KX_Scene::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name), + KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects), + KX_PYATTRIBUTE_RO_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera), + KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), + KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), + KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius), + KX_PYATTRIBUTE_BOOL_RO("dbvt_culling", KX_Scene, m_dbvt_culling), + KX_PYATTRIBUTE_RO_FUNCTION("__dict__", KX_Scene, pyattr_get_dir_dict), { NULL } //Sentinel }; -PyObject* KX_Scene::_getattr(const char *attr) + +PyObject* KX_Scene::py_getattro__internal(PyObject *attr) +{ + py_getattro_up(PyObjectPlus); +} + +int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *pyvalue) { - if (!strcmp(attr, "name")) - return PyString_FromString(GetName()); - - if (!strcmp(attr, "objects")) - return (PyObject*) m_objectlist->AddRef(); - - if (!strcmp(attr, "active_camera")) - return (PyObject*) GetActiveCamera()->AddRef(); - - if (!strcmp(attr, "suspended")) - return PyInt_FromLong(m_suspend); - - if (!strcmp(attr, "activity_culling")) - return PyInt_FromLong(m_activity_culling); - - if (!strcmp(attr, "activity_culling_radius")) - return PyFloat_FromDouble(m_activity_box_radius); + return PyObjectPlus::py_setattro(attr, pyvalue); +} + +PyObject* KX_Scene::py_getattro(PyObject *attr) +{ + PyObject *object = py_getattro__internal(attr); - PyObject* value = PyDict_GetItemString(m_attrlist, attr); - if (value) + if (object==NULL) { - Py_INCREF(value); - return value; + PyErr_Clear(); + object = PyDict_GetItem(m_attr_dict, attr); + if(object) { + Py_INCREF(object); + } + else { + PyErr_Format(PyExc_AttributeError, "value = scene.myAttr: KX_Scene, attribute \"%s\" not found", PyString_AsString(attr)); + } } - _getattr_up(PyObjectPlus); + return object; } -int KX_Scene::_delattr(const char *attr) + +int KX_Scene::py_setattro(PyObject *attr, PyObject *value) { - PyDict_DelItemString(m_attrlist, attr); - return 0; + int ret= py_setattro__internal(attr, value); + + if (ret==PY_SET_ATTR_MISSING) { + if (PyDict_SetItem(m_attr_dict, attr, value)==0) { + PyErr_Clear(); + ret= PY_SET_ATTR_SUCCESS; + } + else { + PyErr_SetString(PyExc_AttributeError, "scene.UserAttr = value: KX_Scenes, failed assigning value to internal dictionary"); + ret= PY_SET_ATTR_FAIL; + } + } + + return ret; } -int KX_Scene::_setattr(const char *attr, PyObject *pyvalue) +int KX_Scene::py_delattro(PyObject *attr) { - if (!PyDict_SetItemString(m_attrlist, attr, pyvalue)) - return 0; - - return PyObjectPlus::_setattr(attr, pyvalue); + PyDict_DelItem(m_attr_dict, attr); + return 0; } KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, @@ -1604,7 +1715,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "Returns a list of all lights in the scene.\n" ) { - return (PyObject*) m_lightlist->AddRef(); + return m_lightlist->GetProxy(); } KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, @@ -1613,7 +1724,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, ) { // ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work? - return (PyObject*) m_objectlist->AddRef(); + return m_objectlist->GetProxy(); } KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, @@ -1633,15 +1744,14 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, int time = 0; - if (!PyArg_ParseTuple(args, "OO|i", &pyob, &pyother, &time)) + if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time)) return NULL; - if (!ConvertPythonToGameObject(pyob, &ob, false) - || !ConvertPythonToGameObject(pyother, &other, false)) + if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) return NULL; SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); - replica->AddRef(); - return replica; + return replica->GetProxy(); }
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 962db1a9b96..a06c66ec5dd 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -85,6 +85,8 @@ class RAS_IRenderTools; class SCA_JoystickManager; class btCollisionShape; class KX_BlenderSceneConverter; +struct KX_ClientObjectInfo; + /** * The KX_Scene holds all data for an independent scene. It relates * KX_Objects to the specific objects in the modules. @@ -92,6 +94,12 @@ class KX_BlenderSceneConverter; class KX_Scene : public PyObjectPlus, public SCA_IScene { Py_Header; + + struct CullingInfo { + int m_layer; + CullingInfo(int layer) : m_layer(layer) {} + }; + protected: RAS_BucketManager* m_bucketmanager; CListValue* m_tempObjectList; @@ -252,6 +260,16 @@ protected: bool m_activity_culling; /** + * Toggle to enable or disable culling via DBVT broadphase of Bullet. + */ + bool m_dbvt_culling; + + /** + * Occlusion culling resolution + */ + int m_dbvt_occlusion_res; + + /** * The framing settings used by this scene */ @@ -269,6 +287,7 @@ protected: void MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera*cam,int layer=0); void MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera*cam,int layer=0); void MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj, KX_Camera*cam, int layer=0); + static void PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo); double m_suspendedtime; double m_suspendeddelta; @@ -276,7 +295,7 @@ protected: /** * This stores anything from python */ - PyObject* m_attrlist; + PyObject* m_attr_dict; struct Scene* m_blenderScene; @@ -530,6 +549,11 @@ public: bool IsSuspended(); bool IsClearingZBuffer(); void EnableZBufferClearing(bool isclearingZbuffer); + // use of DBVT tree for camera culling + void SetDbvtCulling(bool b) { m_dbvt_culling = b; }; + bool GetDbvtCulling() { return m_dbvt_culling; }; + void SetDbvtOcclusionRes(int i) { m_dbvt_occlusion_res = i; }; + int GetDbvtOcclusionRes() { return m_dbvt_occlusion_res; }; void SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter); @@ -565,11 +589,22 @@ public: KX_PYMETHOD_DOC(KX_Scene, setSceneViewport); */ - virtual PyObject* _getattr(const char *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ - virtual int _setattr(const char *attr, PyObject *pyvalue); - virtual int _delattr(const char *attr); - virtual PyObject* _repr(void) { return PyString_FromString(GetName().ReadPtr()); } + /* attributes */ + static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_objects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + /* for dir(), python3 uses __dir__() */ + static PyObject* pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + + virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ + virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + virtual int py_delattro(PyObject *attr); + virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); } + PyObject* py_getattro__internal(PyObject *attr); + int py_setattro__internal(PyObject *attr, PyObject *pyvalue); /** * Sets the time the scene was suspended diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 1cad4e21352..f54d8542260 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -226,22 +226,22 @@ KX_Scene* KX_SceneActuator::FindScene(char * sceneName) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_SceneActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_SceneActuator", - sizeof(KX_SceneActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -259,24 +259,93 @@ PyParentObject KX_SceneActuator::Parents[] = PyMethodDef KX_SceneActuator::Methods[] = { + //Deprecated functions ------> {"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, (PY_METHODCHAR)SetUseRestart_doc}, {"setScene", (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, (PY_METHODCHAR)SetScene_doc}, {"setCamera", (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, (PY_METHODCHAR)SetCamera_doc}, - {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_VARARGS, (PY_METHODCHAR)GetUseRestart_doc}, - {"getScene", (PyCFunction) KX_SceneActuator::sPyGetScene, METH_VARARGS, (PY_METHODCHAR)GetScene_doc}, - {"getCamera", (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_VARARGS, (PY_METHODCHAR)GetCamera_doc}, + {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_NOARGS, (PY_METHODCHAR)GetUseRestart_doc}, + {"getScene", (PyCFunction) KX_SceneActuator::sPyGetScene, METH_NOARGS, (PY_METHODCHAR)GetScene_doc}, + {"getCamera", (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_NOARGS, (PY_METHODCHAR)GetCamera_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; PyAttributeDef KX_SceneActuator::Attributes[] = { + KX_PYATTRIBUTE_STRING_RW("scene",0,32,true,KX_SceneActuator,m_nextSceneName), + KX_PYATTRIBUTE_RW_FUNCTION("camera",KX_SceneActuator,pyattr_get_camera,pyattr_set_camera), { NULL } //Sentinel }; -PyObject* KX_SceneActuator::_getattr(const char *attr) +PyObject* KX_SceneActuator::py_getattro(PyObject *attr) { - _getattr_up(SCA_IActuator); + py_getattro_up(SCA_IActuator); } +int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_IActuator); +} + +PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self); + if (!actuator->m_camera) + Py_RETURN_NONE; + + return actuator->m_camera->GetProxy(); +} + +int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self); + KX_Camera *camOb; + + if(value==Py_None) + { + if (actuator->m_camera) + actuator->m_camera->UnregisterActuator(actuator); + + actuator->m_camera= NULL; + return 0; + } + + if (PyObject_TypeCheck(value, &KX_Camera::Type)) + { + KX_Camera *camOb= static_cast<KX_Camera*>BGE_PROXY_REF(value); + + if(camOb==NULL) + { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + return 1; + } + + if (actuator->m_camera) + actuator->m_camera->UnregisterActuator(actuator); + + actuator->m_camera = camOb; + actuator->m_camera->RegisterActuator(actuator); + return 0; + } + + if (PyString_Check(value)) + { + char *camName = PyString_AsString(value); + + camOb = actuator->FindCamera(camName); + if (camOb) + { + if (actuator->m_camera) + actuator->m_camera->UnregisterActuator(actuator); + actuator->m_camera = camOb; + actuator->m_camera->RegisterActuator(actuator); + return 0; + } + PyErr_SetString(PyExc_TypeError, "not a valid camera name"); + return 1; + } + PyErr_SetString(PyExc_TypeError, "expected a string or a camera object reference"); + return 1; +} /* 2. setUseRestart--------------------------------------------------------- */ @@ -284,13 +353,12 @@ const char KX_SceneActuator::SetUseRestart_doc[] = "setUseRestart(flag)\n" "\t- flag: 0 or 1.\n" "\tSet flag to 1 to restart the scene.\n" ; -PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SceneActuator::PySetUseRestart(PyObject* args) { + ShowDeprecationWarning("setUseRestart()", "(no replacement)"); int boolArg; - if (!PyArg_ParseTuple(args, "i", &boolArg)) + if (!PyArg_ParseTuple(args, "i:setUseRestart", &boolArg)) { return NULL; } @@ -306,10 +374,9 @@ PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self, const char KX_SceneActuator::GetUseRestart_doc[] = "getUseRestart()\n" "\tReturn whether the scene will be restarted.\n" ; -PyObject* KX_SceneActuator::PyGetUseRestart(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SceneActuator::PyGetUseRestart() { + ShowDeprecationWarning("getUseRestart()", "(no replacement)"); return PyInt_FromLong(!(m_restart == 0)); } @@ -320,14 +387,13 @@ const char KX_SceneActuator::SetScene_doc[] = "setScene(scene)\n" "\t- scene: string\n" "\tSet the name of scene the actuator will switch to.\n" ; -PyObject* KX_SceneActuator::PySetScene(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SceneActuator::PySetScene(PyObject* args) { + ShowDeprecationWarning("setScene()", "the scene property"); /* one argument: a scene, ignore the rest */ char *scene_name; - if(!PyArg_ParseTuple(args, "s", &scene_name)) + if(!PyArg_ParseTuple(args, "s:setScene", &scene_name)) { return NULL; } @@ -344,10 +410,9 @@ PyObject* KX_SceneActuator::PySetScene(PyObject* self, const char KX_SceneActuator::GetScene_doc[] = "getScene()\n" "\tReturn the name of the scene the actuator wants to switch to.\n" ; -PyObject* KX_SceneActuator::PyGetScene(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SceneActuator::PyGetScene() { + ShowDeprecationWarning("getScene()", "the scene property"); return PyString_FromString(m_nextSceneName); } @@ -358,25 +423,34 @@ const char KX_SceneActuator::SetCamera_doc[] = "setCamera(camera)\n" "\t- camera: string\n" "\tSet the camera to switch to.\n" ; -PyObject* KX_SceneActuator::PySetCamera(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SceneActuator::PySetCamera(PyObject* args) { + ShowDeprecationWarning("setCamera()", "the camera property"); PyObject *cam; - if (PyArg_ParseTuple(args, "O!", &KX_Camera::Type, &cam)) + if (PyArg_ParseTuple(args, "O!:setCamera", &KX_Camera::Type, &cam)) { + KX_Camera *new_camera; + + new_camera = static_cast<KX_Camera*>BGE_PROXY_REF(cam); + if(new_camera==NULL) + { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + return NULL; + } + if (m_camera) m_camera->UnregisterActuator(this); - m_camera = (KX_Camera*) cam; - if (m_camera) - m_camera->RegisterActuator(this); + + m_camera= new_camera; + + m_camera->RegisterActuator(this); Py_RETURN_NONE; } PyErr_Clear(); /* one argument: a scene, ignore the rest */ char *camName; - if(!PyArg_ParseTuple(args, "s", &camName)) + if(!PyArg_ParseTuple(args, "s:setCamera", &camName)) { return NULL; } @@ -399,10 +473,14 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, const char KX_SceneActuator::GetCamera_doc[] = "getCamera()\n" "\tReturn the name of the camera to switch to.\n" ; -PyObject* KX_SceneActuator::PyGetCamera(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SceneActuator::PyGetCamera() { - return PyString_FromString(m_camera->GetName()); + ShowDeprecationWarning("getCamera()", "the camera property"); + if (m_camera) { + return PyString_FromString(m_camera->GetName()); + } + else { + Py_RETURN_NONE; + } } /* eof */ diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index af11af955bf..803c5106a60 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -92,24 +92,28 @@ class KX_SceneActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. set */ /* Removed */ /* 2. setUseRestart: */ - KX_PYMETHOD_DOC(KX_SceneActuator,SetUseRestart); + KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetUseRestart); /* 3. getUseRestart: */ - KX_PYMETHOD_DOC(KX_SceneActuator,GetUseRestart); + KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetUseRestart); /* 4. setScene: */ - KX_PYMETHOD_DOC(KX_SceneActuator,SetScene); + KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetScene); /* 5. getScene: */ - KX_PYMETHOD_DOC(KX_SceneActuator,GetScene); + KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetScene); /* 6. setCamera: */ - KX_PYMETHOD_DOC(KX_SceneActuator,SetCamera); + KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetCamera); /* 7. getCamera: */ - KX_PYMETHOD_DOC(KX_SceneActuator,GetCamera); + KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetCamera); + static PyObject* pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + }; /* end of class KXSceneActuator */ #endif diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 6de1d67bfdb..412be497c5a 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -35,6 +35,7 @@ #include "KX_GameObject.h" #include "SND_SoundObject.h" #include "SND_Scene.h" // needed for replication +#include "KX_PyMath.h" // needed for PyObjectFrom() #include <iostream> #ifdef HAVE_CONFIG_H @@ -233,22 +234,22 @@ void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_SoundActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_SoundActuator", - sizeof(KX_SoundActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -264,104 +265,328 @@ PyParentObject KX_SoundActuator::Parents[] = { PyMethodDef KX_SoundActuator::Methods[] = { + // Deprecated -----> {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL}, - {"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_VARARGS,NULL}, - {"startSound",(PyCFunction) KX_SoundActuator::sPyStartSound,METH_VARARGS,NULL}, - {"pauseSound",(PyCFunction) KX_SoundActuator::sPyPauseSound,METH_VARARGS,NULL}, - {"stopSound",(PyCFunction) KX_SoundActuator::sPyStopSound,METH_VARARGS,NULL}, + {"getFilename", (PyCFunction) KX_SoundActuator::sPyGetFilename, METH_NOARGS,NULL}, {"setGain",(PyCFunction) KX_SoundActuator::sPySetGain,METH_VARARGS,NULL}, - {"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_VARARGS,NULL}, + {"getGain",(PyCFunction) KX_SoundActuator::sPyGetGain,METH_NOARGS,NULL}, {"setPitch",(PyCFunction) KX_SoundActuator::sPySetPitch,METH_VARARGS,NULL}, - {"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_VARARGS,NULL}, + {"getPitch",(PyCFunction) KX_SoundActuator::sPyGetPitch,METH_NOARGS,NULL}, {"setRollOffFactor",(PyCFunction) KX_SoundActuator::sPySetRollOffFactor,METH_VARARGS,NULL}, - {"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_VARARGS,NULL}, + {"getRollOffFactor",(PyCFunction) KX_SoundActuator::sPyGetRollOffFactor,METH_NOARGS,NULL}, {"setLooping",(PyCFunction) KX_SoundActuator::sPySetLooping,METH_VARARGS,NULL}, - {"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_VARARGS,NULL}, + {"getLooping",(PyCFunction) KX_SoundActuator::sPyGetLooping,METH_NOARGS,NULL}, {"setPosition",(PyCFunction) KX_SoundActuator::sPySetPosition,METH_VARARGS,NULL}, {"setVelocity",(PyCFunction) KX_SoundActuator::sPySetVelocity,METH_VARARGS,NULL}, {"setOrientation",(PyCFunction) KX_SoundActuator::sPySetOrientation,METH_VARARGS,NULL}, {"setType",(PyCFunction) KX_SoundActuator::sPySetType,METH_VARARGS,NULL}, - {"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_VARARGS,NULL}, + {"getType",(PyCFunction) KX_SoundActuator::sPyGetType,METH_NOARGS,NULL}, + // <----- + + KX_PYMETHODTABLE_NOARGS(KX_SoundActuator, startSound), + KX_PYMETHODTABLE_NOARGS(KX_SoundActuator, pauseSound), + KX_PYMETHODTABLE_NOARGS(KX_SoundActuator, stopSound), {NULL,NULL,NULL,NULL} //Sentinel }; PyAttributeDef KX_SoundActuator::Attributes[] = { + KX_PYATTRIBUTE_RW_FUNCTION("filename", KX_SoundActuator, pyattr_get_filename, pyattr_set_filename), + KX_PYATTRIBUTE_RW_FUNCTION("volume", KX_SoundActuator, pyattr_get_gain, pyattr_set_gain), + KX_PYATTRIBUTE_RW_FUNCTION("pitch", KX_SoundActuator, pyattr_get_pitch, pyattr_set_pitch), + KX_PYATTRIBUTE_RW_FUNCTION("rollOffFactor", KX_SoundActuator, pyattr_get_rollOffFactor, pyattr_set_rollOffFactor), + KX_PYATTRIBUTE_RW_FUNCTION("looping", KX_SoundActuator, pyattr_get_looping, pyattr_set_looping), + KX_PYATTRIBUTE_RW_FUNCTION("position", KX_SoundActuator, pyattr_get_position, pyattr_set_position), + KX_PYATTRIBUTE_RW_FUNCTION("velocity", KX_SoundActuator, pyattr_get_velocity, pyattr_set_velocity), + KX_PYATTRIBUTE_RW_FUNCTION("orientation", KX_SoundActuator, pyattr_get_orientation, pyattr_set_orientation), + KX_PYATTRIBUTE_ENUM_RW("type",KX_SoundActuator::KX_SOUNDACT_NODEF+1,KX_SoundActuator::KX_SOUNDACT_MAX-1,false,KX_SoundActuator,m_type), { NULL } //Sentinel }; -PyObject* KX_SoundActuator::_getattr(const char *attr) +/* Methods ----------------------------------------------------------------- */ +KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound, +"startSound()\n" +"\tStarts the sound.\n") { - _getattr_up(SCA_IActuator); -} - - + if (m_soundObject) + // This has no effect if the actuator is not active. + // To start the sound you must activate the actuator. + // This function is to restart the sound. + m_soundObject->StartSound(); + Py_RETURN_NONE; +} -PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObject* kwds) +KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound, +"pauseSound()\n" +"\tPauses the sound.\n") { - char *soundName = NULL; - // void *soundPointer = NULL; /*unused*/ - - if (!PyArg_ParseTuple(args, "s", &soundName)) - return NULL; + if (m_soundObject) + // unfortunately, openal does not implement pause correctly, it is equivalent to a stop + m_soundObject->PauseSound(); + Py_RETURN_NONE; +} +KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, +"stopSound()\n" +"\tStops the sound.\n") +{ + if (m_soundObject) + m_soundObject->StopSound(); Py_RETURN_NONE; } +/* Atribute setting and getting -------------------------------------------- */ +PyObject* KX_SoundActuator::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_IActuator); +} +int KX_SoundActuator::py_setattro(PyObject *attr, PyObject* value) { + py_setattro_up(SCA_IActuator); +} -PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { - if (!m_soundObject) + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + if (!actuator->m_soundObject) { return PyString_FromString(""); } - STR_String objectname = m_soundObject->GetObjectName(); + STR_String objectname = actuator->m_soundObject->GetObjectName(); char* name = objectname.Ptr(); if (!name) { - PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename"); + PyErr_SetString(PyExc_RuntimeError, "value = actuator.filename: KX_SoundActuator, unable to get sound filename"); return NULL; } else return PyString_FromString(name); } +PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + float gain = (actuator->m_soundObject) ? actuator->m_soundObject->GetGain() : 1.0f; + PyObject* result = PyFloat_FromDouble(gain); + + return result; +} -PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { - if (m_soundObject) - // This has no effect if the actuator is not active. - // To start the sound you must activate the actuator. - // This function is to restart the sound. - m_soundObject->StartSound(); - Py_RETURN_NONE; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + float pitch = (actuator->m_soundObject) ? actuator->m_soundObject->GetPitch() : 1.0; + PyObject* result = PyFloat_FromDouble(pitch); + + return result; +} + +PyObject* KX_SoundActuator::pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + float rollofffactor = (actuator->m_soundObject) ? actuator->m_soundObject->GetRollOffFactor() : 1.0; + PyObject* result = PyFloat_FromDouble(rollofffactor); + + return result; +} + +PyObject* KX_SoundActuator::pyattr_get_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + int looping = (actuator->m_soundObject) ? actuator->m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; + PyObject* result = PyInt_FromLong(looping); + + return result; +} + +PyObject* KX_SoundActuator::pyattr_get_position(void * self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + MT_Vector3 pos(0.0, 0.0, 0.0); + + if (actuator->m_soundObject) + pos = actuator->m_soundObject->GetPosition(); + + PyObject * result = PyObjectFrom(pos); + return result; +} + +PyObject* KX_SoundActuator::pyattr_get_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + MT_Vector3 vel; + + if (actuator->m_soundObject) + vel = actuator->m_soundObject->GetVelocity(); + + PyObject * result = PyObjectFrom(vel); + return result; +} + +PyObject* KX_SoundActuator::pyattr_get_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + MT_Matrix3x3 ori; + + if (actuator->m_soundObject) + ori = actuator->m_soundObject->GetOrientation(); + + PyObject * result = PyObjectFrom(ori); + return result; +} + +int KX_SoundActuator::pyattr_set_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + char *soundName = NULL; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator*> (self); + // void *soundPointer = NULL; /*unused*/ + + if (!PyArg_Parse(value, "s", &soundName)) + return 1; + + if (actuator->m_soundObject) { + actuator->m_soundObject->SetObjectName(soundName); + } + + return 0; +} + + +int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + float gain = 1.0; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + if (!PyArg_Parse(value, "f", &gain)) + return 1; + + if (actuator->m_soundObject) + actuator->m_soundObject->SetGain(gain); + + return 0; } +int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + float pitch = 1.0; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + if (!PyArg_Parse(value, "f", &pitch)) + return 1; + + if (actuator->m_soundObject) + actuator->m_soundObject->SetPitch(pitch); + + return 0; +} +int KX_SoundActuator::pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + float rollofffactor = 1.0; + if (!PyArg_Parse(value, "f", &rollofffactor)) + return 1; + + if (actuator->m_soundObject) + actuator->m_soundObject->SetRollOffFactor(rollofffactor); -PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds) + return 0; +} + +int KX_SoundActuator::pyattr_set_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - if (m_soundObject) - // unfortunately, openal does not implement pause correctly, it is equivalent to a stop - m_soundObject->PauseSound(); - Py_RETURN_NONE; -} + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + int looping = 1; + if (!PyArg_Parse(value, "i", &looping)) + return 1; + + if (actuator->m_soundObject) + actuator->m_soundObject->SetLoopMode(looping); + + return 0; +} +int KX_SoundActuator::pyattr_set_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + float pos[3]; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); -PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds) + if (!PyArg_ParseTuple(value, "fff", &pos[0], &pos[1], &pos[2])) + return 1; + + if (actuator->m_soundObject) + actuator->m_soundObject->SetPosition(MT_Vector3(pos)); + + return 0; +} + +int KX_SoundActuator::pyattr_set_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - if (m_soundObject) - m_soundObject->StopSound(); - Py_RETURN_NONE; + float vel[3]; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + + + if (!PyArg_ParseTuple(value, "fff", &vel[0], &vel[1], &vel[2])) + return 1; + + if (actuator->m_soundObject) + actuator->m_soundObject->SetVelocity(MT_Vector3(vel)); + + return 0; + +} + +int KX_SoundActuator::pyattr_set_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + + MT_Matrix3x3 rot; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + + /* if value is not a sequence PyOrientationTo makes an error */ + if (!PyOrientationTo(value, rot, "actuator.orientation = value: KX_SoundActuator")) + return NULL; + + if (!actuator->m_soundObject) + return 0; /* Since not having m_soundObject didn't do anything in the old version, + * it probably should be kept that way */ + + actuator->m_soundObject->SetOrientation(rot); + return 0; } +// Deprecated -----> +PyObject* KX_SoundActuator::PySetFilename(PyObject* args) +{ + char *soundName = NULL; + ShowDeprecationWarning("setFilename()", "the filename property"); + // void *soundPointer = NULL; /*unused*/ + + if (!PyArg_ParseTuple(args, "s", &soundName)) + return NULL; + Py_RETURN_NONE; +} -PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PyGetFilename() { + ShowDeprecationWarning("getFilename()", "the filename property"); + if (!m_soundObject) + { + return PyString_FromString(""); + } + STR_String objectname = m_soundObject->GetObjectName(); + char* name = objectname.Ptr(); + + if (!name) { + PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename"); + return NULL; + } else + return PyString_FromString(name); +} + +PyObject* KX_SoundActuator::PySetGain(PyObject* args) +{ + ShowDeprecationWarning("setGain()", "the volume property"); float gain = 1.0; - if (!PyArg_ParseTuple(args, "f", &gain)) + if (!PyArg_ParseTuple(args, "f:setGain", &gain)) return NULL; if (m_soundObject) @@ -372,8 +597,9 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* -PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PyGetGain() { + ShowDeprecationWarning("getGain()", "the volume property"); float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f; PyObject* result = PyFloat_FromDouble(gain); @@ -382,10 +608,11 @@ PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* -PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetPitch(PyObject* args) { + ShowDeprecationWarning("setPitch()", "the pitch property"); float pitch = 1.0; - if (!PyArg_ParseTuple(args, "f", &pitch)) + if (!PyArg_ParseTuple(args, "f:setPitch", &pitch)) return NULL; if (m_soundObject) @@ -396,8 +623,9 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* -PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PyGetPitch() { + ShowDeprecationWarning("getPitch()", "the pitch property"); float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0; PyObject* result = PyFloat_FromDouble(pitch); @@ -406,10 +634,11 @@ PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* -PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* args) { + ShowDeprecationWarning("setRollOffFactor()", "the rollOffFactor property"); float rollofffactor = 1.0; - if (!PyArg_ParseTuple(args, "f", &rollofffactor)) + if (!PyArg_ParseTuple(args, "f:setRollOffFactor", &rollofffactor)) return NULL; if (m_soundObject) @@ -420,8 +649,9 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P -PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PyGetRollOffFactor() { + ShowDeprecationWarning("getRollOffFactor()", "the rollOffFactor property"); float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0; PyObject* result = PyFloat_FromDouble(rollofffactor); @@ -430,10 +660,11 @@ PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, P -PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetLooping(PyObject* args) { + ShowDeprecationWarning("setLooping()", "the looping property"); bool looping = 1; - if (!PyArg_ParseTuple(args, "i", &looping)) + if (!PyArg_ParseTuple(args, "i:setLooping", &looping)) return NULL; if (m_soundObject) @@ -444,8 +675,9 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec -PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PyGetLooping() { + ShowDeprecationWarning("getLooping()", "the looping property"); int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; PyObject* result = PyInt_FromLong(looping); @@ -454,14 +686,15 @@ PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObjec -PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetPosition(PyObject* args) { MT_Point3 pos; + ShowDeprecationWarning("setPosition()", "the position property"); pos[0] = 0.0; pos[1] = 0.0; pos[2] = 0.0; - if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2])) + if (!PyArg_ParseTuple(args, "fff:setPosition", &pos[0], &pos[1], &pos[2])) return NULL; if (m_soundObject) @@ -472,14 +705,15 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje -PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetVelocity(PyObject* args) { MT_Vector3 vel; + ShowDeprecationWarning("setVelocity()", "the velocity property"); vel[0] = 0.0; vel[1] = 0.0; vel[2] = 0.0; - if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2])) + if (!PyArg_ParseTuple(args, "fff:setVelocity", &vel[0], &vel[1], &vel[2])) return NULL; if (m_soundObject) @@ -490,9 +724,10 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje -PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetOrientation(PyObject* args) { MT_Matrix3x3 ori; + ShowDeprecationWarning("setOrientation()", "the orientation property"); ori[0][0] = 1.0; ori[0][1] = 0.0; ori[0][2] = 0.0; @@ -503,7 +738,7 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO ori[2][1] = 0.0; ori[2][2] = 1.0; - if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2])) + if (!PyArg_ParseTuple(args, "fffffffff:setOrientation", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2])) return NULL; if (m_soundObject) @@ -512,11 +747,12 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO Py_RETURN_NONE; } -PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PySetType(PyObject* args) { int typeArg; + ShowDeprecationWarning("setType()", "the type property"); - if (!PyArg_ParseTuple(args, "i", &typeArg)) { + if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) { return NULL; } @@ -528,10 +764,10 @@ PyObject* KX_SoundActuator::PySetType(PyObject* self, PyObject* args, PyObject* Py_RETURN_NONE; } -PyObject* KX_SoundActuator::PyGetType(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_SoundActuator::PyGetType() { + ShowDeprecationWarning("getType()", "the type property"); return PyInt_FromLong(m_type); } - - +// <----- diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 68d5b792729..d5e678bbecd 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -80,26 +80,51 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); - - KX_PYMETHOD(KX_SoundActuator,SetFilename); - KX_PYMETHOD(KX_SoundActuator,GetFilename); - KX_PYMETHOD(KX_SoundActuator,StartSound); - KX_PYMETHOD(KX_SoundActuator,PauseSound); - KX_PYMETHOD(KX_SoundActuator,StopSound); - KX_PYMETHOD(KX_SoundActuator,SetGain); - KX_PYMETHOD(KX_SoundActuator,GetGain); - KX_PYMETHOD(KX_SoundActuator,SetPitch); - KX_PYMETHOD(KX_SoundActuator,GetPitch); - KX_PYMETHOD(KX_SoundActuator,SetRollOffFactor); - KX_PYMETHOD(KX_SoundActuator,GetRollOffFactor); - KX_PYMETHOD(KX_SoundActuator,SetLooping); - KX_PYMETHOD(KX_SoundActuator,GetLooping); - KX_PYMETHOD(KX_SoundActuator,SetPosition); - KX_PYMETHOD(KX_SoundActuator,SetVelocity); - KX_PYMETHOD(KX_SoundActuator,SetOrientation); - KX_PYMETHOD(KX_SoundActuator,SetType); - KX_PYMETHOD(KX_SoundActuator,GetType); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); + + KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, startSound); + KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, pauseSound); + KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, stopSound); + + static int pyattr_set_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + + static PyObject* pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_orientation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + + // Deprecated -----> + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetFilename); + KX_PYMETHOD_NOARGS(KX_SoundActuator,GetFilename); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetGain); + KX_PYMETHOD_NOARGS(KX_SoundActuator,GetGain); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetPitch); + KX_PYMETHOD_NOARGS(KX_SoundActuator,GetPitch); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetRollOffFactor); + KX_PYMETHOD_NOARGS(KX_SoundActuator,GetRollOffFactor); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetLooping); + KX_PYMETHOD_NOARGS(KX_SoundActuator,GetLooping); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetPosition); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetVelocity); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetOrientation); + KX_PYMETHOD_VARARGS(KX_SoundActuator,SetType); + KX_PYMETHOD_NOARGS(KX_SoundActuator,GetType); + // <----- + }; #endif //__KX_SOUNDACTUATOR diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index 0de4da79bd8..976e7ea5204 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -108,24 +108,23 @@ KX_StateActuator::Update() /* Integration hooks ------------------------------------------------------- */ -PyTypeObject -KX_StateActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) +PyTypeObject KX_StateActuator::Type = { + PyObject_HEAD_INIT(NULL) 0, "KX_StateActuator", - sizeof(KX_StateActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject @@ -139,22 +138,30 @@ KX_StateActuator::Parents[] = { PyMethodDef KX_StateActuator::Methods[] = { + // deprecated --> {"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation, METH_VARARGS, (PY_METHODCHAR)SetOperation_doc}, {"setMask", (PyCFunction) KX_StateActuator::sPySetMask, METH_VARARGS, (PY_METHODCHAR)SetMask_doc}, + // <-- {NULL,NULL} //Sentinel }; PyAttributeDef KX_StateActuator::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("operation",KX_StateActuator::OP_NOP+1,KX_StateActuator::OP_COUNT-1,false,KX_StateActuator,m_operation), + KX_PYATTRIBUTE_INT_RW("mask",0,0x3FFFFFFF,false,KX_StateActuator,m_mask), { NULL } //Sentinel }; -PyObject* KX_StateActuator::_getattr(const char *attr) +PyObject* KX_StateActuator::py_getattro(PyObject *attr) { - _getattr_up(SCA_IActuator); + py_getattro_up(SCA_IActuator); }; +int KX_StateActuator::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IActuator); +} /* set operation ---------------------------------------------------------- */ @@ -166,12 +173,11 @@ KX_StateActuator::SetOperation_doc[] = "\tUse setMask() to specify the bits that will be modified.\n"; PyObject* -KX_StateActuator::PySetOperation(PyObject* self, - PyObject* args, - PyObject* kwds) { +KX_StateActuator::PySetOperation(PyObject* args) { + ShowDeprecationWarning("setOperation()", "the operation property"); int oper; - if(!PyArg_ParseTuple(args, "i", &oper)) { + if(!PyArg_ParseTuple(args, "i:setOperation", &oper)) { return NULL; } @@ -191,12 +197,11 @@ KX_StateActuator::SetMask_doc[] = "\twhich copies the value to the object state.\n"; PyObject* -KX_StateActuator::PySetMask(PyObject* self, - PyObject* args, - PyObject* kwds) { +KX_StateActuator::PySetMask(PyObject* args) { + ShowDeprecationWarning("setMask()", "the mask property"); int mask; - if(!PyArg_ParseTuple(args, "i", &mask)) { + if(!PyArg_ParseTuple(args, "i:setMask", &mask)) { return NULL; } diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h index 023b8993d7c..4a64894259d 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.h +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -39,13 +39,15 @@ class KX_StateActuator : public SCA_IActuator /** Make visible? */ enum { + OP_NOP = -1, OP_CPY = 0, OP_SET, OP_CLR, - OP_NEG + OP_NEG, + OP_COUNT }; int m_operation; - unsigned int m_mask; + int m_mask; public: @@ -73,10 +75,11 @@ class KX_StateActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); //KX_PYMETHOD_DOC - KX_PYMETHOD_DOC(KX_StateActuator,SetOperation); - KX_PYMETHOD_DOC(KX_StateActuator,SetMask); + KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetOperation); + KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetMask); }; #endif diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp index 7631ee05b0b..fc053f05e63 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp @@ -209,6 +209,11 @@ void KX_SumoPhysicsController::SetMass(MT_Scalar newmass) { } +MT_Vector3 KX_SumoPhysicsController::GetLocalInertia() +{ + return MT_Vector3(0.f, 0.f, 0.f); // \todo +} + MT_Scalar KX_SumoPhysicsController::GetRadius() { return SumoPhysicsController::GetRadius(); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index 46c8ba6df45..083d89896f6 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -88,10 +88,15 @@ public: virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); virtual void SetMass(MT_Scalar newmass); + virtual MT_Vector3 GetLocalInertia(); virtual MT_Scalar GetRadius(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); + virtual float GetLinVelocityMin() { return SumoPhysicsController::GetLinVelocityMin(); } + virtual void SetLinVelocityMin(float val) { SumoPhysicsController::SetLinVelocityMin(val); } + virtual float GetLinVelocityMax() { return SumoPhysicsController::GetLinVelocityMax(); } + virtual void SetLinVelocityMax(float val) { SumoPhysicsController::SetLinVelocityMax(val); } virtual SG_Controller* GetReplica(class SG_Node* destnode); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 705b54edd37..5a6e8e6f501 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -242,22 +242,22 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll /* ------------------------------------------------------------------------- */ /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_TouchSensor::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_TouchSensor", - sizeof(KX_TouchSensor), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_TouchSensor::Parents[] = { @@ -286,34 +286,19 @@ PyAttributeDef KX_TouchSensor::Attributes[] = { KX_PYATTRIBUTE_STRING_RW("property",0,100,false,KX_TouchSensor,m_touchedpropname), KX_PYATTRIBUTE_BOOL_RW("useMaterial",KX_TouchSensor,m_bFindMaterial), KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse), - KX_PYATTRIBUTE_DUMMY("objectHit"), - KX_PYATTRIBUTE_DUMMY("objectHitList"), + KX_PYATTRIBUTE_RO_FUNCTION("objectHit", KX_TouchSensor, pyattr_get_object_hit), + KX_PYATTRIBUTE_RO_FUNCTION("objectHitList", KX_TouchSensor, pyattr_get_object_hit_list), { NULL } //Sentinel }; -PyObject* KX_TouchSensor::_getattr(const char *attr) -{ - if (!strcmp(attr, "objectHit")) { - if (m_hitObject) return m_hitObject->AddRef(); - else Py_RETURN_NONE; - } - if (!strcmp(attr, "objectHitList")) { - return m_colliders->AddRef(); - } - - PyObject* object= _getattr_self(Attributes, this, attr); - if (object != NULL) - return object; - _getattr_up(SCA_ISensor); +PyObject* KX_TouchSensor::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_ISensor); } -int KX_TouchSensor::_setattr(const char *attr, PyObject *value) +int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value) { - int ret = _setattr_self(Attributes, this, attr, value); - if (ret >= 0) - return ret; - - return SCA_ISensor::_setattr(attr, value); + py_setattro_up(SCA_ISensor); } /* Python API */ @@ -325,7 +310,7 @@ const char KX_TouchSensor::SetProperty_doc[] = "\tSet the property or material to collide with. Use\n" "\tsetTouchMaterial() to switch between properties and\n" "\tmaterials."; -PyObject* KX_TouchSensor::PySetProperty(PyObject* self, PyObject* value) +PyObject* KX_TouchSensor::PySetProperty(PyObject* value) { ShowDeprecationWarning("setProperty()", "the propertyName property"); char *nameArg= PyString_AsString(value); @@ -343,21 +328,21 @@ const char KX_TouchSensor::GetProperty_doc[] = "\tReturns the property or material to collide with. Use\n" "\tgetTouchMaterial() to find out whether this sensor\n" "\tlooks for properties or materials."; -PyObject* KX_TouchSensor::PyGetProperty(PyObject* self) { +PyObject* KX_TouchSensor::PyGetProperty() { return PyString_FromString(m_touchedpropname); } const char KX_TouchSensor::GetHitObject_doc[] = "getHitObject()\n" ; -PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self) +PyObject* KX_TouchSensor::PyGetHitObject() { ShowDeprecationWarning("getHitObject()", "the objectHit property"); /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ if (m_hitObject) { - return m_hitObject->AddRef(); + return m_hitObject->GetProxy(); } Py_RETURN_NONE; } @@ -366,12 +351,12 @@ const char KX_TouchSensor::GetHitObjectList_doc[] = "getHitObjectList()\n" "\tReturn a list of the objects this object collided with,\n" "\tbut only those matching the property/material condition.\n"; -PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self) +PyObject* KX_TouchSensor::PyGetHitObjectList() { ShowDeprecationWarning("getHitObjectList()", "the objectHitList property"); /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ /* Edit, this seems ok and not to leak memory - Campbell */ - return m_colliders->AddRef(); + return m_colliders->GetProxy(); } /*getTouchMaterial and setTouchMaterial were never added to the api, @@ -382,9 +367,9 @@ const char KX_TouchSensor::GetTouchMaterial_doc[] = "getTouchMaterial()\n" "\tReturns KX_TRUE if this sensor looks for a specific material,\n" "\tKX_FALSE if it looks for a specific property.\n" ; -PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self) +PyObject* KX_TouchSensor::PyGetTouchMaterial() { - ShowDeprecationWarning("getTouchMaterial()", "the materialCheck property"); + ShowDeprecationWarning("getTouchMaterial()", "the useMaterial property"); return PyInt_FromLong(m_bFindMaterial); } @@ -395,8 +380,9 @@ const char KX_TouchSensor::SetTouchMaterial_doc[] = "\t- flag: KX_TRUE or KX_FALSE.\n" "\tSet flag to KX_TRUE to switch on positive pulse mode,\n" "\tKX_FALSE to switch off positive pulse mode.\n" ; -PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject *value) +PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject *value) { + ShowDeprecationWarning("setTouchMaterial()", "the useMaterial property"); int pulseArg = PyInt_AsLong(value); if(pulseArg ==-1 && PyErr_Occurred()) { @@ -410,4 +396,21 @@ PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject *value) } #endif +PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v); + + if (self->m_hitObject) + return self->m_hitObject->GetProxy(); + else + Py_RETURN_NONE; +} + +PyObject* KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v); + return self->m_colliders->GetProxy(); +} + + /* eof */ diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 18ce9406a9b..15ef653c1b2 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -120,8 +120,8 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated -----> /* 1. setProperty */ @@ -140,6 +140,10 @@ public: #endif //<----- + static PyObject* pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + }; #endif //__KX_TOUCHSENSOR diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 8637bc92d39..fbf43de6cf4 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -402,7 +402,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) // set the models tranformation properties curobj->NodeSetLocalOrientation(mat); curobj->NodeSetLocalPosition(localpos); - curobj->UpdateTransform(); + //curobj->UpdateTransform(); } else { @@ -425,22 +425,22 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_TrackToActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_TrackToActuator", - sizeof(KX_TrackToActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; @@ -456,12 +456,11 @@ PyParentObject KX_TrackToActuator::Parents[] = { PyMethodDef KX_TrackToActuator::Methods[] = { + // ---> deprecated {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc}, - {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, (PY_METHODCHAR)GetTime_doc}, + {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc}, {"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, (PY_METHODCHAR)SetUse3D_doc}, - {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, (PY_METHODCHAR)GetUse3D_doc}, - - // ---> deprecated + {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_NOARGS, (PY_METHODCHAR)GetUse3D_doc}, {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc}, {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc}, @@ -469,40 +468,50 @@ PyMethodDef KX_TrackToActuator::Methods[] = { }; PyAttributeDef KX_TrackToActuator::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_TrackToActuator,m_time), + KX_PYATTRIBUTE_BOOL_RW("use3D",KX_TrackToActuator,m_allow3D), + KX_PYATTRIBUTE_RW_FUNCTION("object", KX_TrackToActuator, pyattr_get_object, pyattr_set_object), + { NULL } //Sentinel }; - -PyObject* KX_TrackToActuator::_getattr(const char *attr) +PyObject* KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { - if (!strcmp(attr, "object")) { - if (!m_object) Py_RETURN_NONE; - else return m_object->AddRef(); - } - - _getattr_up(SCA_IActuator); + KX_TrackToActuator* actuator = static_cast<KX_TrackToActuator*>(self); + if (!actuator->m_object) + Py_RETURN_NONE; + else + return actuator->m_object->GetProxy(); } -int KX_TrackToActuator::_setattr(const char *attr, PyObject* value) +int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - if (!strcmp(attr, "object")) { - KX_GameObject *gameobj; + KX_TrackToActuator* actuator = static_cast<KX_TrackToActuator*>(self); + KX_GameObject *gameobj; - if (!ConvertPythonToGameObject(value, &gameobj, true)) - return 1; // ConvertPythonToGameObject sets the error + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_TrackToActuator")) + return 1; // ConvertPythonToGameObject sets the error - if (m_object != NULL) - m_object->UnregisterActuator(this); + if (actuator->m_object != NULL) + actuator->m_object->UnregisterActuator(actuator); - m_object = (SCA_IObject*)gameobj; + actuator->m_object = (SCA_IObject*) gameobj; - if (m_object) - m_object->RegisterActuator(this); + if (actuator->m_object) + actuator->m_object->RegisterActuator(actuator); - return 0; - } - - return SCA_IActuator::_setattr(attr, value); + return 0; +} + + +PyObject* KX_TrackToActuator::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_IActuator); +} + +int KX_TrackToActuator::py_setattro(PyObject *attr, PyObject* value) +{ + py_setattro_up(SCA_IActuator); } /* 1. setObject */ @@ -510,13 +519,13 @@ const char KX_TrackToActuator::SetObject_doc[] = "setObject(object)\n" "\t- object: KX_GameObject, string or None\n" "\tSet the object to track with the parent of this actuator.\n"; -PyObject* KX_TrackToActuator::PySetObject(PyObject* self, PyObject* value) +PyObject* KX_TrackToActuator::PySetObject(PyObject* value) { KX_GameObject *gameobj; ShowDeprecationWarning("setObject()", "the object property"); - if (!ConvertPythonToGameObject(value, &gameobj, true)) + if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.setObject(value): KX_TrackToActuator")) return NULL; // ConvertPythonToGameObject sets the error if (m_object != NULL) @@ -536,13 +545,13 @@ const char KX_TrackToActuator::GetObject_doc[] = "getObject(name_only = 1)\n" "name_only - optional arg, when true will return the KX_GameObject rather then its name\n" "\tReturns the object to track with the parent of this actuator\n"; -PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args) +PyObject* KX_TrackToActuator::PyGetObject(PyObject* args) { int ret_name_only = 1; ShowDeprecationWarning("getObject()", "the object property"); - if (!PyArg_ParseTuple(args, "|i", &ret_name_only)) + if (!PyArg_ParseTuple(args, "|i:getObject", &ret_name_only)) return NULL; if (!m_object) @@ -551,7 +560,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_object->GetName()); else - return m_object->AddRef(); + return m_object->GetProxy(); } @@ -561,11 +570,12 @@ const char KX_TrackToActuator::SetTime_doc[] = "setTime(time)\n" "\t- time: integer\n" "\tSet the time in frames with which to delay the tracking motion.\n"; -PyObject* KX_TrackToActuator::PySetTime(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_TrackToActuator::PySetTime(PyObject* args) { + ShowDeprecationWarning("setTime()", "the timer property"); int timeArg; - if (!PyArg_ParseTuple(args, "i", &timeArg)) + if (!PyArg_ParseTuple(args, "i:setTime", &timeArg)) { return NULL; } @@ -582,8 +592,9 @@ const char KX_TrackToActuator::GetTime_doc[] = "getTime()\n" "\t- time: integer\n" "\tReturn the time in frames with which the tracking motion is delayed.\n"; -PyObject* KX_TrackToActuator::PyGetTime(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_TrackToActuator::PyGetTime() { + ShowDeprecationWarning("getTime()", "the timer property"); return PyInt_FromLong(m_time); } @@ -593,8 +604,9 @@ PyObject* KX_TrackToActuator::PyGetTime(PyObject* self, PyObject* args, PyObject const char KX_TrackToActuator::GetUse3D_doc[] = "getUse3D()\n" "\tReturns 1 if the motion is allowed to extend in the z-direction.\n"; -PyObject* KX_TrackToActuator::PyGetUse3D(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_TrackToActuator::PyGetUse3D() { + ShowDeprecationWarning("setTime()", "the use3D property"); return PyInt_FromLong(!(m_allow3D == 0)); } @@ -606,11 +618,12 @@ const char KX_TrackToActuator::SetUse3D_doc[] = "\t- value: 0 or 1\n" "\tSet to 1 to allow the tracking motion to extend in the z-direction,\n" "\tset to 0 to lock the tracking motion to the x-y plane.\n"; -PyObject* KX_TrackToActuator::PySetUse3D(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* KX_TrackToActuator::PySetUse3D(PyObject* args) { + ShowDeprecationWarning("setTime()", "the use3D property"); int boolArg; - if (!PyArg_ParseTuple(args, "i", &boolArg)) { + if (!PyArg_ParseTuple(args, "i:setUse3D", &boolArg)) { return NULL; } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index 392e55402f1..99505f93cfe 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -72,21 +72,25 @@ class KX_TrackToActuator : public SCA_IActuator virtual bool Update(double curtime, bool frame); /* Python part */ - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject* value); - + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject* value); + + /* These are used to get and set m_ob */ + static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_TrackToActuator,SetObject); /* 2. getObject */ KX_PYMETHOD_DOC_VARARGS(KX_TrackToActuator,GetObject); /* 3. setTime */ - KX_PYMETHOD_DOC(KX_TrackToActuator,SetTime); + KX_PYMETHOD_DOC_VARARGS(KX_TrackToActuator,SetTime); /* 4. getTime */ - KX_PYMETHOD_DOC(KX_TrackToActuator,GetTime); + KX_PYMETHOD_DOC_NOARGS(KX_TrackToActuator,GetTime); /* 5. getUse3D */ - KX_PYMETHOD_DOC(KX_TrackToActuator,GetUse3D); + KX_PYMETHOD_DOC_NOARGS(KX_TrackToActuator,GetUse3D); /* 6. setUse3D */ - KX_PYMETHOD_DOC(KX_TrackToActuator,SetUse3D); + KX_PYMETHOD_DOC_VARARGS(KX_TrackToActuator,SetUse3D); }; /* end of class KX_TrackToActuator : public KX_EditObjectActuator */ diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 8d5af1b9216..1a6fb196db5 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -35,9 +35,7 @@ KX_VehicleWrapper::~KX_VehicleWrapper() } -PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args) { PyObject* pylistPos,*pylistDir,*pylistAxleDir; @@ -46,14 +44,18 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self, int hasSteering; - if (PyArg_ParseTuple(args,"OOOOffi",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering)) + if (PyArg_ParseTuple(args,"OOOOffi:addWheel",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering)) { - KX_GameObject* gameOb = (KX_GameObject*) wheelGameObject; + KX_GameObject *gameOb; + if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)")) + return NULL; + if (gameOb->GetSGNode()) { PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); - + + /* TODO - no error checking here! - bad juju */ MT_Vector3 attachPos,attachDir,attachAxle; PyVecTo(pylistPos,attachPos); PyVecTo(pylistDir,attachDir); @@ -82,14 +84,12 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self, -PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* args) { int wheelIndex; - if (PyArg_ParseTuple(args,"i",&wheelIndex)) + if (PyArg_ParseTuple(args,"i:getWheelPosition",&wheelIndex)) { float position[3]; m_vehicle->GetWheelPosition(wheelIndex,position[0],position[1],position[2]); @@ -99,24 +99,20 @@ PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* self, return NULL; } -PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* args) { int wheelIndex; - if (PyArg_ParseTuple(args,"i",&wheelIndex)) + if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex)) { return PyFloat_FromDouble(m_vehicle->GetWheelRotation(wheelIndex)); } return NULL; } -PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args) { int wheelIndex; - if (PyArg_ParseTuple(args,"i",&wheelIndex)) + if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex)) { float orn[4]; m_vehicle->GetWheelOrientationQuaternion(wheelIndex,orn[0],orn[1],orn[2],orn[3]); @@ -129,31 +125,25 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* self, } -PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args) { return PyInt_FromLong(m_vehicle->GetNumWheels()); } -PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args) { return PyInt_FromLong(m_vehicle->GetUserConstraintId()); } -PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* args) { float force; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&force,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:applyEngineForce",&force,&wheelIndex)) { force *= -1.f;//someone reverse some conventions inside Bullet (axle winding) m_vehicle->ApplyEngineForce(force,wheelIndex); @@ -164,14 +154,12 @@ PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* args) { float wheelFriction; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&wheelFriction,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:setTyreFriction",&wheelFriction,&wheelIndex)) { m_vehicle->SetWheelFriction(wheelFriction,wheelIndex); } @@ -181,14 +169,12 @@ PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* args) { float suspensionStiffness; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&suspensionStiffness,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:setSuspensionStiffness",&suspensionStiffness,&wheelIndex)) { m_vehicle->SetSuspensionStiffness(suspensionStiffness,wheelIndex); } @@ -198,14 +184,12 @@ PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* args) { float suspensionDamping; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&suspensionDamping,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:setSuspensionDamping",&suspensionDamping,&wheelIndex)) { m_vehicle->SetSuspensionDamping(suspensionDamping,wheelIndex); } else { @@ -214,14 +198,12 @@ PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* args) { float suspensionCompression; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&suspensionCompression,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:setSuspensionCompression",&suspensionCompression,&wheelIndex)) { m_vehicle->SetSuspensionCompression(suspensionCompression,wheelIndex); } else { @@ -230,14 +212,12 @@ PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* self, Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* args) { float rollInfluence; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&rollInfluence,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:setRollInfluence",&rollInfluence,&wheelIndex)) { m_vehicle->SetRollInfluence(rollInfluence,wheelIndex); } @@ -248,14 +228,12 @@ PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* self, } -PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* args) { float braking; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&braking,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:applyBraking",&braking,&wheelIndex)) { m_vehicle->ApplyBraking(braking,wheelIndex); } @@ -268,14 +246,12 @@ PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* self, -PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args) { float steeringValue; int wheelIndex; - if (PyArg_ParseTuple(args,"fi",&steeringValue,&wheelIndex)) + if (PyArg_ParseTuple(args,"fi:setSteeringValue",&steeringValue,&wheelIndex)) { m_vehicle->SetSteeringValue(steeringValue,wheelIndex); } @@ -286,9 +262,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* self, } -PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args) { return PyInt_FromLong(m_vehicle->GetUserConstraintType()); } @@ -299,38 +273,39 @@ PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* self, //python specific stuff PyTypeObject KX_VehicleWrapper::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_VehicleWrapper", - sizeof(KX_VehicleWrapper), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_VehicleWrapper::Parents[] = { &KX_VehicleWrapper::Type, + &PyObjectPlus::Type, NULL }; -PyObject* KX_VehicleWrapper::_getattr(const char *attr) +PyObject* KX_VehicleWrapper::py_getattro(PyObject *attr) { //here you can search for existing data members (like mass,friction etc.) - _getattr_up(PyObjectPlus); + py_getattro_up(PyObjectPlus); } -int KX_VehicleWrapper::_setattr(const char *attr,PyObject* pyobj) +int KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* pyobj) { - + /* TODO - strange setattr, needs updating */ PyTypeObject* type = pyobj->ob_type; int result = 1; @@ -352,7 +327,7 @@ int KX_VehicleWrapper::_setattr(const char *attr,PyObject* pyobj) result = 0; } if (result) - result = PyObjectPlus::_setattr(attr,pyobj); + result = PyObjectPlus::py_setattro(attr,pyobj); return result; }; diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index cad926ce85a..de7fe75cfba 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -12,8 +12,8 @@ class PHY_IMotionState; class KX_VehicleWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *value); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); std::vector<PHY_IMotionState*> m_motionStates; @@ -23,31 +23,31 @@ public: int getConstraintId(); - KX_PYMETHOD(KX_VehicleWrapper,AddWheel); - KX_PYMETHOD(KX_VehicleWrapper,GetNumWheels); - KX_PYMETHOD(KX_VehicleWrapper,GetWheelOrientationQuaternion); - KX_PYMETHOD(KX_VehicleWrapper,GetWheelRotation); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,AddWheel); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetNumWheels); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetWheelOrientationQuaternion); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetWheelRotation); - KX_PYMETHOD(KX_VehicleWrapper,GetWheelPosition); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetWheelPosition); - KX_PYMETHOD(KX_VehicleWrapper,GetConstraintId); - KX_PYMETHOD(KX_VehicleWrapper,GetConstraintType); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetConstraintId); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,GetConstraintType); - KX_PYMETHOD(KX_VehicleWrapper,SetSteeringValue); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSteeringValue); - KX_PYMETHOD(KX_VehicleWrapper,ApplyEngineForce); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,ApplyEngineForce); - KX_PYMETHOD(KX_VehicleWrapper,ApplyBraking); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,ApplyBraking); - KX_PYMETHOD(KX_VehicleWrapper,SetTyreFriction); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetTyreFriction); - KX_PYMETHOD(KX_VehicleWrapper,SetSuspensionStiffness); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionStiffness); - KX_PYMETHOD(KX_VehicleWrapper,SetSuspensionDamping); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionDamping); - KX_PYMETHOD(KX_VehicleWrapper,SetSuspensionCompression); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionCompression); - KX_PYMETHOD(KX_VehicleWrapper,SetRollInfluence); + KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetRollInfluence); private: diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index da0e3dbdd8d..88f63334285 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -37,22 +37,22 @@ #include "KX_PyMath.h" PyTypeObject KX_VertexProxy::Type = { - PyObject_HEAD_INIT(&PyType_Type) + PyObject_HEAD_INIT(NULL) 0, "KX_VertexProxy", - sizeof(KX_VertexProxy), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods }; PyParentObject KX_VertexProxy::Parents[] = { @@ -79,47 +79,71 @@ PyMethodDef KX_VertexProxy::Methods[] = { }; PyAttributeDef KX_VertexProxy::Attributes[] = { + + KX_PYATTRIBUTE_DUMMY("x"), + KX_PYATTRIBUTE_DUMMY("y"), + KX_PYATTRIBUTE_DUMMY("z"), + + KX_PYATTRIBUTE_DUMMY("r"), + KX_PYATTRIBUTE_DUMMY("g"), + KX_PYATTRIBUTE_DUMMY("b"), + KX_PYATTRIBUTE_DUMMY("a"), + + KX_PYATTRIBUTE_DUMMY("u"), + KX_PYATTRIBUTE_DUMMY("v"), + + KX_PYATTRIBUTE_DUMMY("u2"), + KX_PYATTRIBUTE_DUMMY("v2"), + + KX_PYATTRIBUTE_DUMMY("XYZ"), + KX_PYATTRIBUTE_DUMMY("UV"), + + KX_PYATTRIBUTE_DUMMY("color"), + KX_PYATTRIBUTE_DUMMY("colour"), + + KX_PYATTRIBUTE_DUMMY("normal"), + { NULL } //Sentinel }; PyObject* -KX_VertexProxy::_getattr(const char *attr) +KX_VertexProxy::py_getattro(PyObject *attr) { - - if (attr[1]=='\0') { // Group single letters + char *attr_str= PyString_AsString(attr); + if (attr_str[1]=='\0') { // Group single letters // pos - if (attr[0]=='x') + if (attr_str[0]=='x') return PyFloat_FromDouble(m_vertex->getXYZ()[0]); - if (attr[0]=='y') + if (attr_str[0]=='y') return PyFloat_FromDouble(m_vertex->getXYZ()[1]); - if (attr[0]=='z') + if (attr_str[0]=='z') return PyFloat_FromDouble(m_vertex->getXYZ()[2]); // Col - if (attr[0]=='r') + if (attr_str[0]=='r') return PyFloat_FromDouble(m_vertex->getRGBA()[0]/255.0); - if (attr[0]=='g') + if (attr_str[0]=='g') return PyFloat_FromDouble(m_vertex->getRGBA()[1]/255.0); - if (attr[0]=='b') + if (attr_str[0]=='b') return PyFloat_FromDouble(m_vertex->getRGBA()[2]/255.0); - if (attr[0]=='a') + if (attr_str[0]=='a') return PyFloat_FromDouble(m_vertex->getRGBA()[3]/255.0); // UV - if (attr[0]=='u') + if (attr_str[0]=='u') return PyFloat_FromDouble(m_vertex->getUV1()[0]); - if (attr[0]=='v') + if (attr_str[0]=='v') return PyFloat_FromDouble(m_vertex->getUV1()[1]); } - if (!strcmp(attr, "XYZ")) + if (!strcmp(attr_str, "XYZ")) return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); - if (!strcmp(attr, "UV")) + if (!strcmp(attr_str, "UV")) return PyObjectFrom(MT_Point2(m_vertex->getUV1())); - if (!strcmp(attr, "color") || !strcmp(attr, "colour")) + if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour")) { const unsigned char *colp = m_vertex->getRGBA(); MT_Vector4 color(colp[0], colp[1], colp[2], colp[3]); @@ -127,64 +151,65 @@ KX_VertexProxy::_getattr(const char *attr) return PyObjectFrom(color); } - if (!strcmp(attr, "normal")) + if (!strcmp(attr_str, "normal")) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } - _getattr_up(SCA_IObject); + py_getattro_up(SCA_IObject); } -int KX_VertexProxy::_setattr(const char *attr, PyObject *pyvalue) +int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) { + char *attr_str= PyString_AsString(attr); if (PySequence_Check(pyvalue)) { - if (!strcmp(attr, "XYZ")) + if (!strcmp(attr_str, "XYZ")) { MT_Point3 vec; if (PyVecTo(pyvalue, vec)) { m_vertex->SetXYZ(vec); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - return 1; + return PY_SET_ATTR_FAIL; } - if (!strcmp(attr, "UV")) + if (!strcmp(attr_str, "UV")) { MT_Point2 vec; if (PyVecTo(pyvalue, vec)) { m_vertex->SetUV(vec); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - return 1; + return PY_SET_ATTR_FAIL; } - if (!strcmp(attr, "color") || !strcmp(attr, "colour")) + if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour")) { MT_Vector4 vec; if (PyVecTo(pyvalue, vec)) { m_vertex->SetRGBA(vec); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - return 1; + return PY_SET_ATTR_FAIL; } - if (!strcmp(attr, "normal")) + if (!strcmp(attr_str, "normal")) { MT_Vector3 vec; if (PyVecTo(pyvalue, vec)) { m_vertex->SetNormal(vec); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - return 1; + return PY_SET_ATTR_FAIL; } } @@ -193,51 +218,51 @@ int KX_VertexProxy::_setattr(const char *attr, PyObject *pyvalue) float val = PyFloat_AsDouble(pyvalue); // pos MT_Point3 pos(m_vertex->getXYZ()); - if (!strcmp(attr, "x")) + if (!strcmp(attr_str, "x")) { pos.x() = val; m_vertex->SetXYZ(pos); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "y")) + if (!strcmp(attr_str, "y")) { pos.y() = val; m_vertex->SetXYZ(pos); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "z")) + if (!strcmp(attr_str, "z")) { pos.z() = val; m_vertex->SetXYZ(pos); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } // uv MT_Point2 uv = m_vertex->getUV1(); - if (!strcmp(attr, "u")) + if (!strcmp(attr_str, "u")) { uv[0] = val; m_vertex->SetUV(uv); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "v")) + if (!strcmp(attr_str, "v")) { uv[1] = val; m_vertex->SetUV(uv); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } // uv MT_Point2 uv2 = m_vertex->getUV2(); - if (!strcmp(attr, "u2")) + if (!strcmp(attr_str, "u2")) { uv[0] = val; m_vertex->SetUV2(uv); @@ -245,49 +270,49 @@ int KX_VertexProxy::_setattr(const char *attr, PyObject *pyvalue) return 0; } - if (!strcmp(attr, "v2")) + if (!strcmp(attr_str, "v2")) { uv[1] = val; m_vertex->SetUV2(uv); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } // col unsigned int icol = *((const unsigned int *)m_vertex->getRGBA()); unsigned char *cp = (unsigned char*) &icol; val *= 255.0; - if (!strcmp(attr, "r")) + if (!strcmp(attr_str, "r")) { cp[0] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "g")) + if (!strcmp(attr_str, "g")) { cp[1] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "b")) + if (!strcmp(attr_str, "b")) { cp[2] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } - if (!strcmp(attr, "a")) + if (!strcmp(attr_str, "a")) { cp[3] = (unsigned char) val; m_vertex->SetRGBA(icol); m_mesh->SetMeshModified(true); - return 0; + return PY_SET_ATTR_SUCCESS; } } - return SCA_IObject::_setattr(attr, pyvalue); + return SCA_IObject::py_setattro(attr, pyvalue); } KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex) @@ -307,7 +332,7 @@ CValue* KX_VertexProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;} CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} STR_String sVertexName="vertex"; const STR_String & KX_VertexProxy::GetText() {return sVertexName;}; -float KX_VertexProxy::GetNumber() { return -1;} +double KX_VertexProxy::GetNumber() { return -1;} STR_String KX_VertexProxy::GetName() { return sVertexName;} void KX_VertexProxy::SetName(STR_String) { }; CValue* KX_VertexProxy::GetReplica() { return NULL;} @@ -316,12 +341,12 @@ void KX_VertexProxy::ReplicaSetName(STR_String) {}; // stuff for python integration -PyObject* KX_VertexProxy::PyGetXYZ(PyObject*) +PyObject* KX_VertexProxy::PyGetXYZ() { return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); } -PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value) +PyObject* KX_VertexProxy::PySetXYZ(PyObject* value) { MT_Point3 vec; if (!PyVecTo(value, vec)) @@ -332,12 +357,12 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value) Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetNormal(PyObject*) +PyObject* KX_VertexProxy::PyGetNormal() { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } -PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value) +PyObject* KX_VertexProxy::PySetNormal(PyObject* value) { MT_Vector3 vec; if (!PyVecTo(value, vec)) @@ -349,13 +374,13 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value) } -PyObject* KX_VertexProxy::PyGetRGBA(PyObject*) +PyObject* KX_VertexProxy::PyGetRGBA() { int *rgba = (int *) m_vertex->getRGBA(); return PyInt_FromLong(*rgba); } -PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value) +PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) { if PyInt_Check(value) { int rgba = PyInt_AsLong(value); @@ -373,17 +398,17 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value) } } - PyErr_SetString(PyExc_TypeError, "expected a 4D vector or an int"); + PyErr_SetString(PyExc_TypeError, "vert.setRGBA(value): KX_VertexProxy, expected a 4D vector or an int"); return NULL; } -PyObject* KX_VertexProxy::PyGetUV(PyObject*) +PyObject* KX_VertexProxy::PyGetUV() { return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); } -PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value) +PyObject* KX_VertexProxy::PySetUV(PyObject* value) { MT_Point2 vec; if (!PyVecTo(value, vec)) @@ -394,12 +419,12 @@ PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value) Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetUV2(PyObject*) +PyObject* KX_VertexProxy::PyGetUV2() { return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); } -PyObject* KX_VertexProxy::PySetUV2(PyObject*, PyObject* args) +PyObject* KX_VertexProxy::PySetUV2(PyObject* args) { MT_Point2 vec; unsigned int unit=0; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 28196075904..67a15d96768 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -46,7 +46,7 @@ public: CValue* Calc(VALUE_OPERATOR op, CValue *val) ; CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); const STR_String & GetText(); - float GetNumber(); + double GetNumber(); STR_String GetName(); void SetName(STR_String name); // Set the name of the value void ReplicaSetName(STR_String name); @@ -54,8 +54,8 @@ public: // stuff for python integration - virtual PyObject* _getattr(const char *attr); - virtual int _setattr(const char *attr, PyObject *pyvalue); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *pyvalue); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index 0ec280080bd..ba59d0d3d47 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -38,11 +38,13 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool occlusion, bool recursive, PyTypeObject* T ) : SCA_IActuator(gameobj,T), m_visible(visible), + m_occlusion(occlusion), m_recursive(recursive) { // intentionally empty @@ -78,6 +80,7 @@ KX_VisibilityActuator::Update() KX_GameObject *obj = (KX_GameObject*) GetParent(); obj->SetVisible(m_visible, m_recursive); + obj->SetOccluder(m_occlusion, m_recursive); obj->UpdateBuckets(m_recursive); return false; @@ -90,24 +93,24 @@ KX_VisibilityActuator::Update() /* Integration hooks ------------------------------------------------------- */ -PyTypeObject -KX_VisibilityActuator::Type = { - PyObject_HEAD_INIT(&PyType_Type) +PyTypeObject KX_VisibilityActuator::Type = { + PyObject_HEAD_INIT(NULL) 0, "KX_VisibilityActuator", - sizeof(KX_VisibilityActuator), + sizeof(PyObjectPlus_Proxy), 0, - PyDestructor, + py_base_dealloc, 0, - __getattr, - __setattr, - 0, //&MyPyCompare, - __repr, - 0, //&cvalue_as_number, 0, 0, 0, - 0 + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods + }; PyParentObject @@ -121,20 +124,29 @@ KX_VisibilityActuator::Parents[] = { PyMethodDef KX_VisibilityActuator::Methods[] = { - {"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible, - METH_VARARGS, (PY_METHODCHAR)SetVisible_doc}, + // Deprecated -----> + {"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible, METH_VARARGS, + (PY_METHODCHAR) SetVisible_doc}, + // <----- {NULL,NULL} //Sentinel }; PyAttributeDef KX_VisibilityActuator::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("visibility", KX_VisibilityActuator, m_visible), + KX_PYATTRIBUTE_BOOL_RW("occlusion", KX_VisibilityActuator, m_occlusion), + KX_PYATTRIBUTE_BOOL_RW("recursion", KX_VisibilityActuator, m_recursive), { NULL } //Sentinel }; -PyObject* KX_VisibilityActuator::_getattr(const char *attr) +PyObject* KX_VisibilityActuator::py_getattro(PyObject *attr) { - _getattr_up(SCA_IActuator); -}; + py_getattro_up(SCA_IActuator); +} +int KX_VisibilityActuator::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_IActuator); +} /* set visibility ---------------------------------------------------------- */ @@ -145,12 +157,11 @@ KX_VisibilityActuator::SetVisible_doc[] = "\tSet the properties of the actuator.\n"; PyObject* -KX_VisibilityActuator::PySetVisible(PyObject* self, - PyObject* args, - PyObject* kwds) { +KX_VisibilityActuator::PySetVisible(PyObject* args) { int vis; + ShowDeprecationWarning("SetVisible()", "the visible property"); - if(!PyArg_ParseTuple(args, "i", &vis)) { + if(!PyArg_ParseTuple(args, "i:setVisible", &vis)) { return NULL; } diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index 323280de8cb..04633bce665 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -39,6 +39,7 @@ class KX_VisibilityActuator : public SCA_IActuator /** Make visible? */ bool m_visible; + bool m_occlusion; bool m_recursive; public: @@ -46,6 +47,7 @@ class KX_VisibilityActuator : public SCA_IActuator KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool occlusion, bool recursive, PyTypeObject* T=&Type ); @@ -67,9 +69,13 @@ class KX_VisibilityActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* _getattr(const char *attr); - //KX_PYMETHOD_DOC - KX_PYMETHOD_DOC(KX_VisibilityActuator,SetVisible); + virtual PyObject* py_getattro(PyObject *attr); + virtual int py_setattro(PyObject *attr, PyObject *value); + + // Deprecated -----> + KX_PYMETHOD_DOC_VARARGS(KX_VisibilityActuator,SetVisible); + // <----- + }; diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile index 0b48ad8b8c3..bdc0b335b02 100644 --- a/source/gameengine/Ketsji/Makefile +++ b/source/gameengine/Ketsji/Makefile @@ -61,7 +61,7 @@ CPPFLAGS += -I. CPPFLAGS += -I../Converter CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/blenlib -CPPFLAGS += -I../../blender/include +CPPFLAGS += -I../../blender/editors/include CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I../../blender/imbuf CPPFLAGS += -I../../blender/gpu diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 5989d9d8b52..0e888edd43b 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -6,19 +6,29 @@ Import ('env') sources = env.Glob('*.cpp') defs = '' +# XXX 2.5 # Mathutils C files. -sources.extend([\ - '#source/blender/python/api2_2x/Mathutils.c',\ - '#source/blender/python/api2_2x/constant.c',\ - '#source/blender/python/api2_2x/euler.c',\ - '#source/blender/python/api2_2x/gen_utils.c',\ - '#source/blender/python/api2_2x/matrix.c',\ - '#source/blender/python/api2_2x/point.c',\ - '#source/blender/python/api2_2x/quat.c',\ - '#source/blender/python/api2_2x/vector.c',\ -]) - -incs = '. #source/blender/python/api2_2x' # Only for Mathutils! - no other deps +#sources.extend([\ +# '#source/blender/python/api2_2x/Mathutils.c',\ +# '#source/blender/python/api2_2x/constant.c',\ +# '#source/blender/python/api2_2x/euler.c',\ +# '#source/blender/python/api2_2x/gen_utils.c',\ +# '#source/blender/python/api2_2x/matrix.c',\ +# '#source/blender/python/api2_2x/point.c',\ +# '#source/blender/python/api2_2x/quat.c',\ +# '#source/blender/python/api2_2x/vector.c',\ +#]) +# +#sources.extend([\ +# '#source/blender/python/api2_2x/bpy_internal_import.c' +#]) +# +# +#sources.extend([\ +# '#source/blender/python/api2_2x/BGL.c' +#]) + +incs = '. #source/blender/python/api2_2x' # Only for Mathutils! and bpy_internal_import.h, be very careful incs += ' #source/kernel/gen_system #intern/string #intern/guardedalloc' incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #intern/bmfont' @@ -26,7 +36,7 @@ incs += ' #intern/SoundSystem #intern/SoundSystem/include #intern/SoundSystem/op incs += ' #intern/SoundSystem/dummy #intern/SoundSystem/intern #source/gameengine/Converter' incs += ' #source/gameengine/BlenderRoutines #source/blender/imbuf #intern/moto/include' incs += ' #source/gameengine/Ketsji #source/gameengine/Ketsji/KXNetwork #source/blender/blenlib' -incs += ' #source/blender/blenkernel #source/blender #source/blender/include' +incs += ' #source/blender/blenkernel #source/blender #source/blender/editors/include' incs += ' #source/blender/makesdna #source/blender/python #source/gameengine/Rasterizer' incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #source/gameengine/Physics/Bullet' @@ -54,4 +64,4 @@ if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') cxxflags.append ('/O2') -env.BlenderLib ( 'bf_ketsji', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], cxx_compileflags = cxxflags ) +env.BlenderLib ( 'bf_ketsji', sources, Split(incs), Split(defs), libtype=['core','player'], priority=[320, 60], cxx_compileflags = cxxflags ) |