BGE: Add property/material detection and X-Ray for mouse over any sensor
This patch adds a Property/Material detection and a X-Ray mode to the mouse over any sensor like on the ray sensor. Proposal: http://blenderartists.org/forum/showthread.php?261847-BGE-proposal-Mouse-Over-Any-sensor-with-Property-and-X-Ray&highlight=proposal Reviewers: moguri Reviewed By: moguri Differential Revision: https://developer.blender.org/D653
This commit is contained in:
@@ -64,3 +64,20 @@ base class --- :class:`SCA_MouseSensor`
|
|||||||
|
|
||||||
:type: boolean
|
:type: boolean
|
||||||
|
|
||||||
|
.. attribute:: useXRay
|
||||||
|
|
||||||
|
If enabled it allows the sensor to see through game objects that don't have the selected property or material.
|
||||||
|
|
||||||
|
:type: boolean
|
||||||
|
|
||||||
|
.. attribute:: propName
|
||||||
|
|
||||||
|
The property or material the sensor is looking for.
|
||||||
|
|
||||||
|
:type: string
|
||||||
|
|
||||||
|
.. attribute:: useMaterial
|
||||||
|
|
||||||
|
Determines if the sensor is looking for a property or material. KX_True = Find material; KX_False = Find property.
|
||||||
|
|
||||||
|
:type: boolean
|
||||||
|
|||||||
@@ -1144,15 +1144,35 @@ static void draw_sensor_message(uiLayout *layout, PointerRNA *ptr)
|
|||||||
uiItemR(layout, ptr, "subject", 0, NULL, ICON_NONE);
|
uiItemR(layout, ptr, "subject", 0, NULL, ICON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_sensor_mouse(uiLayout *layout, PointerRNA *ptr)
|
static void draw_sensor_mouse(uiLayout *layout, PointerRNA *ptr, bContext *C)
|
||||||
{
|
{
|
||||||
uiLayout *split;
|
uiLayout *split, *split2;
|
||||||
|
|
||||||
|
Object *ob = (Object *)ptr->id.data;
|
||||||
|
PointerRNA main_ptr;
|
||||||
|
|
||||||
split = uiLayoutSplit(layout, 0.8f, false);
|
split = uiLayoutSplit(layout, 0.8f, false);
|
||||||
uiItemR(split, ptr, "mouse_event", 0, NULL, ICON_NONE);
|
uiItemR(split, ptr, "mouse_event", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY)
|
if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY)
|
||||||
|
{
|
||||||
uiItemR(split, ptr, "use_pulse", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
|
uiItemR(split, ptr, "use_pulse", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
split = uiLayoutSplit(layout, 0.3f, false);
|
||||||
|
uiItemR(split, ptr, "use_material", 0, "", ICON_NONE);
|
||||||
|
|
||||||
|
split2 = uiLayoutSplit(split, 0.7f, false);
|
||||||
|
if (RNA_enum_get(ptr, "use_material") == SENS_RAY_PROPERTY)
|
||||||
|
{
|
||||||
|
uiItemR(split2, ptr, "property", 0, "", ICON_NONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RNA_main_pointer_create(CTX_data_main(C), &main_ptr);
|
||||||
|
uiItemPointerR(split2, ptr, "material", &main_ptr, "materials", "", ICON_MATERIAL_DATA);
|
||||||
|
}
|
||||||
|
uiItemR(split2, ptr, "use_x_ray", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_sensor_near(uiLayout *layout, PointerRNA *ptr)
|
static void draw_sensor_near(uiLayout *layout, PointerRNA *ptr)
|
||||||
@@ -1273,7 +1293,7 @@ static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
|
|||||||
draw_sensor_message(box, ptr);
|
draw_sensor_message(box, ptr);
|
||||||
break;
|
break;
|
||||||
case SENS_MOUSE:
|
case SENS_MOUSE:
|
||||||
draw_sensor_mouse(box, ptr);
|
draw_sensor_mouse(box, ptr, C);
|
||||||
break;
|
break;
|
||||||
case SENS_NEAR:
|
case SENS_NEAR:
|
||||||
draw_sensor_near(box, ptr);
|
draw_sensor_near(box, ptr);
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ typedef struct bMouseSensor {
|
|||||||
short type;
|
short type;
|
||||||
short flag;
|
short flag;
|
||||||
short pad1;
|
short pad1;
|
||||||
short pad2;
|
short mode; /* flag to choose material or property */
|
||||||
|
char propname[64];
|
||||||
|
char matname[64];
|
||||||
} bMouseSensor;
|
} bMouseSensor;
|
||||||
|
|
||||||
/* DEPRECATED */
|
/* DEPRECATED */
|
||||||
|
|||||||
@@ -405,6 +405,12 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
|
|||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const EnumPropertyItem prop_mouse_type_items[] = {
|
||||||
|
{SENS_COLLISION_PROPERTY, "PROPERTY", ICON_LOGIC, "Property", "Use a material for ray intersections"},
|
||||||
|
{SENS_COLLISION_MATERIAL, "MATERIAL", ICON_MATERIAL_DATA, "Material", "Use a property for ray intersections"},
|
||||||
|
{0, NULL, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "MouseSensor", "Sensor");
|
srna = RNA_def_struct(brna, "MouseSensor", "Sensor");
|
||||||
RNA_def_struct_ui_text(srna, "Mouse Sensor", "Sensor to detect mouse events");
|
RNA_def_struct_ui_text(srna, "Mouse Sensor", "Sensor to detect mouse events");
|
||||||
RNA_def_struct_sdna_from(srna, "bMouseSensor", "data");
|
RNA_def_struct_sdna_from(srna, "bMouseSensor", "data");
|
||||||
@@ -419,6 +425,27 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
|
|||||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SENS_MOUSE_FOCUS_PULSE);
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", SENS_MOUSE_FOCUS_PULSE);
|
||||||
RNA_def_property_ui_text(prop, "Pulse", "Moving the mouse over a different object generates a pulse");
|
RNA_def_property_ui_text(prop, "Pulse", "Moving the mouse over a different object generates a pulse");
|
||||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_material", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode");
|
||||||
|
RNA_def_property_enum_items(prop, prop_mouse_type_items);
|
||||||
|
RNA_def_property_ui_text(prop, "M/P", "Toggle collision on material or property");
|
||||||
|
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "property", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "propname");
|
||||||
|
RNA_def_property_ui_text(prop, "Property", "Only look for objects with this property (blank = all objects)");
|
||||||
|
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "matname");
|
||||||
|
RNA_def_property_ui_text(prop, "Material", "Only look for objects with this material (blank = all objects)");
|
||||||
|
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_x_ray", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", SENS_RAY_XRAY);
|
||||||
|
RNA_def_property_ui_text(prop, "X-Ray", "Toggle X-Ray option (see through objects that don't have the property)");
|
||||||
|
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_keyboard_sensor(BlenderRNA *brna)
|
static void rna_def_keyboard_sensor(BlenderRNA *brna)
|
||||||
|
|||||||
@@ -329,12 +329,19 @@ void BL_ConvertSensors(struct Object* blenderobject,
|
|||||||
gameobj);
|
gameobj);
|
||||||
} else {
|
} else {
|
||||||
/* give us a focus-aware sensor */
|
/* give us a focus-aware sensor */
|
||||||
|
bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL);
|
||||||
|
bool bXRay = (bmouse->flag & SENS_RAY_XRAY);
|
||||||
|
STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname);
|
||||||
|
|
||||||
gamesensor = new KX_MouseFocusSensor(eventmgr,
|
gamesensor = new KX_MouseFocusSensor(eventmgr,
|
||||||
startx,
|
startx,
|
||||||
starty,
|
starty,
|
||||||
keytype,
|
keytype,
|
||||||
trackfocus,
|
trackfocus,
|
||||||
(bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false,
|
(bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false,
|
||||||
|
checkname,
|
||||||
|
bFindMaterial,
|
||||||
|
bXRay,
|
||||||
kxscene,
|
kxscene,
|
||||||
kxengine,
|
kxengine,
|
||||||
gameobj);
|
gameobj);
|
||||||
|
|||||||
@@ -63,12 +63,18 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
|
|||||||
short int mousemode,
|
short int mousemode,
|
||||||
int focusmode,
|
int focusmode,
|
||||||
bool bTouchPulse,
|
bool bTouchPulse,
|
||||||
|
const STR_String& propname,
|
||||||
|
bool bFindMaterial,
|
||||||
|
bool bXRay,
|
||||||
KX_Scene* kxscene,
|
KX_Scene* kxscene,
|
||||||
KX_KetsjiEngine *kxengine,
|
KX_KetsjiEngine *kxengine,
|
||||||
SCA_IObject* gameobj)
|
SCA_IObject* gameobj)
|
||||||
: SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj),
|
: SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj),
|
||||||
m_focusmode(focusmode),
|
m_focusmode(focusmode),
|
||||||
m_bTouchPulse(bTouchPulse),
|
m_bTouchPulse(bTouchPulse),
|
||||||
|
m_propertyname(propname),
|
||||||
|
m_bFindMaterial(bFindMaterial),
|
||||||
|
m_bXRay(bXRay),
|
||||||
m_kxscene(kxscene),
|
m_kxscene(kxscene),
|
||||||
m_kxengine(kxengine)
|
m_kxengine(kxengine)
|
||||||
{
|
{
|
||||||
@@ -146,7 +152,31 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
|
|||||||
* self-hits are excluded by setting the correct ignore-object.)
|
* self-hits are excluded by setting the correct ignore-object.)
|
||||||
* Hitspots now become valid. */
|
* Hitspots now become valid. */
|
||||||
KX_GameObject* thisObj = (KX_GameObject*) GetParent();
|
KX_GameObject* thisObj = (KX_GameObject*) GetParent();
|
||||||
|
|
||||||
|
bool bFound = false;
|
||||||
|
|
||||||
if ((m_focusmode == 2) || hitKXObj == thisObj)
|
if ((m_focusmode == 2) || hitKXObj == thisObj)
|
||||||
|
{
|
||||||
|
if (m_propertyname.Length() == 0)
|
||||||
|
{
|
||||||
|
bFound = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_bFindMaterial)
|
||||||
|
{
|
||||||
|
if (client_info->m_auxilary_info)
|
||||||
|
{
|
||||||
|
bFound = (m_propertyname== ((char*)client_info->m_auxilary_info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bFound)
|
||||||
{
|
{
|
||||||
m_hitObject = hitKXObj;
|
m_hitObject = hitKXObj;
|
||||||
m_hitPosition = result->m_hitPoint;
|
m_hitPosition = result->m_hitPoint;
|
||||||
@@ -154,12 +184,41 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
|
|||||||
m_hitUV = result->m_hitUV;
|
m_hitUV = result->m_hitUV;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true; // object must be visible to trigger
|
return true; // object must be visible to trigger
|
||||||
//return false; // occluded objects can trigger
|
//return false; // occluded objects can trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function is used to pre-filter the object before casting the ray on them.
|
||||||
|
* This is useful for "X-Ray" option when we want to see "through" unwanted object.
|
||||||
|
*/
|
||||||
|
bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
|
||||||
|
{
|
||||||
|
if (client->m_type > KX_ClientObjectInfo::ACTOR)
|
||||||
|
{
|
||||||
|
// Unknown type of object, skip it.
|
||||||
|
// Should not occur as the sensor objects are filtered in RayTest()
|
||||||
|
printf("Invalid client type %d found ray casting\n", client->m_type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (m_bXRay && m_propertyname.Length() != 0)
|
||||||
|
{
|
||||||
|
if (m_bFindMaterial)
|
||||||
|
{
|
||||||
|
// not quite correct: an object may have multiple material
|
||||||
|
// should check all the material and not only the first one
|
||||||
|
if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
|
bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
|
||||||
{
|
{
|
||||||
@@ -384,7 +443,10 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = {
|
|||||||
KX_PYATTRIBUTE_RO_FUNCTION("hitPosition", KX_MouseFocusSensor, pyattr_get_hit_position),
|
KX_PYATTRIBUTE_RO_FUNCTION("hitPosition", KX_MouseFocusSensor, pyattr_get_hit_position),
|
||||||
KX_PYATTRIBUTE_RO_FUNCTION("hitNormal", KX_MouseFocusSensor, pyattr_get_hit_normal),
|
KX_PYATTRIBUTE_RO_FUNCTION("hitNormal", KX_MouseFocusSensor, pyattr_get_hit_normal),
|
||||||
KX_PYATTRIBUTE_RO_FUNCTION("hitUV", KX_MouseFocusSensor, pyattr_get_hit_uv),
|
KX_PYATTRIBUTE_RO_FUNCTION("hitUV", KX_MouseFocusSensor, pyattr_get_hit_uv),
|
||||||
KX_PYATTRIBUTE_BOOL_RW("usePulseFocus", KX_MouseFocusSensor,m_bTouchPulse),
|
KX_PYATTRIBUTE_BOOL_RW("usePulseFocus", KX_MouseFocusSensor, m_bTouchPulse),
|
||||||
|
KX_PYATTRIBUTE_BOOL_RW("useXRay", KX_MouseFocusSensor, m_bXRay),
|
||||||
|
KX_PYATTRIBUTE_BOOL_RW("useMaterial", KX_MouseFocusSensor, m_bFindMaterial),
|
||||||
|
KX_PYATTRIBUTE_STRING_RW("propName", 0, MAX_PROP_NAME, false, KX_MouseFocusSensor, m_propertyname),
|
||||||
{ NULL } //Sentinel
|
{ NULL } //Sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
|
|||||||
short int mousemode,
|
short int mousemode,
|
||||||
int focusmode,
|
int focusmode,
|
||||||
bool bTouchPulse,
|
bool bTouchPulse,
|
||||||
|
const STR_String& propname,
|
||||||
|
bool bFindMaterial,
|
||||||
|
bool bXRay,
|
||||||
KX_Scene* kxscene,
|
KX_Scene* kxscene,
|
||||||
KX_KetsjiEngine* kxengine,
|
KX_KetsjiEngine* kxengine,
|
||||||
SCA_IObject* gameobj);
|
SCA_IObject* gameobj);
|
||||||
@@ -88,7 +91,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
|
bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
|
||||||
bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
|
bool NeedRayCast(KX_ClientObjectInfo* client);
|
||||||
|
|
||||||
const MT_Point3& RaySource() const;
|
const MT_Point3& RaySource() const;
|
||||||
const MT_Point3& RayTarget() const;
|
const MT_Point3& RayTarget() const;
|
||||||
@@ -133,6 +136,21 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
|
|||||||
*/
|
*/
|
||||||
bool m_bTouchPulse;
|
bool m_bTouchPulse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags get trought other objects
|
||||||
|
*/
|
||||||
|
bool m_bXRay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags material
|
||||||
|
*/
|
||||||
|
bool m_bFindMaterial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property or material name
|
||||||
|
*/
|
||||||
|
STR_String m_propertyname;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags whether the previous test evaluated positive.
|
* Flags whether the previous test evaluated positive.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user