2using System.Collections.Generic;
9[AddComponentMenu(
"UI/Primitive Canvas")]
36 for (
int i = 0; i <
uiVerts.Length; i++)
38 UIVertex simpleVert = UIVertex.simpleVert;
39 simpleVert.color =
color;
50 for (
int i = 0; i <
uiVerts.Length; i++)
52 uiVerts[i].position =
new Vector3((
points[i].x + offset.x) * scale.x, (
points[i].y + offset.y) * scale.y, 0f);
57 for (
int j = 0; j <
uiVerts.Length; j++)
60 uiVerts[j].position =
new Vector3((
points[j].x + offset.x) * scale.x, (
points[j].y + offset.y) * scale.y, 0f);
63 for (
int k = 0; k <
triangles.Length; k++)
87 for (
int i = 0; i <
uiVerts.Length; i++)
89 UIVertex simpleVert = UIVertex.simpleVert;
90 simpleVert.color =
color;
107 for (
int i = 0; i <
uiVerts.Length; i++)
109 uiVerts[i].position =
new Vector3((
points[i].x + offset.x) * scale.x, (
points[i].y + offset.y) * scale.y, 0f);
114 for (
int j = 0; j <
uiVerts.Length; j++)
117 uiVerts[j].position =
new Vector3((
points[j].x + offset.x) * scale.x, (
points[j].y + offset.y) * scale.y, 0f);
120 for (
int k = 0; k <
uiVerts.Length; k += 4)
135 public static float Cross2D(Vector2 lhs, Vector2 rhs)
137 return lhs.x * rhs.y - lhs.y * rhs.x;
142 return Mathf.Abs((0f - tri1.y) * tri2.x + tri0.y * (0f - tri1.x + tri2.x) + tri0.x * (tri1.y - tri2.y) + tri1.x * tri2.y);
145 public static bool PointInTriangle(Vector2 point, Vector2 tri0, Vector2 tri1, Vector2 tri2,
float triAarea)
147 float num = tri0.y * tri2.x - tri0.x * tri2.y + (tri2.y - tri0.y) * point.x + (tri0.x - tri2.x) * point.y;
148 float num2 = tri0.x * tri1.y - tri0.y * tri1.x + (tri0.y - tri1.y) * point.x + (tri1.x - tri0.x) * point.y;
149 if (num <= 0f || num2 <= 0f)
153 return num + num2 < triAarea;
156 public static Vector2?
GetLineIntersection(Vector2 line1P1, Vector2 line1P2, Vector2 line2P1, Vector2 line2P2)
158 float num = (line2P2.y - line2P1.y) * (line1P2.x - line1P1.x) - (line2P2.x - line2P1.x) * (line1P2.y - line1P1.y);
159 float num2 = (line2P2.x - line2P1.x) * (line1P1.y - line2P1.y) - (line2P2.y - line2P1.y) * (line1P1.x - line2P1.x);
160 float f = (line1P2.x - line1P1.x) * (line1P1.y - line2P1.y) - (line1P2.y - line1P1.y) * (line1P1.x - line2P1.x);
161 if (Mathf.Abs(num2) < Mathf.Epsilon && Mathf.Abs(f) < Mathf.Epsilon && Mathf.Abs(num) < Mathf.Epsilon)
163 return new Vector2((line1P1.x + line1P2.x) * 0.5f, (line1P1.y + line1P2.y) * 0.5f);
165 if (Mathf.Abs(num) < Mathf.Epsilon)
169 float num3 = num2 / num;
170 return new Vector2(line1P1.x + num3 * (line1P2.x - line1P1.x), line1P1.y + num3 * (line1P2.y - line1P1.y));
175 Vector2 vector =
new Vector2(strokeThickness, strokeThickness *
aspectRatio);
176 Vector2 normalized = (point2 - point1).normalized;
177 Vector2 vector2 =
new Vector2((0f - normalized.y) * vector.x, normalized.x * vector.y);
178 return new Vector2[4]
189 Vector2 vector =
new Vector2(strokeThickness, strokeThickness *
aspectRatio);
190 Vector2 normalized = (points[1] - points[0]).normalized;
191 Vector2 vector2 =
new Vector2((0f - normalized.y) * vector.x, normalized.x * vector.y);
192 List<Vector2> list =
new List<Vector2>();
193 list.Add(points[0] - vector2);
194 list.Add(points[0] + vector2);
195 list.Add(points[1] + vector2);
196 list.Add(points[1] - vector2);
197 for (
int i = 1; i < points.Length - 1; i++)
199 normalized = (points[i + 1] - points[i]).normalized;
200 vector2 =
new Vector2((0f - normalized.y) * vector.x, normalized.x * vector.y);
201 list.Add(points[i] - vector2);
202 list.Add(points[i] + vector2);
203 list.Add(points[i + 1] + vector2);
204 list.Add(points[i + 1] - vector2);
205 Vector2? lineIntersection =
GetLineIntersection(list[list.Count - 8], list[list.Count - 5], list[list.Count - 4], list[list.Count - 1]);
206 Vector2? lineIntersection2 =
GetLineIntersection(list[list.Count - 7], list[list.Count - 6], list[list.Count - 3], list[list.Count - 2]);
207 if (lineIntersection.HasValue)
209 Vector2 value = lineIntersection.Value;
210 int index = list.Count - 5;
211 Vector2 value2 = (list[list.Count - 4] = value);
212 list[index] = value2;
214 if (lineIntersection2.HasValue)
216 Vector2 value = lineIntersection2.Value;
217 int index2 = list.Count - 6;
218 Vector2 value2 = (list[list.Count - 3] = value);
219 list[index2] = value2;
224 normalized = (points[^1] - points[0]).normalized;
225 vector2 =
new Vector2((0f - normalized.y) * vector.x, normalized.x * vector.y);
226 list.Add(points[^1] - vector2);
227 list.Add(points[^1] + vector2);
228 list.Add(points[0] + vector2);
229 list.Add(points[0] - vector2);
230 Vector2? lineIntersection =
GetLineIntersection(list[list.Count - 8], list[list.Count - 5], list[list.Count - 3], list[list.Count - 2]);
231 Vector2? lineIntersection2 =
GetLineIntersection(list[list.Count - 7], list[list.Count - 6], list[list.Count - 4], list[list.Count - 1]);
232 if (lineIntersection.HasValue)
234 Vector2 value = lineIntersection.Value;
235 int index3 = list.Count - 5;
236 Vector2 value2 = (list[list.Count - 3] = value);
237 list[index3] = value2;
239 if (lineIntersection2.HasValue)
241 Vector2 value = lineIntersection2.Value;
242 int index4 = list.Count - 6;
243 Vector2 value2 = (list[list.Count - 4] = value);
244 list[index4] = value2;
246 lineIntersection =
GetLineIntersection(list[3], list[0], list[list.Count - 3], list[list.Count - 2]);
247 lineIntersection2 =
GetLineIntersection(list[2], list[1], list[list.Count - 4], list[list.Count - 1]);
248 if (lineIntersection.HasValue)
250 Vector2 value = lineIntersection.Value;
251 Vector2 value2 = (list[list.Count - 2] = value);
254 if (lineIntersection2.HasValue)
256 Vector2 value = lineIntersection2.Value;
257 Vector2 value2 = (list[list.Count - 1] = value);
261 return list.ToArray();
267 private List<PUIElement>
elements =
new List<PUIElement>();
269 public float aspectRatio => base.rectTransform.rect.width / base.rectTransform.rect.height;
274 Vector2 size = base.rectTransform.rect.size;
275 Vector3 vector =
new Vector3(0f - base.rectTransform.pivot.x, 0f - base.rectTransform.pivot.y, 0f);
276 List<List<UIVertex>> list =
new List<List<UIVertex>>(
elements.Count);
277 for (
int i = 0; i <
elements.Count; i++)
279 list.Add(
elements[i].GetUIVertexTriangleStream(vector, size, color));
281 vh.AddUIVertexTriangleStream(list.SelectMany((List<UIVertex> l) => l).ToList());
292 base.OnRectTransformDimensionsChange();
302 float strokeThickness = pUIStrokeElement.strokeStyle.thickness / base.rectTransform.rect.width;
303 if (pUIStrokeElement.
rawPoints.Length == 2)
322 DrawSquare(center, size, 0f,
null, strokeStyle);
327 DrawSquare(center, size, 0f, fillColor, strokeStyle);
347 DrawRectangle(
new Rect(x, y, width, height), fillColor, strokeStyle);
352 DrawRectangle(
new Rect(x, y, width, height), rotation, fillColor, strokeStyle);
372 Vector2 center = rect.center;
373 Vector2[] array =
new Vector2[4];
378 array[0] =
new Vector2(rect.min.x, rect.min.y);
379 array[1] =
new Vector2(rect.min.x, rect.max.y);
380 array[2] =
new Vector2(rect.max.x, rect.max.y);
381 array[3] =
new Vector2(rect.max.x, rect.min.y);
384 rotation *= MathF.PI / 180f;
385 float num = Mathf.Cos(rotation);
386 float num2 = Mathf.Sin(rotation);
387 for (
int i = 0; i < array.Length; i++)
389 float num3 = array[i].x - rect.center.x;
390 float num4 = array[i].y - rect.center.y;
391 array[i] =
new Vector2((num3 * num + num4 * num2) /
aspectRatio + center.x, num4 * num - num3 * num2 + center.y);
394 if (fillColor.HasValue)
398 if (strokeStyle !=
null)
400 DrawPath(array, strokeStyle, closePath:
true);
410 DrawCircle(center, radius, 1f, 0f, 360f, fillColor);
420 DrawCircle(center, radius, 1f, 0f, 360f, fillColor, strokeStyle);
423 public void DrawCircle(Vector2 center,
float radius,
float stepSize = 1f,
float startAngle = 0f,
float endAngle = 360f,
Color? fillColor =
null,
StrokeStyle strokeStyle =
null)
425 if (endAngle - startAngle < 0f)
427 Debug.LogWarning(
"DrawCircle() only works in the clockwise-direction; please ensure endAngle > startAngle.");
431 DrawEllipse(center,
new Vector2(radius, radius *
aspectRatio), stepSize, 0f, startAngle, endAngle, fillColor, strokeStyle);
437 DrawEllipse(center, radii, 1f, 0f, 0f, 360f, fillColor);
442 DrawEllipse(center, radii, 1f, 0f, 0f, 360f,
null, strokeStyle);
447 DrawEllipse(center, radii, 1f, 0f, 0f, 360f, fillColor, strokeStyle);
450 public void DrawEllipse(Vector2 center, Vector2 radii,
float stepSize = 1f,
float rotation = 0f,
float startAngle = 0f,
float endAngle = 360f,
Color? fillColor =
null,
StrokeStyle strokeStyle =
null)
452 if (endAngle - startAngle == 0f)
456 if (endAngle - startAngle < 0f)
458 Debug.LogWarning(
"DrawEllipse() only works in the clockwise-direction; please ensure endAngle > startAngle.");
461 Vector2 vector = center;
466 float num = MathF.PI / 2f - startAngle * (MathF.PI / 180f);
467 float num2 = MathF.PI * 2f / (360f / stepSize);
468 int num3 = Mathf.CeilToInt((endAngle - startAngle) / stepSize) + 1;
469 List<Vector2> list =
new List<Vector2>();
471 for (
int i = 0; i < num3; i++)
473 list.Add(
new Vector2(Mathf.Cos(num - num2 * (
float)i) * radii.x + center.x, Mathf.Sin(num - num2 * (
float)i) * radii.y + center.y));
477 rotation *= MathF.PI / 180f;
479 float num5 = Mathf.Cos(rotation);
480 float num6 = Mathf.Sin(rotation);
481 for (
int j = 0; j < list.Count; j++)
483 float num7 = list[j].x - center.x;
484 float num8 = list[j].y - center.y;
485 list[j] =
new Vector2((num7 * num5 + num8 * num6) / num4 + vector.x, num8 * num5 - num7 * num6 + vector.y);
488 if (fillColor.HasValue)
491 if (endAngle - startAngle == 0f)
493 array =
new int[(list.Count - 1) * 3];
496 while (num9 < array.Length)
499 array[num9 + 1] = num10;
500 array[num9 + 2] = num10 + 1;
508 array =
new int[(list.Count - 2) * 3];
511 while (num11 < array.Length)
514 array[num11 + 1] = num12;
515 array[num11 + 2] = num12 + 1;
522 if (strokeStyle !=
null)
524 DrawPath(list.GetRange(1, list.Count - 2).ToArray(), strokeStyle, closePath:
true);
551 Debug.LogError(
"DrawRegularSolid() requires at least 3 sides.");
555 DrawCircle(center, radius, 360f / (
float)sides, rotation, 360f + rotation, fillColor, strokeStyle);
576 int num = radii.Length;
579 Debug.LogError(
"DrawIrregularSolid() requires at least 3 radii.");
582 float num2 = MathF.PI / 2f - rotation * (MathF.PI / 180f);
583 float num3 = MathF.PI * 2f / (float)num;
585 List<Vector2> list =
new List<Vector2>();
587 for (
int i = 0; i < num; i++)
589 Vector2 vector =
new Vector2(radii[i], radii[i] * num4);
590 list.Add(
new Vector2(Mathf.Cos(num2 - num3 * (
float)i) * vector.x + center.x, Mathf.Sin(num2 - num3 * (
float)i) * vector.y + center.y));
592 if (fillColor.HasValue)
594 int[] array =
new int[(list.Count - 1) * 3];
597 while (num5 < array.Length)
600 array[num5 + 1] = num6;
601 array[num5 + 2] = num6 + 1;
608 if (strokeStyle !=
null)
610 DrawPath(list.GetRange(1, list.Count - 2).ToArray(), strokeStyle, closePath:
true);
625 DrawPath(points, strokeStyle, closePath:
true);
630 if (points.Length < 3)
632 Debug.LogError(
"DrawPolygon() requires at least 3 vertices");
635 if (points.Length == 3)
637 points =
new Vector2[3]
645 else if (points.Length == 4)
651 int[] array =
new int[(points.Length - 2) * 3];
653 LinkedList<Vector2> linkedList =
new LinkedList<Vector2>(points);
654 List<LinkedListNode<Vector2>> list =
new List<LinkedListNode<Vector2>>();
655 List<LinkedListNode<Vector2>> list2 =
new List<LinkedListNode<Vector2>>();
656 List<LinkedListNode<Vector2>> list3 =
new List<LinkedListNode<Vector2>>();
657 LinkedListNode<Vector2> linkedListNode = linkedList.First;
658 LinkedListNode<Vector2> linkedListNode2 = linkedList.First;
659 while (linkedListNode.Next !=
null)
661 linkedListNode = linkedListNode.Next;
662 if (linkedListNode.Value.x < linkedListNode2.Value.x)
664 linkedListNode2 = linkedListNode;
667 LinkedListNode<Vector2> linkedListNode3 = linkedListNode2.Previous ?? linkedListNode2.List.Last;
668 LinkedListNode<Vector2> linkedListNode4 = linkedListNode2.Next ?? linkedListNode2.List.First;
669 Func<Vector2, Vector2, Vector2, bool> func = ((!(linkedListNode4.Value.y > linkedListNode3.Value.y)) ? ((Func<Vector2, Vector2, Vector2, bool>)delegate(Vector2 prev, Vector2 cur, Vector2 next)
671 Vector2 vector2 = cur - prev;
672 Vector2 rhs2 = next - cur;
673 return Vector2.Dot(
new Vector2(0f - vector2.y, vector2.x), rhs2) > 0f;
674 }) : ((Func<Vector2, Vector2, Vector2, bool>)delegate(Vector2 prev, Vector2 cur, Vector2 next)
676 Vector2 vector = cur - prev;
677 Vector2 rhs = next - cur;
678 return Vector2.Dot(
new Vector2(0f - vector.y, vector.x), rhs) < 0f;
680 linkedListNode = linkedList.First;
681 for (
int i = 0; i < linkedList.Count; i++)
683 linkedListNode3 = linkedListNode.Previous ?? linkedListNode.List.Last;
684 linkedListNode4 = linkedListNode.Next ?? linkedListNode.List.First;
685 if (func(linkedListNode3.Value, linkedListNode.Value, linkedListNode4.Value))
687 list2.Add(linkedListNode);
688 float triangleArea =
PUIUtils.
GetTriangleArea(linkedListNode3.Value, linkedListNode.Value, linkedListNode4.Value);
690 foreach (LinkedListNode<Vector2>
item in list3)
700 list.Add(linkedListNode);
705 list3.Add(linkedListNode);
707 linkedListNode = linkedListNode.Next;
709 while (linkedList.Count > 3)
711 linkedListNode = list[0];
712 linkedListNode3 = linkedListNode.Previous ?? linkedListNode.List.Last;
713 linkedListNode4 = linkedListNode.Next ?? linkedListNode.List.First;
714 array[num] = Array.IndexOf(points, linkedListNode3.Value);
715 array[num + 1] = Array.IndexOf(points, linkedListNode.Value);
716 array[num + 2] = Array.IndexOf(points, linkedListNode4.Value);
718 list.Remove(linkedListNode);
719 linkedList.Remove(linkedListNode);
720 LinkedListNode<Vector2>[] array2 =
new LinkedListNode<Vector2>[2] { linkedListNode3, linkedListNode4 };
721 foreach (LinkedListNode<Vector2> linkedListNode5
in array2)
723 LinkedListNode<Vector2> linkedListNode6 = linkedListNode5.Previous ?? linkedListNode5.List.Last;
724 LinkedListNode<Vector2> linkedListNode7 = linkedListNode5.Next ?? linkedListNode5.List.First;
725 if (func(linkedListNode6.Value, linkedListNode5.Value, linkedListNode7.Value))
727 if (list3.Contains(linkedListNode5))
729 list3.Remove(linkedListNode5);
730 list2.Add(linkedListNode5);
732 float triangleArea2 =
PUIUtils.
GetTriangleArea(linkedListNode6.Value, linkedListNode5.Value, linkedListNode7.Value);
734 foreach (LinkedListNode<Vector2> item2
in list3)
736 if (
PUIUtils.
PointInTriangle(item2.Value, linkedListNode6.Value, linkedListNode5.Value, linkedListNode7.Value, triangleArea2))
742 if (flag2 && !list.Contains(linkedListNode5))
744 list.Add(linkedListNode5);
746 else if (!flag2 && list.Contains(linkedListNode5))
748 list.Remove(linkedListNode5);
753 list2.Remove(linkedListNode5);
754 list3.Add(linkedListNode5);
758 array[num] = Array.IndexOf(points, linkedList.First.Value);
759 array[num + 1] = Array.IndexOf(points, linkedList.First.Next.Value);
760 array[num + 2] = Array.IndexOf(points, linkedList.First.Next.Next.Value);
763 if (strokeStyle !=
null)
765 DrawPath(points, strokeStyle, closePath:
true);
782 public void DrawLine(Vector2 point1, Vector2 point2)
804 DrawPath(points, strokeStyle, closePath:
false);
809 if (points.Length < 2)
811 Debug.LogError(
"DrawPath() needs at least two points to draw");
814 if (points.Length == 2)
816 DrawLine(points[0], points[1], strokeStyle);
819 Debug.LogWarning(
"DrawPath() can't close a path with only two points. 'closePath' parameter ignored.");
List< UIVertex > uiVertexTriangleStream
abstract List< UIVertex > GetUIVertexTriangleStream(Vector2 offset, Vector2 scale, Color32 color)
PUIFillElement(Vector2[] points, int[] triangles, Color32 color)
override List< UIVertex > GetUIVertexTriangleStream(Vector2 offset, Vector2 scale, Color32 color)
PUIStrokeElement(Vector2[] rawPoints, Vector2[] points, StrokeStyle strokeStyle, bool isClosedPath)
override List< UIVertex > GetUIVertexTriangleStream(Vector2 offset, Vector2 scale, Color32 color)
void UpdatePoints(Vector2[] newPoints)
static bool PointInTriangle(Vector2 point, Vector2 tri0, Vector2 tri1, Vector2 tri2, float triAarea)
static float GetTriangleArea(Vector2 tri0, Vector2 tri1, Vector2 tri2)
static Vector2[] GetLinePoints(Vector2 point1, Vector2 point2, float strokeThickness, float aspectRatio)
static Vector2[] GetPathPoints(Vector2[] points, bool closePath, float strokeThickness, float aspectRatio)
static float Cross2D(Vector2 lhs, Vector2 rhs)
static ? Vector2 GetLineIntersection(Vector2 line1P1, Vector2 line1P2, Vector2 line2P1, Vector2 line2P2)
void DrawRegularSolid(Vector2 center, float radius, int sides, Color fillColor)
void DrawSquare(Vector2 center, float size, Color fillColor, StrokeStyle strokeStyle)
override void OnPopulateMesh(VertexHelper vh)
void DrawCircle(Vector2 center, float radius, float stepSize=1f, float startAngle=0f, float endAngle=360f, Color? fillColor=null, StrokeStyle strokeStyle=null)
void DrawIrregularSolid(Vector2 center, float[] radii, Color fillColor, StrokeStyle strokeStyle)
void DrawRectangle(Rect rect, Color fillColor)
void DrawRectangle(float x, float y, float width, float height, Color fillColor, StrokeStyle strokeStyle)
void DrawRawMesh(Vector2[] points, int[] triangles, Color fillColor)
void DrawPath(Vector2[] points)
void DrawEllipse(Vector2 center, Vector2 radii, Color fillColor, StrokeStyle strokeStyle)
void DrawEllipse(Vector2 center, Vector2 radii, float stepSize=1f, float rotation=0f, float startAngle=0f, float endAngle=360f, Color? fillColor=null, StrokeStyle strokeStyle=null)
void DrawRectangle(Rect rect, float rotation=0f, Color? fillColor=null, StrokeStyle strokeStyle=null)
void DrawRectangle(float x, float y, float width, float height, float rotation=0f, Color? fillColor=null, StrokeStyle strokeStyle=null)
override void OnRectTransformDimensionsChange()
void DrawRectangle(float x, float y, float width, float height, StrokeStyle strokeStyle)
void DrawRegularSolid(Vector2 center, float radius, int sides, float rotation=0f, Color? fillColor=null, StrokeStyle strokeStyle=null)
void DrawPolygon(Vector2[] points, Color fillColor, StrokeStyle strokeStyle)
void DrawRegularSolid(Vector2 center, float radius, int sides, Color fillColor, StrokeStyle strokeStyle)
void DrawSquare(Vector2 center, float size, Color fillColor)
void DrawIrregularSolid(Vector2 center, float[] radii, Color fillColor)
void DrawCircle(Vector2 center, float radius, Color fillColor)
void DrawLine(Vector2 point1, Vector2 point2)
void DrawIrregularSolid(Vector2 center, float[] radii, StrokeStyle strokeStyle)
void DrawEllipse(Vector2 center, Vector2 radii, Color fillColor)
void DrawCircle(Vector2 center, float radius, Color fillColor, StrokeStyle strokeStyle)
void DrawPolygon(Vector2[] points, StrokeStyle strokeStyle)
void DrawPath(Vector2[] points, StrokeStyle strokeStyle, bool closePath)
void DrawIrregularSolid(Vector2 center, float[] radii, float rotation, Color? fillColor, StrokeStyle strokeStyle)
void DrawLine(Vector2 point1, Vector2 point2, StrokeStyle strokeStyle)
void DrawRectangle(float x, float y, float width, float height, Color fillColor)
void DrawRectangle(Rect rect, StrokeStyle strokeStyle)
List< PUIElement > elements
void DrawSquare(Vector2 center, float size, StrokeStyle strokeStyle)
void DrawCircle(Vector2 center, float radius, StrokeStyle strokeStyle)
void DrawSquare(Vector2 center, float size, float rotation=0f, Color? fillColor=null, StrokeStyle strokeStyle=null)
void DrawPath(Vector2[] points, StrokeStyle strokeStyle)
void DrawEllipse(Vector2 center, Vector2 radii, StrokeStyle strokeStyle)
void DrawPolygon(Vector2[] points, Color fillColor)
void DrawRegularSolid(Vector2 center, float radius, int sides, StrokeStyle strokeStyle)
void DrawRectangle(Rect rect, Color fillColor, StrokeStyle strokeStyle)
static StrokeStyle defaultStrokeStyle
StrokeScaleMode scaleMode