Skip to content

Commit

Permalink
Merge pull request #561 from thestonefox/feat/tag-script-policy-lists
Browse files Browse the repository at this point in the history
feat(PolicyList): add ability to have multiple tag/script ignore checks
  • Loading branch information
thestonefox authored Sep 12, 2016
2 parents 61cfbf2 + 5f99aed commit 1d0b01c
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 25 deletions.
8 changes: 6 additions & 2 deletions Assets/VRTK/Scripts/Abstractions/VRTK_DestinationMarker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public abstract class VRTK_DestinationMarker : MonoBehaviour
public event DestinationMarkerEventHandler DestinationMarkerSet;

protected string invalidTargetWithTagOrClass;
protected VRTK_TagOrScriptPolicyList invalidTagOrScriptListPolicy;
protected float navMeshCheckDistance;
protected bool headsetPositionCompensation;

Expand Down Expand Up @@ -80,12 +81,15 @@ public virtual void OnDestinationMarkerSet(DestinationMarkerEventArgs e)
}

/// <summary>
/// The SetInvalidTarget method is used to set objects that contain the given tag or class matching the name as invalid destination targets.
/// The SetInvalidTarget method is used to set objects that contain the given tag or class matching the name as invalid destination targets. It can also accept a VRTK_TagOrScriptPolicyList for a more custom level of policy management.
/// </summary>
/// <param name="name">The name of the tag or class that is the invalid target.</param>
public virtual void SetInvalidTarget(string name)
/// <param name="list">The Tag Or Script list policy to check the set operation on.</param>
public virtual void SetInvalidTarget(string name, VRTK_TagOrScriptPolicyList list = null)
{
invalidTargetWithTagOrClass = name;
invalidTagOrScriptListPolicy = list;

}

/// <summary>
Expand Down
12 changes: 8 additions & 4 deletions Assets/VRTK/Scripts/Abstractions/VRTK_WorldPointer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public enum pointerVisibilityStates
public bool handlePlayAreaCursorCollisions = false;
[Tooltip("A string that specifies an object Tag or the name of a Script attached to an object and notifies the play area cursor to ignore collisions with the object.")]
public string ignoreTargetWithTagOrClass;
[Tooltip("A specified VRTK_TagOrScriptPolicyList to use to determine whether the play area cursor collisions will be acted upon. If a list is provided then the 'Ignore Target With Tag Or Class' parameter will be ignored.")]
public VRTK_TagOrScriptPolicyList targetTagOrScriptListPolicy;
[Tooltip("Determines when the pointer beam should be displayed.")]
public pointerVisibilityStates pointerVisibility = pointerVisibilityStates.On_When_Active;
[Tooltip("If this is checked then the pointer beam will be activated on first press of the pointer alias button and will stay active until the pointer alias button is pressed again. The destination set event is emitted when the beam is deactivated on the second button press.")]
Expand Down Expand Up @@ -307,7 +309,7 @@ protected virtual bool ValidDestination(Transform target, Vector3 destinationPos
{
validNavMeshLocation = true;
}
return (validNavMeshLocation && target && target.tag != invalidTargetWithTagOrClass && target.GetComponent(invalidTargetWithTagOrClass) == null);
return (validNavMeshLocation && target && !(Utilities.TagOrScriptCheck(target.gameObject, invalidTagOrScriptListPolicy, invalidTargetWithTagOrClass)));
}

private bool PointerActivatesUseAction(VRTK_InteractableObject io)
Expand Down Expand Up @@ -431,7 +433,7 @@ private void InitPlayAreaCursor()

var playAreaCursorScript = playAreaCursor.AddComponent<VRTK_PlayAreaCollider>();
playAreaCursorScript.SetParent(gameObject);
playAreaCursorScript.SetIgnoreTarget(ignoreTargetWithTagOrClass);
playAreaCursorScript.SetIgnoreTarget(ignoreTargetWithTagOrClass, targetTagOrScriptListPolicy);
playAreaCursor.layer = LayerMask.NameToLayer("Ignore Raycast");

var playAreaBoundaryX = playArea.transform.localScale.x / 2;
Expand Down Expand Up @@ -467,20 +469,22 @@ public class VRTK_PlayAreaCollider : MonoBehaviour
{
private GameObject parent;
private string ignoreTargetWithTagOrClass;
private VRTK_TagOrScriptPolicyList targetTagOrScriptListPolicy;

public void SetParent(GameObject setParent)
{
parent = setParent;
}

public void SetIgnoreTarget(string ignore)
public void SetIgnoreTarget(string ignore, VRTK_TagOrScriptPolicyList list = null)
{
ignoreTargetWithTagOrClass = ignore;
targetTagOrScriptListPolicy = list;
}

private bool ValidTarget(Collider collider)
{
return (!collider.GetComponent<VRTK_PlayerObject>() & collider.tag != ignoreTargetWithTagOrClass && collider.GetComponent(ignoreTargetWithTagOrClass) == null);
return (!collider.GetComponent<VRTK_PlayerObject>() && !(Utilities.TagOrScriptCheck(collider.gameObject, targetTagOrScriptListPolicy, ignoreTargetWithTagOrClass)));
}

private void OnTriggerStay(Collider collider)
Expand Down
12 changes: 12 additions & 0 deletions Assets/VRTK/Scripts/Helper/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,17 @@ public static float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n)
Vector3.Dot(n, Vector3.Cross(v1, v2)),
Vector3.Dot(v1, v2)) * Mathf.Rad2Deg;
}

public static bool TagOrScriptCheck(GameObject obj, VRTK_TagOrScriptPolicyList tagOrScriptList, string ignoreString)
{
if (tagOrScriptList)
{
return tagOrScriptList.Find(obj);
}
else
{
return (obj.tag == ignoreString || obj.GetComponent(ignoreString) != null);
}
}
}
}
25 changes: 15 additions & 10 deletions Assets/VRTK/Scripts/Helper/VRTK_EventSystemVRInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,22 @@ private bool IsHovering(VRTK_UIPointer pointer)
return false;
}

private bool ShouldIgnoreElement(GameObject obj, string ignoreCanvasWithTagOrClass)
private bool ShouldIgnoreElement(GameObject obj, string ignoreCanvasWithTagOrClass, VRTK_TagOrScriptPolicyList canvasTagOrScriptListPolicy)
{
var canvas = obj.GetComponentInParent<Canvas>();
return (canvas && (canvas.gameObject.tag == ignoreCanvasWithTagOrClass || canvas.GetComponent(ignoreCanvasWithTagOrClass) != null));
if (!canvas)
{
return false;
}

return (Utilities.TagOrScriptCheck(canvas.gameObject, canvasTagOrScriptListPolicy, ignoreCanvasWithTagOrClass));
}

private void Hover(VRTK_UIPointer pointer, List<RaycastResult> results)
{
if (pointer.pointerEventData.pointerEnter)
{
if (ShouldIgnoreElement(pointer.pointerEventData.pointerEnter, pointer.ignoreCanvasWithTagOrClass))
if (ShouldIgnoreElement(pointer.pointerEventData.pointerEnter, pointer.ignoreCanvasWithTagOrClass, pointer.canvasTagOrScriptListPolicy))
{
return;
}
Expand All @@ -105,7 +110,7 @@ private void Hover(VRTK_UIPointer pointer, List<RaycastResult> results)
{
foreach (var result in results)
{
if (ShouldIgnoreElement(result.gameObject, pointer.ignoreCanvasWithTagOrClass))
if (ShouldIgnoreElement(result.gameObject, pointer.ignoreCanvasWithTagOrClass, pointer.canvasTagOrScriptListPolicy))
{
continue;
}
Expand Down Expand Up @@ -152,7 +157,7 @@ private void Click(VRTK_UIPointer pointer, List<RaycastResult> results)

if (pointer.pointerEventData.pointerPress)
{
if (ShouldIgnoreElement(pointer.pointerEventData.pointerPress, pointer.ignoreCanvasWithTagOrClass))
if (ShouldIgnoreElement(pointer.pointerEventData.pointerPress, pointer.ignoreCanvasWithTagOrClass, pointer.canvasTagOrScriptListPolicy))
{
return;
}
Expand All @@ -176,7 +181,7 @@ private void Click(VRTK_UIPointer pointer, List<RaycastResult> results)
{
foreach (var result in results)
{
if (ShouldIgnoreElement(result.gameObject, pointer.ignoreCanvasWithTagOrClass))
if (ShouldIgnoreElement(result.gameObject, pointer.ignoreCanvasWithTagOrClass, pointer.canvasTagOrScriptListPolicy))
{
continue;
}
Expand All @@ -199,7 +204,7 @@ private void Drag(VRTK_UIPointer pointer, List<RaycastResult> results)

if (pointer.pointerEventData.pointerDrag)
{
if (ShouldIgnoreElement(pointer.pointerEventData.pointerDrag, pointer.ignoreCanvasWithTagOrClass))
if (ShouldIgnoreElement(pointer.pointerEventData.pointerDrag, pointer.ignoreCanvasWithTagOrClass, pointer.canvasTagOrScriptListPolicy))
{
return;
}
Expand All @@ -226,7 +231,7 @@ private void Drag(VRTK_UIPointer pointer, List<RaycastResult> results)
{
foreach (var result in results)
{
if (ShouldIgnoreElement(result.gameObject, pointer.ignoreCanvasWithTagOrClass))
if (ShouldIgnoreElement(result.gameObject, pointer.ignoreCanvasWithTagOrClass, pointer.canvasTagOrScriptListPolicy))
{
continue;
}
Expand All @@ -252,14 +257,14 @@ private void Scroll(VRTK_UIPointer pointer, List<RaycastResult> results)
if (pointer.pointerEventData.scrollDelta != Vector2.zero)
{
var target = ExecuteEvents.ExecuteHierarchy(result.gameObject, pointer.pointerEventData, ExecuteEvents.scrollHandler);
if(target)
if (target)
{
scrollWheelVisible = true;
}
}
}

if(pointer.controllerRenderModel)
if (pointer.controllerRenderModel)
{
VRTK_SDK_Bridge.SetControllerRenderModelWheel(pointer.controllerRenderModel, scrollWheelVisible);
}
Expand Down
6 changes: 4 additions & 2 deletions Assets/VRTK/Scripts/VRTK_BasicTeleport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class VRTK_BasicTeleport : MonoBehaviour
public bool headsetPositionCompensation = true;
[Tooltip("A string that specifies an object Tag or the name of a Script attached to an object and notifies the teleporter that the destination is to be ignored so the user cannot teleport to that location. It also ensure the pointer colour is set to the miss colour.")]
public string ignoreTargetWithTagOrClass;
[Tooltip("A specified VRTK_TagOrScriptPolicyList to use to determine whether destination targets will be acted upon by the Teleporter. If a list is provided then the 'Ignore Target With Tag Or Class' parameter will be ignored.")]
public VRTK_TagOrScriptPolicyList targetTagOrScriptListPolicy;
[Tooltip("The max distance the nav mesh edge can be from the teleport destination to be considered valid. If a value of `0` is given then the nav mesh restriction will be ignored.")]
public float navMeshLimitDistance = 0f;

Expand Down Expand Up @@ -66,7 +68,7 @@ public void InitDestinationSetListener(GameObject markerMaker, bool register)
if (register)
{
worldMarker.DestinationMarkerSet += new DestinationMarkerEventHandler(DoTeleport);
worldMarker.SetInvalidTarget(ignoreTargetWithTagOrClass);
worldMarker.SetInvalidTarget(ignoreTargetWithTagOrClass, targetTagOrScriptListPolicy);
worldMarker.SetNavMeshCheckDistance(navMeshLimitDistance);
worldMarker.SetHeadsetPositionCompensation(headsetPositionCompensation);
}
Expand Down Expand Up @@ -149,7 +151,7 @@ protected virtual bool ValidLocation(Transform target, Vector3 destinationPositi
validNavMeshLocation = true;
}

return (validNavMeshLocation && target && target.tag != ignoreTargetWithTagOrClass && target.GetComponent(ignoreTargetWithTagOrClass) == null);
return (validNavMeshLocation && target && !(Utilities.TagOrScriptCheck(target.gameObject, targetTagOrScriptListPolicy, ignoreTargetWithTagOrClass)));
}

protected virtual void DoTeleport(object sender, DestinationMarkerEventArgs e)
Expand Down
4 changes: 3 additions & 1 deletion Assets/VRTK/Scripts/VRTK_HeadsetCollision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class VRTK_HeadsetCollision : MonoBehaviour
{
[Tooltip("A string that specifies an object Tag or the name of a Script attached to an object and will be ignored on headset collision.")]
public string ignoreTargetWithTagOrClass;
[Tooltip("A specified VRTK_TagOrScriptPolicyList to use to determine whether any objects will be acted upon by the Headset Collision. If a list is provided then the 'Ignore Target With Tag Or Class' parameter will be ignored.")]
public VRTK_TagOrScriptPolicyList targetTagOrScriptListPolicy;

/// <summary>
/// Emitted when the user's headset collides with another game object.
Expand Down Expand Up @@ -106,7 +108,7 @@ private HeadsetCollisionEventArgs SetHeadsetCollisionEvent(Collider collider, Tr

private bool ValidTarget(Transform target)
{
return (target && target.tag != ignoreTargetWithTagOrClass && target.GetComponent(ignoreTargetWithTagOrClass) == null);
return (target && !(Utilities.TagOrScriptCheck(target.gameObject, targetTagOrScriptListPolicy, ignoreTargetWithTagOrClass)));
}

private void OnTriggerStay(Collider collider)
Expand Down
3 changes: 3 additions & 0 deletions Assets/VRTK/Scripts/VRTK_HeadsetCollisionFade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class VRTK_HeadsetCollisionFade : MonoBehaviour
public Color fadeColor = Color.black;
[Tooltip("A string that specifies an object Tag or the name of a Script attached to an object and will prevent the object from fading the headset view on collision.")]
public string ignoreTargetWithTagOrClass;
[Tooltip("A specified VRTK_TagOrScriptPolicyList to use to determine whether any objects will be acted upon by the Headset Collision Fade. If a list is provided then the 'Ignore Target With Tag Or Class' parameter will be ignored.")]
public VRTK_TagOrScriptPolicyList targetTagOrScriptListPolicy;

private VRTK_HeadsetCollision headsetCollision;
private VRTK_HeadsetFade headsetFade;
Expand All @@ -32,6 +34,7 @@ private void OnEnable()
{
headsetCollision = gameObject.AddComponent<VRTK_HeadsetCollision>();
headsetCollision.ignoreTargetWithTagOrClass = ignoreTargetWithTagOrClass;
headsetCollision.targetTagOrScriptListPolicy = targetTagOrScriptListPolicy;

headsetFade = gameObject.AddComponent<VRTK_HeadsetFade>();

Expand Down
120 changes: 120 additions & 0 deletions Assets/VRTK/Scripts/VRTK_TagOrScriptPolicyList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Tag Or Script Policy List|Scripts|0225
namespace VRTK
{
using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// The Tag Or Script Policy List allows to create a list of either tag names or script names that can be checked against to see if another operation is permitted.
/// </summary>
/// <remarks>
/// A number of other scripts can use a Tag Or Script Policy List to determine if an operation is permitted based on whether a game object has a tag applied or a script component on it.
///
/// For example, the Teleporter scripts can ignore game object targets as a teleport location if the game object contains a tag that is in the identifiers list and the policy is set to ignore.
///
/// Or the teleporter can only allow teleport to targets that contain a tag that is in the identifiers list and the policy is set to include.
///
/// Add the Tag Or Script Policy List script to a game object (preferably the same component utilising the list) and then configure the list accordingly.
///
/// Then in the component that has a Tag Or Script Policy List paramter (e.g. BasicTeleporter has `Target Tag Or Script List Policy`) simply select the list that has been created and defined.
/// </remarks>
public class VRTK_TagOrScriptPolicyList : MonoBehaviour
{
/// <summary>
/// The operation to apply on the list of identifiers.
/// </summary>
/// <param name="Ignore">Will ignore any game objects that contain either a tag or script component that is included in the identifiers list.</param>
/// <param name="Include">Will only include game objects that contain either a tag or script component that is included in the identifiers list.</param>
public enum OperationTypes
{
Ignore,
Include
}

/// <summary>
/// The types of element that can be checked against.
/// </summary>
/// <param name="Tag">The tag applied to the game object.</param>
/// <param name="Script">A script component added to the game object.</param>
/// <param name="Tag_Or_Script">Either a tag applied to the game object or a script component added to the game object.</param>
public enum CheckTypes
{
Tag,
Script,
Tag_Or_Script
}

[Tooltip("The operation to apply on the list of identifiers.")]
public OperationTypes operation = OperationTypes.Ignore;
[Tooltip("The element type on the game object to check against.")]
public CheckTypes checkType = CheckTypes.Tag;
[Tooltip("A list of identifiers to check for against the given check type (either tag or script).")]
public List<string> identifiers = new List<string>() { "" };

/// <summary>
/// The Find method performs the set operation to determine if the given game object contains one of the identifiers on the set check type.
/// </summary>
/// <remarks>
/// For instance, if the Operation is `Ignore` and the Check Type is `Tag` then the Find method will attempt to see if the given game object has a tag that matches one of the identifiers.
/// </remarks>
/// <param name="obj">The game object to check if it has a tag or script that is listed in the identifiers list.</param>
/// <returns>If the operation is `Ignore` and the game object is matched by an identifier from the list then it returns true. If the operation is `Include` and the game object is not matched by an identifier from the list then it returns true.</returns>
public bool Find(GameObject obj)
{
if (operation == OperationTypes.Ignore)
{
return TypeCheck(obj, true);
}
else
{
return TypeCheck(obj, false);
}
}

private bool ScriptCheck(GameObject obj, bool returnState)
{
foreach (var identifier in identifiers)
{
if (obj.GetComponent(identifier))
{
return returnState;
}
}
return !returnState;
}

private bool TagCheck(GameObject obj, bool returnState)
{
if (returnState)
{
return identifiers.Contains(obj.tag);
}
else
{
return !identifiers.Contains(obj.tag);
}
}

private bool TypeCheck(GameObject obj, bool returnState)
{
switch (checkType)
{
case CheckTypes.Script:
return ScriptCheck(obj, returnState);
case CheckTypes.Tag:
return TagCheck(obj, returnState);
case CheckTypes.Tag_Or_Script:
if ((returnState && ScriptCheck(obj, returnState)) || (!returnState && !ScriptCheck(obj, returnState)))
{
return returnState;
}
if ((returnState && TagCheck(obj, returnState)) || (!returnState && !TagCheck(obj, returnState)))
{
return returnState;
}
break;
}
return !returnState;
}
}
}
Loading

0 comments on commit 1d0b01c

Please sign in to comment.