BGE MouseFocusSensor

- fix for multiple viewpors broke single viewport (both work now)
- python could get uninitialized values from m_prevTargetPoint and m_prevSourcePoint
- getting the RayDirection for python could crash blender trying to normalize a zero length vector.
- added python attributes
- removed unused canvas from the MouseFocusSensor class
This commit is contained in:
Campbell Barton 2009-04-15 13:50:56 +00:00
parent e8f4d93221
commit 514c78ba39
4 changed files with 238 additions and 125 deletions

@ -509,7 +509,6 @@ void BL_ConvertSensors(struct Object* blenderobject,
starty,
keytype,
trackfocus,
canvas,
kxscene,
kxengine,
gameobj);

@ -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()
bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
{
m_hitObject = 0;
m_hitPosition.setValue(0,0,0);
m_hitNormal.setValue(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.
@ -188,10 +187,6 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus()
*
* */
MT_Vector4 frompoint;
MT_Vector4 topoint;
bool result = false;
/* Because we don't want to worry about resize events, camera
* changes and all that crap, we just determine this over and
@ -200,35 +195,28 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus()
* 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...*/
list<class KX_Camera*>* cameras = m_kxscene->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())
{
KX_Camera* cam= (*it);
/* 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
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) // above bottom
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);
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! - see from point Z values */
@ -289,16 +277,56 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus()
KX_RayCast::RayTest(physics_environment, m_prevSourcePoint, m_prevTargetPoint, callback);
if (m_hitObject) {
result= true;
break;
}
}
if (m_hitObject)
return true;
return false;
}
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 result;
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;
}
/* ------------------------------------------------------------------------- */
@ -342,11 +370,16 @@ 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
};
@ -360,6 +393,8 @@ const char KX_MouseFocusSensor::GetHitObject_doc[] =
"\tReturns the object that was hit by this ray.\n";
PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self)
{
ShowDeprecationWarning("GetHitObject()", "the hitObject property");
if (m_hitObject)
return m_hitObject->AddRef();
@ -372,6 +407,8 @@ const char KX_MouseFocusSensor::GetHitPosition_doc[] =
"\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n";
PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self)
{
ShowDeprecationWarning("getHitPosition()", "the hitPosition property");
return PyObjectFrom(m_hitPosition);
}
@ -380,9 +417,11 @@ const char KX_MouseFocusSensor::GetRayDirection_doc[] =
"\tReturns the direction from the ray (in worldcoordinates) .\n";
PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self)
{
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);
}
@ -391,6 +430,8 @@ const char KX_MouseFocusSensor::GetHitNormal_doc[] =
"\tReturns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray.\n";
PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self)
{
ShowDeprecationWarning("getHitNormal()", "the hitNormal property");
return PyObjectFrom(m_hitNormal);
}
@ -400,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(PyObject* self)
{
ShowDeprecationWarning("getRayTarget()", "the rayTarget property");
return PyObjectFrom(m_prevTargetPoint);
}
@ -409,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(PyObject* self)
{
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->AddRef();
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 */

@ -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,7 +81,10 @@ 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 ---------------------------------------------------- */
@ -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. */

@ -8,46 +8,59 @@ class KX_MouseFocusSensor(SCA_MouseSensor):
The mouse focus sensor works by transforming the mouse coordinates from 2d device
space to 3d space then raycasting away from the camera.
@ivar raySource: The worldspace source of the ray (the view position)
@type raySource: list (vector of 3 floats)
@ivar rayTarget: The worldspace target of the ray.
@type rayTarget: list (vector of 3 floats)
@ivar rayDirection: The L{rayTarget} - L{raySource} normalized.
@type rayDirection: list (normalized vector of 3 floats)
@ivar hitObject: the last object the mouse was over.
@type hitObject: L{KX_GameObject<KX_GameObject.KX_GameObject>} or None
@ivar hitPosition: The worldspace position of the ray intersecton.
@type hitPosition: list (vector of 3 floats)
@ivar hitNormal: the worldspace normal from the face at point of intersection.
@type hitNormal: list (normalized vector of 3 floats)
"""
def getHitNormal():
"""
Returns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray.
Returns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray. (B{deprecated})
@rtype: list [x, y, z]
@return: the ray collision normal.
"""
def getHitObject():
"""
Returns the object that was hit by this ray or None.
Returns the object that was hit by this ray or None. (B{deprecated})
@rtype: L{KX_GameObject} or None
@return: the collision object.
"""
def getHitPosition():
"""
Returns the position (in worldcoordinates) at the point of collision where the object was hit by this ray.
Returns the position (in worldcoordinates) at the point of collision where the object was hit by this ray. (B{deprecated})
@rtype: list [x, y, z]
@return: the ray collision position.
"""
def getRayDirection():
"""
Returns the normalized direction (in worldcoordinates) of the ray cast by the mouse.
Returns the normalized direction (in worldcoordinates) of the ray cast by the mouse. (B{deprecated})
@rtype: list [x, y, z]
@return: the ray direction.
"""
def getRaySource():
"""
Returns the position (in worldcoordinates) the ray was cast from by the mouse.
Returns the position (in worldcoordinates) the ray was cast from by the mouse. (B{deprecated})
@rtype: list [x, y, z]
@return: the ray source.
"""
def getRayTarget():
"""
Returns the target of the ray (in worldcoordinates) that seeks the focus object.
Returns the target of the ray (in worldcoordinates) that seeks the focus object. (B{deprecated})
@rtype: list [x, y, z]
@return: the ray target.