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
|
||||
|
||||
.. 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);
|
||||
}
|
||||
|
||||
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);
|
||||
uiItemR(split, ptr, "mouse_event", 0, NULL, ICON_NONE);
|
||||
|
||||
if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY)
|
||||
{
|
||||
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)
|
||||
@@ -1273,7 +1293,7 @@ static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
|
||||
draw_sensor_message(box, ptr);
|
||||
break;
|
||||
case SENS_MOUSE:
|
||||
draw_sensor_mouse(box, ptr);
|
||||
draw_sensor_mouse(box, ptr, C);
|
||||
break;
|
||||
case SENS_NEAR:
|
||||
draw_sensor_near(box, ptr);
|
||||
|
@@ -57,7 +57,9 @@ typedef struct bMouseSensor {
|
||||
short type;
|
||||
short flag;
|
||||
short pad1;
|
||||
short pad2;
|
||||
short mode; /* flag to choose material or property */
|
||||
char propname[64];
|
||||
char matname[64];
|
||||
} bMouseSensor;
|
||||
|
||||
/* DEPRECATED */
|
||||
|
@@ -405,6 +405,12 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
|
||||
{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");
|
||||
RNA_def_struct_ui_text(srna, "Mouse Sensor", "Sensor to detect mouse events");
|
||||
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_ui_text(prop, "Pulse", "Moving the mouse over a different object generates a pulse");
|
||||
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)
|
||||
|
@@ -329,12 +329,19 @@ void BL_ConvertSensors(struct Object* blenderobject,
|
||||
gameobj);
|
||||
} else {
|
||||
/* 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,
|
||||
startx,
|
||||
starty,
|
||||
keytype,
|
||||
trackfocus,
|
||||
(bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false,
|
||||
checkname,
|
||||
bFindMaterial,
|
||||
bXRay,
|
||||
kxscene,
|
||||
kxengine,
|
||||
gameobj);
|
||||
|
@@ -60,15 +60,21 @@
|
||||
KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
|
||||
int startx,
|
||||
int starty,
|
||||
short int mousemode,
|
||||
int focusmode,
|
||||
bool bTouchPulse,
|
||||
KX_Scene* kxscene,
|
||||
KX_KetsjiEngine *kxengine,
|
||||
SCA_IObject* gameobj)
|
||||
short int mousemode,
|
||||
int focusmode,
|
||||
bool bTouchPulse,
|
||||
const STR_String& propname,
|
||||
bool bFindMaterial,
|
||||
bool bXRay,
|
||||
KX_Scene* kxscene,
|
||||
KX_KetsjiEngine *kxengine,
|
||||
SCA_IObject* gameobj)
|
||||
: SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj),
|
||||
m_focusmode(focusmode),
|
||||
m_bTouchPulse(bTouchPulse),
|
||||
m_propertyname(propname),
|
||||
m_bFindMaterial(bFindMaterial),
|
||||
m_bXRay(bXRay),
|
||||
m_kxscene(kxscene),
|
||||
m_kxengine(kxengine)
|
||||
{
|
||||
@@ -146,20 +152,73 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
|
||||
* self-hits are excluded by setting the correct ignore-object.)
|
||||
* Hitspots now become valid. */
|
||||
KX_GameObject* thisObj = (KX_GameObject*) GetParent();
|
||||
|
||||
bool bFound = false;
|
||||
|
||||
if ((m_focusmode == 2) || hitKXObj == thisObj)
|
||||
{
|
||||
m_hitObject = hitKXObj;
|
||||
m_hitPosition = result->m_hitPoint;
|
||||
m_hitNormal = result->m_hitNormal;
|
||||
m_hitUV = result->m_hitUV;
|
||||
return true;
|
||||
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_hitPosition = result->m_hitPoint;
|
||||
m_hitNormal = result->m_hitNormal;
|
||||
m_hitUV = result->m_hitUV;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true; // object must be visible to 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)
|
||||
{
|
||||
@@ -384,7 +443,10 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = {
|
||||
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("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
|
||||
};
|
||||
|
||||
|
@@ -57,6 +57,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
|
||||
short int mousemode,
|
||||
int focusmode,
|
||||
bool bTouchPulse,
|
||||
const STR_String& propname,
|
||||
bool bFindMaterial,
|
||||
bool bXRay,
|
||||
KX_Scene* kxscene,
|
||||
KX_KetsjiEngine* kxengine,
|
||||
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 NeedRayCast(KX_ClientObjectInfo* client) { return true; }
|
||||
bool NeedRayCast(KX_ClientObjectInfo* client);
|
||||
|
||||
const MT_Point3& RaySource() const;
|
||||
const MT_Point3& RayTarget() const;
|
||||
@@ -133,6 +136,21 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user