Skip to content

Commit 40812fc

Browse files
committed
feat(Interaction): provide custom highlighter to interactable object
> **Breaking Changes** The Interactable Object script now has an additional parameter that allows injecting a Base Highlighter for the Interactable Object to use. This means that the Highlighter does not need to be on the same GameObject as the Interactable Object and can also be swapped out at runtime for a different highlighter. To enable this to work, the Highlighters now can accept new GameObject parameter in the Initialise method. This GameObject parameter is the second parameter pushing the `options` parameter to the 3rd param which will cause a breaking change for anyone using the existing code.
1 parent 1f3af65 commit 40812fc

File tree

7 files changed

+81
-48
lines changed

7 files changed

+81
-48
lines changed

Assets/VRTK/Documentation/API.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3713,6 +3713,7 @@ The highlighting of an Interactable Object is defaulted to use the `VRTK_Materia
37133713
* **Pointer Activates Use Action:** If this is checked then when a Base Pointer beam (projected from the controller) hits the interactable object, if the object has `Hold Button To Use` unchecked then whilst the pointer is over the object it will run it's `Using` method. If `Hold Button To Use` is unchecked then the `Using` method will be run when the pointer is deactivated. The world pointer will not throw the `Destination Set` event if it is affecting an interactable object with this setting checked as this prevents unwanted teleporting from happening when using an object with a pointer.
37143714
* **Use Override Button:** If this is set to `Undefined` then the global use alias button will use the object, setting it to any other button will ensure the override button is used to use this specific interactable object.
37153715
* **Allowed Use Controllers:** Determines which controller can initiate a use action.
3716+
* **Object Highlighter:** An optional Highlighter to use when highlighting this Interactable Object. If this is left blank, then the first active highlighter on the same GameObject will be used, if one isn't found then a Material Color Swap Highlighter will be created at runtime.
37163717

37173718
### Class Variables
37183719

@@ -4530,12 +4531,13 @@ As this is an abstract class, it cannot be applied directly to a game object and
45304531

45314532
### Class Methods
45324533

4533-
#### Initialise/2
4534+
#### Initialise/3
45344535

4535-
> `public abstract void Initialise(Color? color = null, Dictionary<string, object> options = null);`
4536+
> `public abstract void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null);`
45364537

45374538
* Parameters
45384539
* `Color? color` - An optional colour may be passed through at point of initialisation in case the highlighter requires it.
4540+
* `GameObject affectObject` - An optional GameObject to specify which object to apply the highlighting to.
45394541
* `Dictionary<string, object> options` - An optional dictionary of highlighter specific options that may be differ with highlighter implementations.
45404542
* Returns
45414543
* _none_
@@ -4635,12 +4637,13 @@ This is the default highlighter that is applied to any script that requires a hi
46354637

46364638
### Class Methods
46374639

4638-
#### Initialise/2
4640+
#### Initialise/3
46394641

4640-
> `public override void Initialise(Color? color = null, Dictionary<string, object> options = null)`
4642+
> `public override void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null)`
46414643

46424644
* Parameters
46434645
* `Color? color` - Not used.
4646+
* `GameObject affectObject` - An optional GameObject to specify which object to apply the highlighting to.
46444647
* `Dictionary<string, object> options` - A dictionary array containing the highlighter options:
46454648
* `<'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.
46464649
* Returns
@@ -4706,12 +4709,13 @@ The Draw Call Batching will resume on the original material when the item is no
47064709

47074710
### Class Methods
47084711

4709-
#### Initialise/2
4712+
#### Initialise/3
47104713

4711-
> `public override void Initialise(Color? color = null, Dictionary<string, object> options = null)`
4714+
> `public override void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null)`
47124715

47134716
* Parameters
47144717
* `Color? color` - Not used.
4718+
* `GameObject affectObject` - An optional GameObject to specify which object to apply the highlighting to.
47154719
* `Dictionary<string, object> options` - A dictionary array containing the highlighter options:
47164720
* `<'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.
47174721
* Returns
@@ -4749,12 +4753,13 @@ The Outline Object Copy Highlighter works by making a copy of a mesh and adding
47494753

47504754
### Class Methods
47514755

4752-
#### Initialise/2
4756+
#### Initialise/3
47534757

4754-
> `public override void Initialise(Color? color = null, Dictionary<string, object> options = null)`
4758+
> `public override void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null)`
47554759

47564760
* Parameters
47574761
* `Color? color` - Not used.
4762+
* `GameObject affectObject` - An optional GameObject to specify which object to apply the highlighting to.
47584763
* `Dictionary<string, object> options` - A dictionary array containing the highlighter options:
47594764
* `<'thickness', float>` - Same as `thickness` inspector parameter.
47604765
* `<'customOutlineModels', GameObject[]>` - Same as `customOutlineModels` inspector parameter.

Assets/VRTK/Source/Scripts/Interactions/Highlighters/VRTK_BaseHighlighter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ public abstract class VRTK_BaseHighlighter : MonoBehaviour
1818
public bool unhighlightOnDisable = true;
1919

2020
protected bool usesClonedObject = false;
21+
protected GameObject objectToAffect;
2122

2223
/// <summary>
2324
/// The Initalise method is used to set up the state of the highlighter.
2425
/// </summary>
2526
/// <param name="color">An optional colour may be passed through at point of initialisation in case the highlighter requires it.</param>
27+
/// <param name="affectObject">An optional GameObject to specify which object to apply the highlighting to.</param>
2628
/// <param name="options">An optional dictionary of highlighter specific options that may be differ with highlighter implementations.</param>
27-
public abstract void Initialise(Color? color = null, Dictionary<string, object> options = null);
29+
public abstract void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null);
2830

2931
/// <summary>
3032
/// The ResetHighlighter method is used to reset the highlighter if anything on the object has changed. It should be called by any scripts changing object materials or colours.

Assets/VRTK/Source/Scripts/Interactions/Highlighters/VRTK_MaterialColorSwapHighlighter.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ public class VRTK_MaterialColorSwapHighlighter : VRTK_BaseHighlighter
3737
/// The Initialise method sets up the highlighter for use.
3838
/// </summary>
3939
/// <param name="color">Not used.</param>
40+
/// <param name="affectObject">An optional GameObject to specify which object to apply the highlighting to.</param>
4041
/// <param name="options">A dictionary array containing the highlighter options:\r * `&lt;'resetMainTexture', bool&gt;` - Determines if the default main texture should be cleared on highlight. `true` to reset the main default texture, `false` to not reset it.</param>
41-
public override void Initialise(Color? color = null, Dictionary<string, object> options = null)
42+
public override void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null)
4243
{
44+
objectToAffect = (affectObject != null ? affectObject : gameObject);
4345
originalSharedRendererMaterials = new Dictionary<string, Material[]>();
4446
originalRendererMaterials = new Dictionary<string, Material[]>();
4547
faderRoutines = new Dictionary<string, Coroutine>();
@@ -76,7 +78,7 @@ public override void Highlight(Color? color, float duration = 0f)
7678
/// <param name="duration">Not used.</param>
7779
public override void Unhighlight(Color? color = null, float duration = 0f)
7880
{
79-
if (originalRendererMaterials == null)
81+
if (originalRendererMaterials == null || objectToAffect == null)
8082
{
8183
return;
8284
}
@@ -90,7 +92,7 @@ public override void Unhighlight(Color? color = null, float duration = 0f)
9092
faderRoutines.Clear();
9193
}
9294

93-
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
95+
Renderer[] renderers = objectToAffect.GetComponentsInChildren<Renderer>(true);
9496
for (int i = 0; i < renderers.Length; i++)
9597
{
9698
Renderer renderer = renderers[i];
@@ -109,7 +111,7 @@ protected virtual void StoreOriginalMaterials()
109111
{
110112
originalSharedRendererMaterials.Clear();
111113
originalRendererMaterials.Clear();
112-
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
114+
Renderer[] renderers = objectToAffect.GetComponentsInChildren<Renderer>(true);
113115
for (int i = 0; i < renderers.Length; i++)
114116
{
115117
Renderer renderer = renderers[i];
@@ -122,7 +124,7 @@ protected virtual void StoreOriginalMaterials()
122124

123125
protected virtual void ChangeToHighlightColor(Color color, float duration = 0f)
124126
{
125-
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
127+
Renderer[] renderers = objectToAffect.GetComponentsInChildren<Renderer>(true);
126128
for (int j = 0; j < renderers.Length; j++)
127129
{
128130
Renderer renderer = renderers[j];

Assets/VRTK/Source/Scripts/Interactions/Highlighters/VRTK_MaterialPropertyBlockColorSwapHighlighter.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ public class VRTK_MaterialPropertyBlockColorSwapHighlighter : VRTK_MaterialColor
2525
/// The Initialise method sets up the highlighter for use.
2626
/// </summary>
2727
/// <param name="color">Not used.</param>
28+
/// <param name="affectObject">An optional GameObject to specify which object to apply the highlighting to.</param>
2829
/// <param name="options">A dictionary array containing the highlighter options:\r * `&lt;'resetMainTexture', bool&gt;` - Determines if the default main texture should be cleared on highlight. `true` to reset the main default texture, `false` to not reset it.</param>
29-
public override void Initialise(Color? color = null, Dictionary<string, object> options = null)
30+
public override void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null)
3031
{
32+
objectToAffect = (affectObject != null ? affectObject : gameObject);
3133
originalMaterialPropertyBlocks = new Dictionary<string, MaterialPropertyBlock>();
3234
highlightMaterialPropertyBlocks = new Dictionary<string, MaterialPropertyBlock>();
3335
// call to parent highlighter
34-
base.Initialise(color, options);
36+
base.Initialise(color, affectObject, options);
3537
}
3638

3739
/// <summary>
@@ -41,7 +43,7 @@ public override void Initialise(Color? color = null, Dictionary<string, object>
4143
/// <param name="duration">Not used.</param>
4244
public override void Unhighlight(Color? color = null, float duration = 0f)
4345
{
44-
if (originalMaterialPropertyBlocks == null)
46+
if (originalMaterialPropertyBlocks == null || objectToAffect == null)
4547
{
4648
return;
4749
}
@@ -55,7 +57,7 @@ public override void Unhighlight(Color? color = null, float duration = 0f)
5557
faderRoutines.Clear();
5658
}
5759

58-
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
60+
Renderer[] renderers = objectToAffect.GetComponentsInChildren<Renderer>(true);
5961
for (int i = 0; i < renderers.Length; i++)
6062
{
6163
Renderer renderer = renderers[i];
@@ -73,7 +75,7 @@ protected override void StoreOriginalMaterials()
7375
{
7476
originalMaterialPropertyBlocks.Clear();
7577
highlightMaterialPropertyBlocks.Clear();
76-
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
78+
Renderer[] renderers = objectToAffect.GetComponentsInChildren<Renderer>(true);
7779
for (int i = 0; i < renderers.Length; i++)
7880
{
7981
Renderer renderer = renderers[i];
@@ -86,7 +88,7 @@ protected override void StoreOriginalMaterials()
8688

8789
protected override void ChangeToHighlightColor(Color color, float duration = 0f)
8890
{
89-
Renderer[] renderers = GetComponentsInChildren<Renderer>(true);
91+
Renderer[] renderers = objectToAffect.GetComponentsInChildren<Renderer>(true);
9092
for (int i = 0; i < renderers.Length; i++)
9193
{
9294
Renderer renderer = renderers[i];

Assets/VRTK/Source/Scripts/Interactions/Highlighters/VRTK_OutlineObjectCopyHighlighter.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ public class VRTK_OutlineObjectCopyHighlighter : VRTK_BaseHighlighter
3333
/// The Initialise method sets up the highlighter for use.
3434
/// </summary>
3535
/// <param name="color">Not used.</param>
36+
/// <param name="affectObject">An optional GameObject to specify which object to apply the highlighting to.</param>
3637
/// <param name="options">A dictionary array containing the highlighter options:\r * `&lt;'thickness', float&gt;` - Same as `thickness` inspector parameter.\r * `&lt;'customOutlineModels', GameObject[]&gt;` - Same as `customOutlineModels` inspector parameter.\r * `&lt;'customOutlineModelPaths', string[]&gt;` - Same as `customOutlineModelPaths` inspector parameter.</param>
37-
public override void Initialise(Color? color = null, Dictionary<string, object> options = null)
38+
public override void Initialise(Color? color = null, GameObject affectObject = null, Dictionary<string, object> options = null)
3839
{
40+
objectToAffect = (affectObject != null ? affectObject : gameObject);
3941
usesClonedObject = true;
4042

4143
if (stencilOutline == null)
@@ -89,6 +91,11 @@ public override void Highlight(Color? color, float duration = 0f)
8991
/// <param name="duration">Not used.</param>
9092
public override void Unhighlight(Color? color = null, float duration = 0f)
9193
{
94+
if (objectToAffect == null)
95+
{
96+
return;
97+
}
98+
9299
if (highlightModels != null)
93100
{
94101
for (int i = 0; i < highlightModels.Length; i++)
@@ -185,14 +192,15 @@ protected virtual void SetOptions(Dictionary<string, object> options = null)
185192

186193
protected virtual void DeleteExistingHighlightModels()
187194
{
188-
VRTK_PlayerObject[] existingHighlighterObjects = GetComponentsInChildren<VRTK_PlayerObject>(true);
195+
VRTK_PlayerObject[] existingHighlighterObjects = objectToAffect.GetComponentsInChildren<VRTK_PlayerObject>(true);
189196
for (int i = 0; i < existingHighlighterObjects.Length; i++)
190197
{
191198
if (existingHighlighterObjects[i].objectType == VRTK_PlayerObject.ObjectTypes.Highlighter)
192199
{
193200
Destroy(existingHighlighterObjects[i].gameObject);
194201
}
195202
}
203+
highlightModels = new GameObject[0];
196204
}
197205

198206
protected virtual GameObject CreateHighlightModel(GameObject givenOutlineModel, string givenOutlineModelPath)
@@ -203,14 +211,15 @@ protected virtual GameObject CreateHighlightModel(GameObject givenOutlineModel,
203211
}
204212
else if (givenOutlineModelPath != "")
205213
{
206-
Transform getChildModel = transform.Find(givenOutlineModelPath);
214+
Transform getChildModel = objectToAffect.transform.Find(givenOutlineModelPath);
207215
givenOutlineModel = (getChildModel ? getChildModel.gameObject : null);
208216
}
209217

210218
GameObject copyModel = givenOutlineModel;
211219
if (copyModel == null)
212220
{
213-
copyModel = (GetComponent<Renderer>() ? gameObject : GetComponentInChildren<Renderer>().gameObject);
221+
Renderer copyModelRenderer = objectToAffect.GetComponentInChildren<Renderer>();
222+
copyModel = (copyModelRenderer != null ? copyModelRenderer.gameObject : null);
214223
}
215224

216225
if (copyModel == null)
@@ -219,12 +228,12 @@ protected virtual GameObject CreateHighlightModel(GameObject givenOutlineModel,
219228
return null;
220229
}
221230

222-
GameObject highlightModel = new GameObject(name + "_HighlightModel");
231+
GameObject highlightModel = new GameObject(objectToAffect.name + "_HighlightModel");
223232
highlightModel.transform.SetParent(copyModel.transform.parent, false);
224233
highlightModel.transform.localPosition = copyModel.transform.localPosition;
225234
highlightModel.transform.localRotation = copyModel.transform.localRotation;
226235
highlightModel.transform.localScale = copyModel.transform.localScale;
227-
highlightModel.transform.SetParent(transform);
236+
highlightModel.transform.SetParent(objectToAffect.transform);
228237

229238
Component[] copyModelComponents = copyModel.GetComponents<Component>();
230239
for (int i = 0; i < copyModelComponents.Length; i++)

Assets/VRTK/Source/Scripts/Interactions/VRTK_ControllerHighlighter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public virtual void PopulateHighlighters()
121121

122122
SDK_BaseController.ControllerHand currentHand = VRTK_DeviceFinder.GetControllerHand(actualController);
123123

124-
objectHighlighter.Initialise(null, highlighterOptions);
124+
objectHighlighter.Initialise(null, null, highlighterOptions);
125125

126126
AddHighlighterToElement(GetElementTransform(VRTK_SDK_Bridge.GetControllerElementPath(SDK_BaseController.ControllerElements.ButtonOne, currentHand)), objectHighlighter, elementHighlighterOverrides.buttonOne);
127127
AddHighlighterToElement(GetElementTransform(VRTK_SDK_Bridge.GetControllerElementPath(SDK_BaseController.ControllerElements.ButtonTwo, currentHand)), objectHighlighter, elementHighlighterOverrides.buttonTwo);
@@ -396,7 +396,7 @@ protected virtual void AddHighlighterToElement(Transform element, VRTK_BaseHighl
396396
{
397397
VRTK_BaseHighlighter highlighter = (overrideHighlighter != null ? overrideHighlighter : parentHighlighter);
398398
VRTK_BaseHighlighter clonedHighlighter = (VRTK_BaseHighlighter)VRTK_SharedMethods.CloneComponent(highlighter, element.gameObject);
399-
clonedHighlighter.Initialise(null, highlighterOptions);
399+
clonedHighlighter.Initialise(null, null, highlighterOptions);
400400
}
401401
}
402402

0 commit comments

Comments
 (0)