AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
CompoundButtonMesh.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using UnityEngine;
6 using HoloToolkit.Unity;
7 
8 namespace HoloToolkit.Unity.Buttons
9 {
13  [RequireComponent(typeof(CompoundButton))]
14  public class CompoundButtonMesh : ProfileButtonBase<ButtonMeshProfile>
15  {
16  const float AnimationSpeedMultiplier = 25f;
17 
18  [Tooltip("Transform that scale and offset will be applied to.")]
19  [DropDownComponent]
20  public Transform TargetTransform;
21 
22  [Tooltip("Mesh renderer button for mesh button.")]
23  [DropDownComponent]
24  public MeshRenderer Renderer;
25 
29  [Serializable]
30  public class MeshButtonDatum
31  {
35  public MeshButtonDatum(ButtonStateEnum state) { this.ActiveState = state; this.Name = state.ToString(); }
36 
40  public string Name;
48  public Color StateColor = Color.white;
52  public float StateValue = 0f;
56  public Vector3 Offset;
60  public Vector3 Scale;
61  }
62 
63  private MeshButtonDatum currentDatum;
64 
68  private Material instantiatedMaterial;
69 
73  private Material sharedMaterial;
74 
75 
76  private float lastTimePressed = 0f;
77 
78 #if UNITY_EDITOR
79  public void OnWillSaveScene ()
84  {
85  if (Renderer != null && instantiatedMaterial != null)
86  {
87  Renderer.sharedMaterial = sharedMaterial;
88  GameObject.DestroyImmediate(instantiatedMaterial);
89  }
90  }
91 #endif
92 
93  protected void Start ()
94  {
95  Button button = GetComponent<Button>();
96  if (button == null)
97  {
98  Debug.LogError("No button attached to CompoundButtonMesh in " + name);
99  enabled = false;
100  return;
101  }
102 
103  if (Profile == null)
104  {
105  Debug.LogError("No profile selected for CompoundButtonMesh in " + name);
106  enabled = false;
107  return;
108  }
109 
110  button.StateChange += StateChange;
111  // Disable this script if we're not using smooth changes
112  enabled = Profile.SmoothStateChanges;
113  // Set the current datum so our first state is activated
114  currentDatum = Profile.ButtonStates[(int)ButtonStateEnum.Observation];
115  UpdateButtonProperties(false);
116  }
117 
121  protected void StateChange(ButtonStateEnum newState)
122  {
123  if (newState == ButtonStateEnum.Pressed)
124  {
125  lastTimePressed = Time.time;
126  }
127 
128  currentDatum = Profile.ButtonStates[(int)newState];
129 
130  // If we're not using smooth states, just set them now
131  if (!Profile.SmoothStateChanges)
132  {
133  TargetTransform.localScale = currentDatum.Scale;
134  TargetTransform.localPosition = currentDatum.Offset;
135 
136  if (Renderer != null)
137  {
138  if (instantiatedMaterial == null)
139  {
140  sharedMaterial = Renderer.sharedMaterial;
141  instantiatedMaterial = new Material(sharedMaterial);
142  Renderer.sharedMaterial = instantiatedMaterial;
143  }
144 
145  if (!string.IsNullOrEmpty(Profile.ColorPropertyName))
146  {
147  Renderer.sharedMaterial.SetColor(Profile.ColorPropertyName, currentDatum.StateColor);
148  }
149  if (!string.IsNullOrEmpty(Profile.ValuePropertyName))
150  {
151  Renderer.sharedMaterial.SetFloat(Profile.ValuePropertyName, currentDatum.StateValue);
152  }
153  }
154  }
155  }
156 
157  protected void OnDisable()
158  {
159  StateChange(ButtonStateEnum.Disabled);
160  UpdateButtonProperties(false);
161  }
162 
163  protected void OnEnable() {
164  Button button = GetComponent<Button>();
165  if (button != null) {
166  StateChange(button.ButtonState);
167  }
168  }
169 
170  protected void Update ()
171  {
172  UpdateButtonProperties(true);
173  }
174 
175  protected void UpdateButtonProperties(bool smooth)
176  {
177  if (currentDatum == null)
178  {
179  return;
180  }
181 
182  MeshButtonDatum datum = currentDatum;
183 
184  // If we're using sticky events, and we're still not past the 'sticky' pressed time, use that datum
185  if (Profile.StickyPressedEvents && Time.time < lastTimePressed + Profile.StickyPressedTime)
186  {
187  datum = Profile.ButtonStates[(int)ButtonStateEnum.Pressed];
188  }
189 
190  if (TargetTransform != null)
191  {
192  if (smooth)
193  {
194  TargetTransform.localScale = Vector3.Lerp(
195  TargetTransform.localScale, datum.Scale,
196  Time.deltaTime * Profile.AnimationSpeed * AnimationSpeedMultiplier);
197  TargetTransform.localPosition = Vector3.Lerp(
198  TargetTransform.localPosition, datum.Offset,
199  Time.deltaTime * Profile.AnimationSpeed * AnimationSpeedMultiplier);
200  } else
201  {
202  TargetTransform.localScale = datum.Scale;
203  TargetTransform.localPosition = datum.Offset;
204  }
205  }
206 
207  // Set the color from the datum
208  if (Renderer != null)
209  {
210  if (instantiatedMaterial == null)
211  {
212  sharedMaterial = Renderer.sharedMaterial;
213  instantiatedMaterial = new Material(sharedMaterial);
214  Renderer.sharedMaterial = instantiatedMaterial;
215  }
216 
217  if (!string.IsNullOrEmpty(Profile.ColorPropertyName))
218  {
219  if (smooth)
220  {
221  Renderer.sharedMaterial.SetColor(
222  Profile.ColorPropertyName,
223  Color.Lerp(Renderer.material.GetColor(Profile.ColorPropertyName),
224  datum.StateColor,
225  Time.deltaTime * Profile.AnimationSpeed * AnimationSpeedMultiplier));
226  } else
227  {
228  Renderer.sharedMaterial.SetColor(
229  Profile.ColorPropertyName,
230  datum.StateColor);
231  }
232  }
233  if (!string.IsNullOrEmpty(Profile.ValuePropertyName))
234  {
235  if (smooth)
236  {
237  Renderer.sharedMaterial.SetFloat(
238  Profile.ValuePropertyName,
239  Mathf.Lerp(Renderer.material.GetFloat(Profile.ValuePropertyName),
240  datum.StateValue,
241  Time.deltaTime * Profile.AnimationSpeed * AnimationSpeedMultiplier));
242  } else
243  {
244  Renderer.sharedMaterial.SetFloat(Profile.ValuePropertyName, datum.StateValue);
245  }
246  }
247  }
248  }
249 
250 #if UNITY_EDITOR
251  [UnityEditor.CustomEditor(typeof(CompoundButtonMesh))]
252  public class CustomEditor : MRTKEditor { }
253 #endif
254  }
255 }
ButtonStateEnum
State enum for buttons.
Color StateColor
Button mesh color to use in active state
Action< ButtonStateEnum > StateChange
Event to receive button state change.
Definition: Button.cs:61
Mesh button is a mesh renderer interactable with state data for button state
ButtonStateEnum ButtonState
Current Button State.
Definition: Button.cs:27
MeshButtonDatum(ButtonStateEnum state)
Constructor for mesh button datum
void StateChange(ButtonStateEnum newState)
On state change swap out the active mesh based on the state
Ensures a consistent profile field in compound buttons scripts which use a profile ...
Vector3 Offset
Offset to translate mesh to in active state.
Vector3 Scale
Scale for mesh button in active state
ButtonStateEnum ActiveState
Button state the datum is active in
float StateValue
Button mesh shader property to use in active state