AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
LineObjectCollection.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.Collections.Generic;
5 using UnityEngine;
6 
7 namespace HoloToolkit.Unity.UX
8 {
9  public class LineObjectCollection : MonoBehaviour
10  {
11  public List<Transform> Objects = new List<Transform>();
12 
13  [Range(-2f, 2f)]
14  public float DistributionOffset = 0f;
15  [Range(0f, 2f)]
16  public float LengthOffset = 0f;
17  [Range(0f, 2f)]
18  public float ScaleOffset = 0f;
19  [Range(0.001f, 2f)]
20  public float ScaleMultiplier = 1f;
21  [Range(0.001f, 2f)]
22  public float PositionMultiplier = 1f;
23 
24  public float DistributionOffsetPerObject
25  {
26  get
27  {
28  return 1f / Objects.Count;
29  }
30  }
31 
32  public AnimationCurve ObjectScale = AnimationCurve.Linear(0f, 1f, 1f, 1f);
33 
34  public AnimationCurve ObjectPosition = AnimationCurve.Linear(0f, 0f, 1f, 0f);
35 
36  public bool FlipRotation = false;
37 
38  public Vector3 RotationOffset = Vector3.zero;
39 
40  public Vector3 PositionOffset = Vector3.zero;
41 
42  public RotationTypeEnum RotationTypeOverride = RotationTypeEnum.None;
43 
44  public PointDistributionTypeEnum DistributionType = PointDistributionTypeEnum.None;
45 
46  [Header("Object Placement")]
47  public StepModeEnum StepMode = StepModeEnum.Interpolated;
48 
49  [SerializeField]
50  private LineBase source;
51 
52  [SerializeField]
53  private Transform transformHelper;
54 
55  public virtual LineBase Source
56  {
57  get
58  {
59  if (source == null)
60  {
61  source = GetComponent<LineBase>();
62  }
63  return source;
64  }
65  set
66  {
67  source = value;
68  if (source == null)
69  {
70  enabled = false;
71  }
72  }
73  }
74 
75  // Convenience functions
76  public float GetOffsetFromObjectIndex(int index, bool wrap = true)
77  {
78  if (Objects.Count == 0)
79  {
80  return 0;
81  }
82 
83  if (wrap)
84  {
85  index = WrapIndex(index, Objects.Count);
86  }
87  else
88  {
89  index = Mathf.Clamp(index, 0, Objects.Count - 1);
90  }
91 
92  return (1f / Objects.Count * (index + 1));
93  }
94 
95  public int GetNextObjectIndex(int index, bool wrap = true)
96  {
97  if (Objects.Count == 0)
98  {
99  return 0;
100  }
101 
102  index++;
103 
104  if (wrap)
105  {
106  return WrapIndex(index, Objects.Count);
107  }
108  else
109  {
110  return Mathf.Clamp(index, 0, Objects.Count - 1);
111  }
112  }
113 
114  public int GetPrevObjectIndex(int index, bool wrap = true)
115  {
116  if (Objects.Count == 0)
117  {
118  return 0;
119  }
120 
121  index--;
122 
123  if (wrap)
124  {
125  return WrapIndex(index, Objects.Count);
126  }
127  else
128  {
129  return Mathf.Clamp(index, 0, Objects.Count - 1);
130  }
131  }
132 
133  public void Update()
134  {
135  UpdateCollection();
136  }
137 
138  public void UpdateCollection()
139  {
140  if (Source == null)
141  {
142  return;
143  }
144 
145  if (transformHelper == null)
146  {
147  transformHelper = transform.Find("TransformHelper");
148  if (transformHelper == null)
149  {
150  transformHelper = new GameObject("TransformHelper").transform;
151  transformHelper.parent = transform;
152  }
153  }
154 
155  switch (StepMode)
156  {
157  case StepModeEnum.FromSource:
158  break;
159 
160  case StepModeEnum.Interpolated:
161  for (int i = 0; i < Objects.Count; i++)
162  {
163  if (Objects[i] == null)
164  {
165  continue;
166  }
167 
168  float normalizedDistance = Mathf.Repeat(((float)i / Objects.Count) + DistributionOffset, 1f);
169  Objects[i].position = Source.GetPoint(normalizedDistance);
170  Objects[i].rotation = Source.GetRotation(normalizedDistance, RotationTypeOverride);
171 
172  transformHelper.localScale = Vector3.one;
173  transformHelper.position = Objects[i].position;
174  transformHelper.localRotation = Quaternion.identity;
175  Transform tempParent = Objects[i].parent;
176  Objects[i].parent = transformHelper;
177  transformHelper.localEulerAngles = RotationOffset;
178  Objects[i].parent = tempParent;
179  Objects[i].transform.localScale = Vector3.one * ObjectScale.Evaluate(Mathf.Repeat(ScaleOffset + normalizedDistance, 1f)) * ScaleMultiplier;
180  }
181  break;
182  }
183  }
184 
185 #if UNITY_EDITOR
186  private void OnDrawGizmos()
187  {
188  if (Application.isPlaying)
189  {
190  return;
191  }
192 
193  UpdateCollection();
194  }
195 #endif
196 
197  private static int WrapIndex(int index, int numObjects)
198  {
199  return ((index % numObjects) + numObjects) % numObjects;
200  }
201  }
202 
203 #if UNITY_EDITOR
204  [UnityEditor.CustomEditor(typeof(LineObjectCollection))]
205  public class LineObjectCollectionEditor : UnityEditor.Editor
206  {
207  public void OnSceneGUI()
208  {
210 
211  for (int i = 0; i < loc.Objects.Count; i++)
212  {
213  if (loc.Objects[i] != null)
214  {
215  UnityEditor.Handles.Label(loc.Objects[i].position, "Index: " + i.ToString("000") + "\nOffset: " + loc.GetOffsetFromObjectIndex(i).ToString("00.00"));
216  }
217  }
218  }
219  }
220 #endif
221 }
StepModeEnum
Default options for how to generate points in a line renderer
Definition: LineUtility.cs:41
int GetPrevObjectIndex(int index, bool wrap=true)
RotationTypeEnum
Default options for getting a rotation along a line
Definition: LineUtility.cs:20
int GetNextObjectIndex(int index, bool wrap=true)
float GetOffsetFromObjectIndex(int index, bool wrap=true)
PointDistributionTypeEnum
Default options for getting an interpolated point along a line
Definition: LineUtility.cs:30