Skip to content

Commit

Permalink
feat(SnapDropZone): add valid highlight color option
Browse files Browse the repository at this point in the history
The new Valid Highlight Color will be used when a valid object is
hovering over an already highlighted snap drop zone. For instance
if the Highlight Always Active option is on, it will use the
Highlight Color (which can be set to a different colour) and then
when a valid object passes into the Snap Drop Zone the Valid
Highlight Color will be used.

This also fixes an issue with the OnEnter event as it wasn't
previously being emitted if the Highlight Always On was set to
true, until the object was snapped and then unsnapped.
  • Loading branch information
thestonefox committed Sep 6, 2017
1 parent d02fcbd commit 0fbef07
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 54 deletions.
3 changes: 2 additions & 1 deletion Assets/VRTK/Documentation/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ Provides a predefined zone where a valid interactable object can be dropped and
* **Snap Duration:** The amount of time it takes for the object being snapped to move into the new snapped position, rotation and scale.
* **Apply Scaling On Snap:** If this is checked then the scaled size of the snap drop zone will be applied to the object that is snapped to it.
* **Clone New On Unsnap:** If this is checked then when the snapped object is unsnapped from the drop zone, a clone of the unsnapped object will be snapped back into the drop zone.
* **Highlight Color:** The colour to use when showing the snap zone is active.
* **Highlight Color:** The colour to use when showing the snap zone is active. This is used as the highlight colour when no object is hovering but `Highlight Always Active` is true.
* **Valid Highlight Color:** The colour to use when showing the snap zone is active and a valid object is hovering. If this is `Color.clear` then the `Highlight Color` will be used.
* **Highlight Always Active:** The highlight object will always be displayed when the snap drop zone is available even if a valid item isn't being hovered over.
* **Valid Object List Policy:** A specified VRTK_PolicyList to use to determine which interactable objects will be snapped to the snap drop zone on release.
* **Display Drop Zone In Editor:** If this is checked then the drop zone highlight section will be displayed in the scene editor window.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,55 @@

public class SnapDropZoneGroup_Switcher : MonoBehaviour
{
private GameObject cubeZone;
private GameObject sphereZone;
private VRTK_SnapDropZone cubeZone;
private VRTK_SnapDropZone sphereZone;

private void Start()
{
cubeZone = transform.Find("Cube_SnapDropZone").gameObject;
sphereZone = transform.Find("Sphere_SnapDropZone").gameObject;

cubeZone.GetComponent<VRTK_SnapDropZone>().ObjectEnteredSnapDropZone += new SnapDropZoneEventHandler(DoCubeZoneSnapped);
cubeZone.GetComponent<VRTK_SnapDropZone>().ObjectSnappedToDropZone += new SnapDropZoneEventHandler(DoCubeZoneSnapped);
cubeZone.GetComponent<VRTK_SnapDropZone>().ObjectExitedSnapDropZone += new SnapDropZoneEventHandler(DoCubeZoneUnsnapped);
cubeZone.GetComponent<VRTK_SnapDropZone>().ObjectUnsnappedFromDropZone += new SnapDropZoneEventHandler(DoCubeZoneUnsnapped);

sphereZone.GetComponent<VRTK_SnapDropZone>().ObjectEnteredSnapDropZone += new SnapDropZoneEventHandler(DoSphereZoneSnapped);
sphereZone.GetComponent<VRTK_SnapDropZone>().ObjectSnappedToDropZone += new SnapDropZoneEventHandler(DoSphereZoneSnapped);
sphereZone.GetComponent<VRTK_SnapDropZone>().ObjectExitedSnapDropZone += new SnapDropZoneEventHandler(DoSphereZoneUnsnapped);
sphereZone.GetComponent<VRTK_SnapDropZone>().ObjectUnsnappedFromDropZone += new SnapDropZoneEventHandler(DoSphereZoneUnsnapped);
cubeZone = transform.Find("Cube_SnapDropZone").gameObject.GetComponent<VRTK_SnapDropZone>();
sphereZone = transform.Find("Sphere_SnapDropZone").GetComponent<VRTK_SnapDropZone>();

cubeZone.ObjectEnteredSnapDropZone += new SnapDropZoneEventHandler(DoCubeZoneSnapped);
cubeZone.ObjectSnappedToDropZone += new SnapDropZoneEventHandler(DoCubeZoneSnapped);
cubeZone.ObjectExitedSnapDropZone += new SnapDropZoneEventHandler(DoCubeZoneUnsnapped);
cubeZone.ObjectUnsnappedFromDropZone += new SnapDropZoneEventHandler(DoCubeZoneUnsnapped);

sphereZone.ObjectEnteredSnapDropZone += new SnapDropZoneEventHandler(DoSphereZoneSnapped);
sphereZone.ObjectSnappedToDropZone += new SnapDropZoneEventHandler(DoSphereZoneSnapped);
sphereZone.ObjectExitedSnapDropZone += new SnapDropZoneEventHandler(DoSphereZoneUnsnapped);
sphereZone.ObjectUnsnappedFromDropZone += new SnapDropZoneEventHandler(DoSphereZoneUnsnapped);
}

private void DoCubeZoneSnapped(object sender, SnapDropZoneEventArgs e)
{
sphereZone.SetActive(false);
if (sphereZone.GetCurrentSnappedObject() == null)
{
sphereZone.gameObject.SetActive(false);
}
}

private void DoCubeZoneUnsnapped(object sender, SnapDropZoneEventArgs e)
{
sphereZone.SetActive(true);
if (cubeZone.GetCurrentSnappedObject() == null)
{
sphereZone.gameObject.SetActive(true);
}
}

private void DoSphereZoneSnapped(object sender, SnapDropZoneEventArgs e)
{
cubeZone.SetActive(false);
if (cubeZone.GetCurrentSnappedObject() == null)
{
cubeZone.gameObject.SetActive(false);
}
}

private void DoSphereZoneUnsnapped(object sender, SnapDropZoneEventArgs e)
{
cubeZone.SetActive(true);
if (sphereZone.GetCurrentSnappedObject() == null)
{
cubeZone.gameObject.SetActive(true);
}
}
}
}
94 changes: 59 additions & 35 deletions Assets/VRTK/Prefabs/Internal/Scripts/VRTK_SnapDropZone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ public enum SnapTypes
public bool applyScalingOnSnap = false;
[Tooltip("If this is checked then when the snapped object is unsnapped from the drop zone, a clone of the unsnapped object will be snapped back into the drop zone.")]
public bool cloneNewOnUnsnap = false;
[Tooltip("The colour to use when showing the snap zone is active.")]
public Color highlightColor;
[Tooltip("The colour to use when showing the snap zone is active. This is used as the highlight colour when no object is hovering but `Highlight Always Active` is true.")]
public Color highlightColor = Color.clear;
[Tooltip("The colour to use when showing the snap zone is active and a valid object is hovering. If this is `Color.clear` then the `Highlight Color` will be used.")]
public Color validHighlightColor = Color.clear;
[Tooltip("The highlight object will always be displayed when the snap drop zone is available even if a valid item isn't being hovered over.")]
public bool highlightAlwaysActive = false;
[Tooltip("A specified VRTK_PolicyList to use to determine which interactable objects will be snapped to the snap drop zone on release.")]
Expand Down Expand Up @@ -242,7 +244,14 @@ public virtual void ForceUnsnap()
/// <returns>Returns true if a valid object is currently in the snap drop zone area.</returns>
public virtual bool ValidSnappableObjectIsHovering()
{
return currentValidSnapInteractableObjects.Count > 0;
for (int i = 0; i < currentValidSnapInteractableObjects.Count; i++)
{
if (currentValidSnapInteractableObjects[i].IsGrabbed())
{
return true;
}
}
return false;
}

/// <summary>
Expand Down Expand Up @@ -295,7 +304,7 @@ public virtual List<VRTK_InteractableObject> GetHoveringInteractableObjects()
/// <returns>The GameObject that is currently snapped in the snap drop zone area.</returns>
public virtual GameObject GetCurrentSnappedObject()
{
return currentSnappedObject.gameObject;
return (currentSnappedObject != null ? currentSnappedObject.gameObject : null);
}

/// <summary>
Expand Down Expand Up @@ -365,7 +374,7 @@ protected virtual void OnDisable()
}

ForceUnsnap();

SetHighlightObjectActive(false);
UnregisterAllUngrabEvents();
}

Expand Down Expand Up @@ -397,6 +406,13 @@ protected virtual void CheckCanSnap(VRTK_InteractableObject interactableObjectCh
if (!isSnapped && ValidSnapObject(interactableObjectCheck, true))
{
ToggleHighlight(interactableObjectCheck, true);
interactableObjectCheck.SetSnapDropZoneHover(this, true);
ToggleHighlightColor();
if (!willSnap)
{
OnObjectEnteredSnapDropZone(SetSnapDropZoneEvent(interactableObjectCheck.gameObject));
}
willSnap = true;
}
}
}
Expand All @@ -410,11 +426,21 @@ protected virtual void CheckCanUnsnap(VRTK_InteractableObject interactableObject
ForceUnsnap();
}

RemoveCurrentValidSnapObject(interactableObjectCheck);

if (!ValidSnappableObjectIsHovering())
{
ToggleHighlight(interactableObjectCheck, false);
willSnap = false;
}

interactableObjectCheck.SetSnapDropZoneHover(this, false);

if (ValidSnapObject(interactableObjectCheck, true))
{
ToggleHighlightColor();
OnObjectExitedSnapDropZone(SetSnapDropZoneEvent(interactableObjectCheck.gameObject));
}
RemoveCurrentValidSnapObject(interactableObjectCheck);
}
}

Expand Down Expand Up @@ -468,6 +494,7 @@ protected virtual void SetObjectHighlight()
if (highlightAlwaysActive && !isSnapped && !isHighlighted)
{
SetHighlightObjectActive(true);
ToggleHighlightColor();
}

if (!highlightAlwaysActive && isHighlighted && !ValidSnappableObjectIsHovering())
Expand All @@ -476,6 +503,14 @@ protected virtual void SetObjectHighlight()
}
}

protected virtual void ToggleHighlightColor()
{
if (Application.isPlaying && highlightAlwaysActive && !isSnapped && objectHighlighter != null)
{
objectHighlighter.Highlight((willSnap && validHighlightColor != Color.clear ? validHighlightColor : highlightColor));
}
}

protected virtual void CreateHighlightersInEditor()
{
if (VRTK_SharedMethods.IsEditTime())
Expand Down Expand Up @@ -602,6 +637,7 @@ protected virtual void SnapObject(VRTK_InteractableObject interactableObjectChec

//Force reset isSnapped if the item is grabbed but isSnapped is still true
isSnapped = (isSnapped && interactableObjectCheck != null && interactableObjectCheck.IsGrabbed() ? false : isSnapped);
willSnap = !isSnapped;
wasSnapped = false;
}

Expand All @@ -615,7 +651,6 @@ protected virtual void CreatePermanentClone()
objectToClone = Instantiate(currentSnappedObject.gameObject);
objectToClone.transform.position = highlightContainer.transform.position;
objectToClone.transform.rotation = highlightContainer.transform.rotation;
objectToClone.transform.localScale = highlightContainer.transform.localScale;
Collider[] clonedObjectStates = currentSnappedObject.GetComponentsInChildren<Collider>();
clonedObjectColliderStates = new bool[clonedObjectStates.Length];
for (int i = 0; i < clonedObjectStates.Length; i++)
Expand Down Expand Up @@ -802,6 +837,19 @@ protected virtual void AddCurrentValidSnapObject(VRTK_InteractableObject givenOb
}
}

protected virtual void RemoveCurrentValidSnapObject(VRTK_InteractableObject givenObject)
{
if (givenObject != null)
{
if (currentValidSnapInteractableObjects.Contains(givenObject))
{
givenObject.InteractableObjectGrabbed -= InteractableObjectGrabbed;
givenObject.InteractableObjectUngrabbed -= InteractableObjectUngrabbed;
currentValidSnapInteractableObjects.Remove(givenObject);
}
}
}

protected virtual void InteractableObjectGrabbed(object sender, InteractableObjectEventArgs e)
{
VRTK_InteractableObject grabbedInteractableObject = sender as VRTK_InteractableObject;
Expand All @@ -814,20 +862,11 @@ protected virtual void InteractableObjectGrabbed(object sender, InteractableObje
protected virtual void InteractableObjectUngrabbed(object sender, InteractableObjectEventArgs e)
{
VRTK_InteractableObject releasedInteractableObject = sender as VRTK_InteractableObject;
SnapObjectToZone(releasedInteractableObject);
}

protected virtual void RemoveCurrentValidSnapObject(VRTK_InteractableObject givenObject)
{
if (givenObject != null)
if (attemptTransitionAtEndOfFrameRoutine != null)
{
if (currentValidSnapInteractableObjects.Contains(givenObject))
{
givenObject.InteractableObjectGrabbed -= InteractableObjectGrabbed;
givenObject.InteractableObjectUngrabbed -= InteractableObjectUngrabbed;
currentValidSnapInteractableObjects.Remove(givenObject);
}
StopCoroutine(attemptTransitionAtEndOfFrameRoutine);
}
attemptTransitionAtEndOfFrameRoutine = StartCoroutine(AttemptForceSnapAtEndOfFrame(releasedInteractableObject));
}

protected virtual void AttemptForceSnap(VRTK_InteractableObject objectToSnap)
Expand All @@ -851,21 +890,6 @@ protected virtual void ToggleHighlight(VRTK_InteractableObject checkObject, bool
{
//Toggle the highlighter state
SetHighlightObjectActive(state);
checkObject.SetSnapDropZoneHover(this, state);

willSnap = state;

if (state)
{
if (!IsInteractableObjectHovering(checkObject) || wasSnapped)
{
OnObjectEnteredSnapDropZone(SetSnapDropZoneEvent(checkObject.gameObject));
}
}
else
{
OnObjectExitedSnapDropZone(SetSnapDropZoneEvent(checkObject.gameObject));
}
}
}

Expand Down Expand Up @@ -1070,4 +1094,4 @@ protected virtual void OnDrawGizmosSelected()
}
}
}
}
}

0 comments on commit 0fbef07

Please sign in to comment.