Tanoda
UIPrimitiveBase.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3
5{
6 public enum ResolutionMode
7 {
8 None,
11 }
12
13 public class UIPrimitiveBase : MaskableGraphic, ILayoutElement, ICanvasRaycastFilter
14 {
15 static protected Material s_ETC1DefaultUI = null;
16 List<Vector2> outputList = new List<Vector2>();
17
18 [SerializeField] private Sprite m_Sprite;
19 public Sprite sprite { get { return m_Sprite; } set { if (SetPropertyUtility.SetClass(ref m_Sprite, value)) GeneratedUVs(); SetAllDirty(); } }
20
21 [NonSerialized]
22 private Sprite m_OverrideSprite;
23 public Sprite overrideSprite { get { return activeSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) GeneratedUVs(); SetAllDirty(); } }
24
25 protected Sprite activeSprite { get { return m_OverrideSprite != null ? m_OverrideSprite : sprite; } }
26
27 // Not serialized until we support read-enabled sprites better.
28 internal float m_EventAlphaThreshold = 1;
29 public float eventAlphaThreshold { get { return m_EventAlphaThreshold; } set { m_EventAlphaThreshold = value; } }
30
31 [SerializeField]
32 private ResolutionMode m_improveResolution;
33 public ResolutionMode ImproveResolution { get { return m_improveResolution; } set { m_improveResolution = value; SetAllDirty(); } }
34
35 [SerializeField]
36 protected float m_Resolution;
37 public float Resolution { get { return m_Resolution; } set { m_Resolution = value; SetAllDirty(); } }
38
39 [SerializeField]
40 private bool m_useNativeSize;
41 public bool UseNativeSize { get { return m_useNativeSize; } set { m_useNativeSize = value; SetAllDirty(); } }
42
43 protected UIPrimitiveBase()
44 {
45 useLegacyMeshGeneration = false;
46 }
47
51
52 static public Material defaultETC1GraphicMaterial
53 {
54 get
55 {
56 if (s_ETC1DefaultUI == null)
57 s_ETC1DefaultUI = Canvas.GetETC1SupportedCanvasMaterial();
58 return s_ETC1DefaultUI;
59 }
60 }
61
65 public override Texture mainTexture
66 {
67 get
68 {
69 if (activeSprite == null)
70 {
71 if (material != null && material.mainTexture != null)
72 {
73 return material.mainTexture;
74 }
75 return s_WhiteTexture;
76 }
77
78 return activeSprite.texture;
79 }
80 }
81
85
86 public bool hasBorder
87 {
88 get
89 {
90 if (activeSprite != null)
91 {
92 Vector4 v = activeSprite.border;
93 return v.sqrMagnitude > 0f;
94 }
95 return false;
96 }
97 }
98
99 public float pixelsPerUnit
100 {
101 get
102 {
103 float spritePixelsPerUnit = 100;
104 if (activeSprite)
105 spritePixelsPerUnit = activeSprite.pixelsPerUnit;
106
107 float referencePixelsPerUnit = 100;
108 if (canvas)
109 referencePixelsPerUnit = canvas.referencePixelsPerUnit;
110
111 return spritePixelsPerUnit / referencePixelsPerUnit;
112 }
113 }
114
115 public override Material material
116 {
117 get
118 {
119 if (m_Material != null)
120 return m_Material;
121
122 if (activeSprite && activeSprite.associatedAlphaSplitTexture != null)
124
125 return defaultMaterial;
126 }
127
128 set
129 {
130 base.material = value;
131 }
132 }
133
134
135 protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs)
136 {
137 UIVertex[] vbo = new UIVertex[4];
138 for (int i = 0; i < vertices.Length; i++)
139 {
140 var vert = UIVertex.simpleVert;
141 vert.color = color;
142 vert.position = vertices[i];
143 vert.uv0 = uvs[i];
144 vbo[i] = vert;
145 }
146 return vbo;
147 }
148
149 protected Vector2[] IncreaseResolution(Vector2[] input)
150 {
151 return IncreaseResolution(new List<Vector2>(input)).ToArray();
152 }
153
154 protected List<Vector2> IncreaseResolution(List<Vector2> input)
155 {
156 outputList.Clear();
157
158 switch (ImproveResolution)
159 {
160 case ResolutionMode.PerLine:
161 float totalDistance = 0, increments = 0;
162 for (int i = 0; i < input.Count - 1; i++)
163 {
164 totalDistance += Vector2.Distance(input[i], input[i + 1]);
165 }
166 ResolutionToNativeSize(totalDistance);
167 increments = totalDistance / m_Resolution;
168 var incrementCount = 0;
169 for (int i = 0; i < input.Count - 1; i++)
170 {
171 var p1 = input[i];
172 outputList.Add(p1);
173 var p2 = input[i + 1];
174 var segmentDistance = Vector2.Distance(p1, p2) / increments;
175 var incrementTime = 1f / segmentDistance;
176 for (int j = 0; j < segmentDistance; j++)
177 {
178 outputList.Add(Vector2.Lerp(p1, (Vector2)p2, j * incrementTime));
179 incrementCount++;
180 }
181 outputList.Add(p2);
182 }
183 break;
184 case ResolutionMode.PerSegment:
185 for (int i = 0; i < input.Count - 1; i++)
186 {
187 var p1 = input[i];
188 outputList.Add(p1);
189 var p2 = input[i + 1];
190 ResolutionToNativeSize(Vector2.Distance(p1, p2));
191 increments = 1f / m_Resolution;
192 for (Single j = 1; j < m_Resolution; j++)
193 {
194 outputList.Add(Vector2.Lerp(p1, (Vector2)p2, increments * j));
195 }
196 outputList.Add(p2);
197 }
198 break;
199 }
200 return outputList;
201 }
202
203 protected virtual void GeneratedUVs() { }
204
205 protected virtual void ResolutionToNativeSize(float distance) { }
206
207
208 #region ILayoutElement Interface
209
210 public virtual void CalculateLayoutInputHorizontal() { }
211 public virtual void CalculateLayoutInputVertical() { }
212
213 public virtual float minWidth { get { return 0; } }
214
215 public virtual float preferredWidth
216 {
217 get
218 {
219 if (overrideSprite == null)
220 return 0;
221 return overrideSprite.rect.size.x / pixelsPerUnit;
222 }
223 }
224
225 public virtual float flexibleWidth { get { return -1; } }
226
227 public virtual float minHeight { get { return 0; } }
228
229 public virtual float preferredHeight
230 {
231 get
232 {
233 if (overrideSprite == null)
234 return 0;
235 return overrideSprite.rect.size.y / pixelsPerUnit;
236 }
237 }
238
239 public virtual float flexibleHeight { get { return -1; } }
240
241 public virtual int layoutPriority { get { return 0; } }
242
243 #endregion
244
245 #region ICanvasRaycastFilter Interface
246 public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
247 {
248 // add test for line check
249 if (m_EventAlphaThreshold >= 1)
250 return true;
251
252 Sprite sprite = overrideSprite;
253 if (sprite == null)
254 return true;
255
256 Vector2 local;
257 RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local);
258
259 Rect rect = GetPixelAdjustedRect();
260
261 // Convert to have lower left corner as reference point.
262 local.x += rectTransform.pivot.x * rect.width;
263 local.y += rectTransform.pivot.y * rect.height;
264
265 local = MapCoordinate(local, rect);
266
267 //test local coord with Mesh
268
269 // Normalize local coordinates.
270 Rect spriteRect = sprite.textureRect;
271 Vector2 normalized = new Vector2(local.x / spriteRect.width, local.y / spriteRect.height);
272
273 // Convert to texture space.
274 float x = Mathf.Lerp(spriteRect.x, spriteRect.xMax, normalized.x) / sprite.texture.width;
275 float y = Mathf.Lerp(spriteRect.y, spriteRect.yMax, normalized.y) / sprite.texture.height;
276
277 try
278 {
279 return sprite.texture.GetPixelBilinear(x, y).a >= m_EventAlphaThreshold;
280 }
281 catch (UnityException e)
282 {
283 Debug.LogError("Using clickAlphaThreshold lower than 1 on Image whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this);
284 return true;
285 }
286 }
287
295 private Vector2 MapCoordinate(Vector2 local, Rect rect)
296 {
297 Rect spriteRect = sprite.rect;
298 //if (type == Type.Simple || type == Type.Filled)
299 return new Vector2(local.x * rect.width, local.y * rect.height);
300
301 //Vector4 border = sprite.border;
302 //Vector4 adjustedBorder = GetAdjustedBorders(border / pixelsPerUnit, rect);
303
304 //for (int i = 0; i < 2; i++)
305 //{
306 // if (local[i] <= adjustedBorder[i])
307 // continue;
308
309 // if (rect.size[i] - local[i] <= adjustedBorder[i + 2])
310 // {
311 // local[i] -= (rect.size[i] - spriteRect.size[i]);
312 // continue;
313 // }
314
315 // if (type == Type.Sliced)
316 // {
317 // float lerp = Mathf.InverseLerp(adjustedBorder[i], rect.size[i] - adjustedBorder[i + 2], local[i]);
318 // local[i] = Mathf.Lerp(border[i], spriteRect.size[i] - border[i + 2], lerp);
319 // continue;
320 // }
321 // else
322 // {
323 // local[i] -= adjustedBorder[i];
324 // local[i] = Mathf.Repeat(local[i], spriteRect.size[i] - border[i] - border[i + 2]);
325 // local[i] += border[i];
326 // continue;
327 // }
328 //}
329
330 //return local;
331 }
332
333 Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
334 {
335 for (int axis = 0; axis <= 1; axis++)
336 {
337 // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
338 // In order to avoid artefact's with overlapping borders, we scale the borders down to fit.
339 float combinedBorders = border[axis] + border[axis + 2];
340 if (rect.size[axis] < combinedBorders && combinedBorders != 0)
341 {
342 float borderScaleRatio = rect.size[axis] / combinedBorders;
343 border[axis] *= borderScaleRatio;
344 border[axis + 2] *= borderScaleRatio;
345 }
346 }
347 return border;
348 }
349
350 #endregion
351
352 #region onEnable
353 protected override void OnEnable()
354 {
355 base.OnEnable();
356 SetAllDirty();
357 }
358 #endregion
359
360 }
361}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
Vector2[] IncreaseResolution(Vector2[] input)
static Material defaultETC1GraphicMaterial
Default material used to draw everything if no explicit material was specified.
List< Vector2 > IncreaseResolution(List< Vector2 > input)
override Texture mainTexture
Image's texture comes from the UnityEngine.Image.
UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs)
virtual void ResolutionToNativeSize(float distance)
bool hasBorder
Whether the Image has a border to work with.
Credit Erdener Gonenc - @PixelEnvision.