-
-
Notifications
You must be signed in to change notification settings - Fork 992
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Highlighters): add highlighter composition scripts
A new Highlighter composition concept has been added that allows a separate component to deal with highlighting of objects. Previously, the Interactable Object and the Controller highlighting were done with the same logic in two different scripts and it also meant that there was only one way to highlight these elements. The new highlighter scripts mean the logic for highlighting is in one script but other highlighters can be created and added to an object to provide alternative highlighting methods.
- Loading branch information
1 parent
0c4d5d5
commit 5b850bb
Showing
8 changed files
with
452 additions
and
113 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Base Highlighter|Highlighters|0010 | ||
namespace VRTK.Highlighters | ||
{ | ||
using UnityEngine; | ||
using System.Collections.Generic; | ||
|
||
/// <summary> | ||
/// The Base Highlighter is an abstract class that all other highlighters inherit and are required to implement the public methods. | ||
/// </summary> | ||
/// <remarks> | ||
/// As this is an abstract class, it cannot be applied directly to a game object and performs no logic. | ||
/// </remarks> | ||
public abstract class VRTK_BaseHighlighter : MonoBehaviour | ||
{ | ||
/// <summary> | ||
/// The Initalise method is used to set up the state of the highlighter. | ||
/// </summary> | ||
/// <param name="color">An optional colour may be passed through at point of initialisation in case the highlighter requires it.</param> | ||
/// <param name="options">An optional dictionary of highlighter specific options that may be differ with highlighter implementations.</param> | ||
public abstract void Initialise(Color? color = null, Dictionary<string, object> options = null); | ||
|
||
/// <summary> | ||
/// The Highlight method is used to initiate the highlighting logic to apply to an object. | ||
/// </summary> | ||
/// <param name="color">An optional colour to highlight the game object to. The highlight colour may already have been set in the `Initialise` method so may not be required here.</param> | ||
/// <param name="duration">An optional duration of how long before the highlight has occured. It can be used by highlighters to fade the colour if possible.</param> | ||
|
||
public abstract void Highlight(Color? color = null, float duration = 0f); | ||
/// <summary> | ||
/// The Unhighlight method is used to initiate the logic that returns an object back to it's original appearance. | ||
/// </summary> | ||
/// <param name="color">An optional colour that could be used during the unhighlight phase. Usually will be left as null.</param> | ||
/// <param name="duration">An optional duration of how long before the unhighlight has occured.</param> | ||
public abstract void Unhighlight(Color? color = null, float duration = 0f); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Assets/VRTK/Scripts/Highlighters/VRTK_BaseHighlighter.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
176 changes: 176 additions & 0 deletions
176
Assets/VRTK/Scripts/Highlighters/VRTK_MaterialColorSwapHighlighter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// Material Colour Swap|Highlighters|0020 | ||
namespace VRTK.Highlighters | ||
{ | ||
using UnityEngine; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
|
||
/// <summary> | ||
/// The Material Colour Swap Highlighter is a basic implementation that simply swaps the texture colour for the given highlight colour. | ||
/// </summary> | ||
/// <remarks> | ||
/// Due to the way the object material is interacted with, changing the material colour will break Draw Call Batching in Unity whilst the object is highlighted. | ||
/// | ||
/// The Draw Call Batching will resume on the original material when the item is no longer highlighted. | ||
/// | ||
/// This is the default highlighter that is applied to any script that requires a highlighting component (e.g. `VRTK_Interactable_Object` or `VRTK_ControllerActions`). | ||
/// </remarks> | ||
public class VRTK_MaterialColorSwapHighlighter : VRTK_BaseHighlighter | ||
{ | ||
/// <summary> | ||
/// The emission colour of the texture will be the highlight colour but this percent darker. | ||
/// </summary> | ||
public float emissionDarken = 50f; | ||
|
||
private Dictionary<string, Material[]> originalSharedRendererMaterials; | ||
private Dictionary<string, Material[]> originalRendererMaterials; | ||
private Dictionary<string, Coroutine> faderRoutines; | ||
private bool resetMainTexture = false; | ||
|
||
/// <summary> | ||
/// The Initialise method sets up the highlighter for use. | ||
/// </summary> | ||
/// <param name="color">Not used.</param> | ||
/// <param name="options">A dictionary array containing the highlighter options:\r * `<'resetMainTexture', bool>` - Determines if the default main texture should be cleared on highlight. `true` to reset the main default texture, `false` to not reset it.</param> | ||
public override void Initialise(Color? color = null, Dictionary<string, object> options = null) | ||
{ | ||
originalSharedRendererMaterials = new Dictionary<string, Material[]>(); | ||
originalRendererMaterials = new Dictionary<string, Material[]>(); | ||
faderRoutines = new Dictionary<string, Coroutine>(); | ||
StoreOriginalMaterials(); | ||
|
||
if (options != null && options.ContainsKey("resetMainTexture") && options["resetMainTexture"] != null && options["resetMainTexture"] is bool) | ||
{ | ||
resetMainTexture = (bool)options["resetMainTexture"]; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// The Highlight method initiates the change of colour on the object and will fade to that colour (from a base white colour) for the given duration. | ||
/// </summary> | ||
/// <param name="color">The colour to highlight to.</param> | ||
/// <param name="duration">The time taken to fade to the highlighted colour.</param> | ||
public override void Highlight(Color? color, float duration = 0f) | ||
{ | ||
if (color == null) | ||
{ | ||
return; | ||
} | ||
ChangeToHighlightColor((Color)color, duration); | ||
} | ||
|
||
/// <summary> | ||
/// The Unhighlight method returns the object back to it's original colour. | ||
/// </summary> | ||
/// <param name="color">Not used.</param> | ||
/// <param name="duration">Not used.</param> | ||
public override void Unhighlight(Color? color = null, float duration = 0f) | ||
{ | ||
if (originalRendererMaterials == null) | ||
{ | ||
return; | ||
} | ||
|
||
foreach (var fadeRoutine in faderRoutines) | ||
{ | ||
StopCoroutine(fadeRoutine.Value); | ||
} | ||
faderRoutines.Clear(); | ||
|
||
foreach (Renderer renderer in GetComponentsInChildren<Renderer>()) | ||
{ | ||
var objectReference = renderer.gameObject.GetInstanceID().ToString(); | ||
if (!originalRendererMaterials.ContainsKey(objectReference)) | ||
{ | ||
continue; | ||
} | ||
|
||
renderer.materials = originalRendererMaterials[objectReference]; | ||
renderer.sharedMaterials = originalSharedRendererMaterials[objectReference]; | ||
} | ||
} | ||
|
||
private void StoreOriginalMaterials() | ||
{ | ||
originalSharedRendererMaterials.Clear(); | ||
originalRendererMaterials.Clear(); | ||
foreach (Renderer renderer in GetComponentsInChildren<Renderer>()) | ||
{ | ||
var objectReference = renderer.gameObject.GetInstanceID().ToString(); | ||
originalSharedRendererMaterials[objectReference] = renderer.sharedMaterials; | ||
originalRendererMaterials[objectReference] = renderer.materials; | ||
renderer.sharedMaterials = originalSharedRendererMaterials[objectReference]; | ||
} | ||
} | ||
|
||
private void ChangeToHighlightColor(Color color, float duration = 0f) | ||
{ | ||
foreach (Renderer renderer in GetComponentsInChildren<Renderer>()) | ||
{ | ||
for (int i = 0; i < renderer.materials.Length; i++) | ||
{ | ||
var material = renderer.materials[i]; | ||
var faderRoutineID = material.GetInstanceID().ToString(); | ||
|
||
if (faderRoutines.ContainsKey(faderRoutineID) && faderRoutines[faderRoutineID] != null) | ||
{ | ||
StopCoroutine(faderRoutines[faderRoutineID]); | ||
faderRoutines.Remove(faderRoutineID); | ||
} | ||
|
||
material.EnableKeyword("_EMISSION"); | ||
|
||
if (resetMainTexture && material.HasProperty("_MainTex")) | ||
{ | ||
renderer.material.SetTexture("_MainTex", new Texture()); | ||
} | ||
|
||
if (material.HasProperty("_Color")) | ||
{ | ||
if (duration > 0f) | ||
{ | ||
faderRoutines[faderRoutineID] = StartCoroutine(CycleColor(material, material.color, color, duration)); | ||
} | ||
else | ||
{ | ||
material.color = color; | ||
if (material.HasProperty("_EmissionColor")) | ||
{ | ||
material.SetColor("_EmissionColor", Darken(color, emissionDarken)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
private IEnumerator CycleColor(Material material, Color startColor, Color endColor, float duration) | ||
{ | ||
var elapsedTime = 0f; | ||
while (elapsedTime <= duration) | ||
{ | ||
elapsedTime += Time.deltaTime; | ||
if (material.HasProperty("_Color")) | ||
{ | ||
material.color = Color.Lerp(startColor, endColor, (elapsedTime / duration)); | ||
} | ||
if (material.HasProperty("_EmissionColor")) | ||
{ | ||
material.SetColor("_EmissionColor", Color.Lerp(startColor, Darken(endColor, emissionDarken), (elapsedTime / duration))); | ||
} | ||
yield return null; | ||
} | ||
} | ||
|
||
private Color Darken(Color color, float percent) | ||
{ | ||
return new Color(ColorPercent(color.r, percent), ColorPercent(color.g, percent), ColorPercent(color.b, percent), color.a); | ||
} | ||
|
||
private float ColorPercent(float value, float percent) | ||
{ | ||
percent = Mathf.Clamp(percent, 0f, 100f); | ||
return (percent == 0f ? value : (value - (percent / 100f))); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Assets/VRTK/Scripts/Highlighters/VRTK_MaterialColorSwapHighlighter.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.