Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Susano Pinto <andresusanopinto@gmail.com>2008-08-06 20:50:07 +0400
committerAndre Susano Pinto <andresusanopinto@gmail.com>2008-08-06 20:50:07 +0400
commit523634ca17a392a49e324244ee6f35ac2359544b (patch)
tree38a0b55844b78c4750dfb5de9673ff34b60aa2e4 /source/gameengine
parente57c5ef56c306fe495346525fb9d1f9bcf8cfd2b (diff)
svn merge -r 15908:15988 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp3
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.cpp9
-rw-r--r--source/gameengine/GamePlayer/common/windows/GPW_Canvas.h2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp81
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp13
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h1
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.cpp12
-rw-r--r--source/gameengine/Ketsji/SConscript16
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp5
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h9
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp22
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h5
-rw-r--r--source/gameengine/PyDoc/KX_GameObject.py10
15 files changed, 155 insertions, 42 deletions
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index b3a3a47152a..7de3056e382 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -335,7 +335,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module.
initGameKeys();
initPythonConstraintBinding();
-
+ initMathutils();
if (sceneconverter)
{
@@ -602,6 +602,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
initGameKeys();
initPythonConstraintBinding();
+ initMathutils();
if (sceneconverter)
{
diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp
index 7410beecaf4..ce004fa0504 100644
--- a/source/gameengine/Converter/KX_IpoConvert.cpp
+++ b/source/gameengine/Converter/KX_IpoConvert.cpp
@@ -766,15 +766,18 @@ void BL_ConvertMaterialIpos(
// if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL
// --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor
// because this yields a better performance as not all the vertex colors need to be edited
- if(mat) ConvertMaterialIpos(mat, NULL, gameobj, converter);
+ if(mat) ConvertMaterialIpos(mat, 0, gameobj, converter);
}
else
{
for (int material_index=1; material_index <= blenderobject->totcol; material_index++)
{
Material *mat = give_current_material(blenderobject, material_index);
- STR_HashedString matname = mat->id.name;
- if(mat) ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
+ STR_HashedString matname;
+ if(mat) {
+ matname= mat->id.name;
+ ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
+ }
}
}
}
diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h
index bb1abd71505..bf8cb720811 100644
--- a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h
+++ b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h
@@ -36,7 +36,7 @@
#include <iostream>
#include <windows.h>
-#include <gl/gl.h>
+//#include <gl/gl.h>
#include "GPC_Canvas.h"
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index b5ebffb9378..7be3b94d8ae 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -56,6 +56,7 @@ extern "C"
#include "BLO_readfile.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "DNA_scene_types.h"
#ifdef __cplusplus
}
#endif // __cplusplus
@@ -647,7 +648,7 @@ bool GPG_Application::startEngine(void)
PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module
initGameKeys();
initPythonConstraintBinding();
-
+ initMathutils();
@@ -669,6 +670,11 @@ bool GPG_Application::startEngine(void)
m_ketsjiengine->StartEngine(true);
m_engineRunning = true;
+ // Set the animation playback rate for ipo's and actions
+ // the framerate below should patch with FPS macro defined in blendef.h
+ // Could be in StartEngine set the framerate, we need the scene to do this
+ m_ketsjiengine->SetAnimFrameRate( (((double) G.scene->r.frs_sec) / G.scene->r.frs_sec_base) );
+
}
if (!m_engineRunning)
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 02d1ad1b12b..661bf17ef23 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -914,6 +914,7 @@ PyMethodDef KX_GameObject::Methods[] = {
KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
KX_PYMETHODTABLE(KX_GameObject, rayCast),
KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
+ KX_PYMETHODTABLE(KX_GameObject, getVectTo),
{NULL,NULL} //Sentinel
};
@@ -1367,14 +1368,15 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self,
{
int mesh = 0;
- if (PyArg_ParseTuple(args, "|i", &mesh))
+ if (!PyArg_ParseTuple(args, "|i", &mesh))
+ return NULL; // python sets a simple error
+
+ if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
{
- if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
- {
- KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
- return meshproxy;
- }
+ KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
+ return meshproxy;
}
+
Py_RETURN_NONE;
}
@@ -1488,6 +1490,9 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self,
MT_Vector3 vect;
if (PyVecTo(pyvect, vect))
{
+ if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
+ if (fac< 1.0) fac= 1.0;
+
AlignAxisToVect(vect,axis,fac);
NodeUpdateGS(0.f,true);
Py_RETURN_NONE;
@@ -1555,6 +1560,54 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
return NULL;
}
+KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo,
+"getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
+"Returns a 3-tuple with (distance,worldVector,localVector)\n")
+{
+ MT_Point3 toPoint, fromPoint;
+ MT_Vector3 toDir, locToDir;
+ MT_Scalar distance;
+
+ PyObject *returnValue;
+ PyObject *pyother;
+
+ if (!PyVecArgTo(args, toPoint))
+ {
+ PyErr_Clear();
+ if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother))
+ {
+ KX_GameObject *other = static_cast<KX_GameObject*>(pyother);
+ toPoint = other->NodeGetWorldPosition();
+ }else
+ {
+ PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type");
+ return NULL;
+ }
+ }
+
+ fromPoint = NodeGetWorldPosition();
+ toDir = toPoint-fromPoint;
+ distance = toDir.length();
+
+ if (MT_fuzzyZero(distance))
+ {
+ //cout << "getVectTo() Error: Null vector!\n";
+ locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
+ distance = 0.0;
+ } else {
+ toDir.normalize();
+ locToDir = toDir * NodeGetWorldOrientation();
+ }
+
+ returnValue = PyTuple_New(3);
+ if (returnValue) { // very unlikely to fail, python sets a memory error here.
+ PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
+ PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
+ PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
+ }
+ return returnValue;
+}
+
bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
{
@@ -1588,8 +1641,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
char *propName = NULL;
if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) {
- PyErr_SetString(PyExc_TypeError, "Invalid arguments");
- return NULL;
+ return NULL; // python sets simple error
}
if (!PyVecTo(pyarg, toPoint))
@@ -1654,8 +1706,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
KX_GameObject *other;
if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) {
- PyErr_SetString(PyExc_TypeError, "Invalid arguments");
- return NULL;
+ return NULL; // Python sets a simple error
}
if (!PyVecTo(pyto, toPoint))
@@ -1714,13 +1765,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
if (m_pHitObject)
{
PyObject* returnValue = PyTuple_New(3);
- if (!returnValue) {
- PyErr_SetString(PyExc_TypeError, "PyTuple_New() failed");
- return NULL;
+ 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, 1, PyObjectFrom(resultPoint));
+ PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
}
- PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
- PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
- PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
return returnValue;
}
return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 1d36798b12f..4e435e9ddf4 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -756,6 +756,7 @@ public:
KX_PYMETHOD_DOC(KX_GameObject,rayCastTo);
KX_PYMETHOD_DOC(KX_GameObject,rayCast);
KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo);
+ KX_PYMETHOD_DOC(KX_GameObject,getVectTo);
private :
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index b66c3e42606..db4793de23d 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -62,6 +62,10 @@
#include "KX_PyMath.h"
+extern "C" {
+ #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use.
+}
+
#include "PHY_IPhysicsEnvironment.h"
// FIXME: Enable for access to blender python modules. This is disabled because
// python has dependencies on a lot of other modules and is a pain to link.
@@ -733,7 +737,7 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
ErrorObject = PyString_FromString("GameLogic.error");
PyDict_SetItemString(d, "error", ErrorObject);
-
+
// XXXX Add constants here
/* To use logic bricks, we need some sort of constants. Here, we associate */
/* constants and sumbolic names. Add them to dictionary d. */
@@ -876,7 +880,7 @@ 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, "Rasterizer") || !strcmp(name, "Mathutils")) {
return PyImport_ImportModuleEx(name, globals, locals, fromlist);
}
@@ -1169,6 +1173,11 @@ PyObject* initGameKeys()
return d;
}
+PyObject* initMathutils()
+{
+ return Mathutils_Init("Mathutils"); // Use as a top level module in BGE
+}
+
void PHY_SetActiveScene(class KX_Scene* scene)
{
gp_KetsjiScene = scene;
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
index 41cf7fd67b3..f094a1ca575 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -44,6 +44,7 @@ PyObject* initGameLogic(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* initMathutils();
void exitGamePlayerPythonScripting();
PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
void exitGamePythonScripting();
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
index 7528fdbbc34..48d4cf59a2b 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
@@ -100,17 +100,17 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data,
void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor)
{
KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor);
- m_sensors.insert(touchsensor);
-
- touchsensor->RegisterSumo(this);
+ if (m_sensors.insert(touchsensor).second)
+ // the sensor was effectively inserted, register it
+ touchsensor->RegisterSumo(this);
}
void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor)
{
KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor);
- m_sensors.erase(touchsensor);
-
- touchsensor->UnregisterSumo(this);
+ if (m_sensors.erase(touchsensor))
+ // the sensor was effectively removed, unregister it
+ touchsensor->UnregisterSumo(this);
}
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index fdac5a71071..f6f744b199a 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -5,7 +5,21 @@ Import ('env')
sources = env.Glob('*.cpp')
-incs = '. #source/kernel/gen_system #intern/string #intern/guardedalloc'
+# 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
+
+incs += ' #source/kernel/gen_system #intern/string #intern/guardedalloc'
incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #intern/bmfont'
incs += ' #intern/SoundSystem #intern/SoundSystem/include #intern/SoundSystem/openal'
incs += ' #intern/SoundSystem/dummy #intern/SoundSystem/intern #source/gameengine/Converter'
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 5c70b071661..b872fae6138 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -42,7 +42,8 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
{
m_collisionDelay = 0;
m_newClientInfo = 0;
-
+ m_registerCount = 0;
+
m_MotionState = ci.m_MotionState;
m_bulletMotionState = 0;
@@ -217,7 +218,7 @@ void CcdPhysicsController::WriteDynamicsToMotionState()
void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
{
m_MotionState = motionstate;
-
+ m_registerCount = 0;
m_body = 0;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 64f1876e199..448e5622eff 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -110,12 +110,19 @@ class CcdPhysicsController : public PHY_IPhysicsController
void* m_newClientInfo;
-
+ int m_registerCount; // needed when multiple sensors use the same controller
CcdConstructionInfo m_cci;//needed for replication
void GetWorldOrientation(btMatrix3x3& mat);
void CreateRigidbody();
+ bool Register() {
+ return (m_registerCount++ == 0) ? true : false;
+ }
+ bool Unregister() {
+ return (--m_registerCount == 0) ? true : false;
+ }
+
protected:
void setWorldOrientation(const btMatrix3x3& mat);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index ea14c5430e2..08f40424323 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -439,6 +439,9 @@ void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctr
m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
m_controllers.erase(ctrl);
+ if (ctrl->m_registerCount != 0)
+ printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
+
//remove it from the triggers
m_triggerControllers.erase(ctrl);
}
@@ -473,6 +476,13 @@ void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctr
}
}
+void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ctrl)
+{
+ if (m_controllers.erase(ctrl))
+ {
+ m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
+ }
+}
void CcdPhysicsEnvironment::beginFrame()
@@ -885,13 +895,17 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl)
{
- m_triggerControllers.erase((CcdPhysicsController*)ctrl);
+ CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
+ if (ccdCtrl->Unregister())
+ m_triggerControllers.erase(ccdCtrl);
}
void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl)
{
- removeCcdPhysicsController((CcdPhysicsController*)ctrl);
+ removeCollisionCallback(ctrl);
+
+ disableCcdPhysicsController((CcdPhysicsController*)ctrl);
}
void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
@@ -930,8 +944,8 @@ void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctr
{
CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
- //printf("requestCollisionCallback\n");
- m_triggerControllers.insert(ccdCtrl);
+ if (ccdCtrl->Register())
+ m_triggerControllers.insert(ccdCtrl);
}
void CcdPhysicsEnvironment::CallbackTriggers()
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index fd96522037e..825a5e525f2 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -186,10 +186,7 @@ protected:
void updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask);
- void disableCcdPhysicsController(CcdPhysicsController* ctrl)
- {
- removeCcdPhysicsController(ctrl);
- }
+ void disableCcdPhysicsController(CcdPhysicsController* ctrl);
void enableCcdPhysicsController(CcdPhysicsController* ctrl);
diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py
index 8f17cf26f15..a5ba5b1d634 100644
--- a/source/gameengine/PyDoc/KX_GameObject.py
+++ b/source/gameengine/PyDoc/KX_GameObject.py
@@ -253,6 +253,16 @@ class KX_GameObject:
@type other: L{KX_GameObject} or list [x, y, z]
@rtype: float
"""
+ def getVectTo(other):
+ """
+ Returns the vector and the distance to another object or point.
+ The vector is normalized unless the distance is 0, in which a NULL vector is returned.
+
+ @param other: a point or another L{KX_GameObject} to get the vector and distance to.
+ @type other: L{KX_GameObject} or list [x, y, z]
+ @rtype: 3-tuple (float, 3-tuple (x,y,z), 3-tuple (x,y,z))
+ @return: (distance, globalVector(3), localVector(3))
+ """
def rayCastTo(other,dist,prop):
"""
Look towards another point/object and find first object hit within dist that matches prop.