浏览代码

split Path into small files

/main
xingweizhu 5 年前
当前提交
b69e97e0
共有 9 个文件被更改,包括 1336 次插入1006 次删除
  1. 4
      Runtime/foundation/debug.cs
  2. 974
      Runtime/ui/utils/basic_types/path.cs
  3. 337
      Runtime/ui/utils/basic_types/rect.cs
  4. 149
      Runtime/ui/utils/basic_types/mesh_mesh.cs
  5. 11
      Runtime/ui/utils/basic_types/mesh_mesh.cs.meta
  6. 514
      Runtime/ui/utils/basic_types/path_cache.cs
  7. 11
      Runtime/ui/utils/basic_types/path_cache.cs.meta
  8. 331
      Runtime/ui/utils/basic_types/path_utils.cs
  9. 11
      Runtime/ui/utils/basic_types/path_utils.cs.meta

4
Runtime/foundation/debug.cs


}
}
//[Conditional("UIWidgets_DEBUG")]
[Conditional("UIWidgets_DEBUG")]
public static void assert(Func<bool> result, Func<string> message = null) {
if (!result()) {
throw new AssertionError(message != null ? message() : "");

//[Conditional("UIWidgets_DEBUG")]
[Conditional("UIWidgets_DEBUG")]
public static void assert(bool result, Func<string> message = null) {
if (!result) {
throw new AssertionError(message != null ? message() : "");

974
Runtime/ui/utils/basic_types/path.cs
文件差异内容过多而无法显示
查看文件

337
Runtime/ui/utils/basic_types/rect.cs


using System;
using UnityEngine;
public struct uiRect {
public float top;
public float left;
public float width;
public float height;
public class uiRect : IEquatable<Rect> {
uiRect(float left, float top, float right, float bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
public static uiRect fromLTRB(float left, float top, float right, float bottom) {
return new uiRect(left, top, right, bottom);
}
public static uiRect fromLTWH(float left, float top, float width, float height) {
return new uiRect(left, top, left + width, top + height);
}
public static uiRect fromCircle(Offset center, float radius) {
return new uiRect(center.dx - radius, center.dy - radius, center.dx + radius, center.dy + radius);
}
public static uiRect fromPoints(Offset a, Offset b) {
return new uiRect(
Mathf.Min(a.dx, b.dx),
Mathf.Min(a.dy, b.dy),
Mathf.Max(a.dx, b.dx),
Mathf.Max(a.dy, b.dy)
);
}
public readonly float left;
public readonly float top;
public readonly float right;
public readonly float bottom;
public float width {
get { return this.right - this.left; }
}
public float height {
get { return this.bottom - this.top; }
}
public Size size {
get { return new Size(this.width, this.height); }
}
public static readonly uiRect zero = new uiRect(0, 0, 0, 0);
public static readonly uiRect one = new uiRect(0, 0, 1, 1);
public static readonly uiRect infinity = new uiRect(float.NegativeInfinity, float.NegativeInfinity,
float.PositiveInfinity, float.PositiveInfinity);
public const float _giantScalar = 1.0E+9f;
public static readonly uiRect largest =
fromLTRB(-_giantScalar, -_giantScalar, _giantScalar, _giantScalar);
public bool isInfinite {
get {
return float.IsInfinity(this.left)
|| float.IsInfinity(this.top)
|| float.IsInfinity(this.right)
|| float.IsInfinity(this.bottom);
}
}
public bool isFinite {
get { return !this.isInfinite; }
}
public bool isEmpty {
get { return this.left >= this.right || this.top >= this.bottom; }
}
public uiRect shift(Offset offset) {
return fromLTRB(this.left + offset.dx, this.top + offset.dy, this.right + offset.dx,
this.bottom + offset.dy);
}
public uiRect translate(float translateX, float translateY) {
return fromLTRB(this.left + translateX, this.top + translateY, this.right + translateX,
this.bottom + translateY);
}
public uiRect scale(float scaleX, float? scaleY = null) {
scaleY = scaleY ?? scaleX;
return fromLTRB(
this.left * scaleX, this.top * scaleY.Value,
this.right * scaleX, this.bottom * scaleY.Value);
}
public uiRect outset(float dx, float dy) {
return new uiRect(this.left - dx, this.top - dy, this.right + dx, this.bottom + dy);
}
public uiRect inflate(float delta) {
return fromLTRB(this.left - delta, this.top - delta, this.right + delta, this.bottom + delta);
}
public uiRect deflate(float delta) {
return this.inflate(-delta);
}
public uiRect intersect(Rect other) {
return fromLTRB(
Mathf.Max(this.left, other.left),
Mathf.Max(this.top, other.top),
Mathf.Min(this.right, other.right),
Mathf.Min(this.bottom, other.bottom)
);
}
public uiRect expandToInclude(uiRect other) {
if (this.isEmpty) {
return other;
}
if (other == null || other.isEmpty) {
return this;
}
return fromLTRB(
Mathf.Min(this.left, other.left),
Mathf.Min(this.top, other.top),
Mathf.Max(this.right, other.right),
Mathf.Max(this.bottom, other.bottom)
);
}
public bool overlaps(Rect other) {
if (this.right <= other.left || other.right <= this.left) {
return false;
}
if (this.bottom <= other.top || other.bottom <= this.top) {
return false;
}
return true;
}
public float shortestSide {
get { return Mathf.Min(Mathf.Abs(this.width), Mathf.Abs(this.height)); }
}
public float longestSide {
get { return Mathf.Max(Mathf.Abs(this.width), Mathf.Abs(this.height)); }
}
public Offset topLeft {
get { return new Offset(this.left, this.top); }
}
public Offset topCenter {
get { return new Offset(this.left + this.width / 2.0f, this.top); }
}
public Offset topRight {
get { return new Offset(this.right, this.top); }
}
public Offset centerLeft {
get { return new Offset(this.left, this.top + this.height / 2.0f); }
}
public static uiRect fromRect(Rect rect) {
return new uiRect {
top = rect.top,
left = rect.left,
width = rect.width,
height = rect.height
};
public Offset center {
get { return new Offset(this.left + this.width / 2.0f, this.top + this.height / 2.0f); }
}
public struct uiOffset {
public float dx;
public float dy;
public Offset centerRight {
get { return new Offset(this.right, this.bottom); }
}
public static uiOffset fromOffset(Offset offset) {
return new uiOffset {
dx = offset.dx,
dy = offset.dy
};
public Offset bottomLeft {
get { return new Offset(this.left, this.bottom); }
}
public struct uiSize {
public float width;
public float height;
public Offset bottomCenter {
get { return new Offset(this.left + this.width / 2.0f, this.bottom); }
}
public static uiSize fromSize(Size size) {
return new uiSize {
width = size.width,
height = size.height
};
public Offset bottomRight {
get { return new Offset(this.right, this.bottom); }
}
public bool contains(Offset offset) {
return offset.dx >= this.left && offset.dx < this.right && offset.dy >= this.top && offset.dy < this.bottom;
}
public bool containsInclusive(Offset offset) {
return offset.dx >= this.left && offset.dx <= this.right && offset.dy >= this.top &&
offset.dy <= this.bottom;
}
public bool contains(Rect rect) {
return this.contains(rect.topLeft) && this.contains(rect.bottomRight);
}
public uiRect round() {
return fromLTRB(
Mathf.Round(this.left), Mathf.Round(this.top),
Mathf.Round(this.right), Mathf.Round(this.bottom));
}
public uiRect roundOut() {
return fromLTRB(
Mathf.Floor(this.left), Mathf.Floor(this.top),
Mathf.Ceil(this.right), Mathf.Ceil(this.bottom));
}
public uiRect roundOut(float devicePixelRatio) {
return fromLTRB(
Mathf.Floor(this.left * devicePixelRatio) / devicePixelRatio,
Mathf.Floor(this.top * devicePixelRatio) / devicePixelRatio,
Mathf.Ceil(this.right * devicePixelRatio) / devicePixelRatio,
Mathf.Ceil(this.bottom * devicePixelRatio) / devicePixelRatio);
}
public uiRect roundIn() {
return fromLTRB(
Mathf.Ceil(this.left), Mathf.Ceil(this.top),
Mathf.Floor(this.right), Mathf.Floor(this.bottom));
}
public uiRect normalize() {
if (this.left <= this.right && this.top <= this.bottom) {
return this;
}
return fromLTRB(
Mathf.Min(this.left, this.right),
Mathf.Min(this.top, this.bottom),
Mathf.Max(this.left, this.right),
Mathf.Max(this.top, this.bottom)
);
}
public static uiRect lerp(Rect a, Rect b, float t) {
if (a == null && b == null) {
return null;
}
if (a == null) {
return fromLTRB(b.left * t, b.top * t, b.right * t, b.bottom * t);
}
if (b == null) {
float k = 1.0f - t;
return fromLTRB(a.left * k, a.top * k, a.right * k, a.bottom * k);
}
return fromLTRB(
MathUtils.lerpFloat(a.left, b.left, t),
MathUtils.lerpFloat(a.top, b.top, t),
MathUtils.lerpFloat(a.right, b.right, t),
MathUtils.lerpFloat(a.bottom, b.bottom, t)
);
}
public bool Equals(Rect other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.left.Equals(other.left) && this.top.Equals(other.top) && this.right.Equals(other.right) &&
this.bottom.Equals(other.bottom);
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((Rect) obj);
}
public override int GetHashCode() {
unchecked {
var hashCode = this.left.GetHashCode();
hashCode = (hashCode * 397) ^ this.top.GetHashCode();
hashCode = (hashCode * 397) ^ this.right.GetHashCode();
hashCode = (hashCode * 397) ^ this.bottom.GetHashCode();
return hashCode;
}
}
public static bool operator ==(uiRect left, uiRect right) {
return Equals(left, right);
}
public static bool operator !=(uiRect left, uiRect right) {
return !Equals(left, right);
}
public override string ToString() {
return "Rect.fromLTRB(" + this.left.ToString("0.0") + ", " + this.top.ToString("0.0") + ", " +
this.right.ToString("0.0") + ", " + this.bottom.ToString("0.0") + ")";
}
}
}

149
Runtime/ui/utils/basic_types/mesh_mesh.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class uiMeshMesh : PoolItem {
public uiList<Vector3> vertices;
public uiList<int> triangles;
public uiList<Vector2> uv;
public uiMatrix3 matrix;
public Rect rawBounds;
Rect _bounds;
public Rect bounds {
get {
if (this._bounds == null) {
this._bounds = this.matrix != null ? this.matrix.mapRect(this.rawBounds) : this.rawBounds;
}
return this._bounds;
}
}
static readonly List<int> _boundsTriangles = new List<int>(6) {
0, 2, 1, 1, 2, 3
};
public uiMeshMesh boundsMesh {
get {
return create(this.bounds);
}
}
public uiMeshMesh() {
}
public override void clear() {
this.vertices?.dispose();
this.triangles?.dispose();
this.uv?.dispose();
this.vertices = null;
this.triangles = null;
this.uv = null;
this.matrix = null;
this.rawBounds = null;
this._bounds = null;
}
public static uiMeshMesh create(Rect rect) {
uiMeshMesh newMesh = ItemPoolManager.alloc<uiMeshMesh>();
newMesh.vertices = ItemPoolManager.alloc<uiList<Vector3>>();
newMesh.vertices.Add(new Vector3(rect.right, rect.bottom));
newMesh.vertices.Add(new Vector3(rect.right, rect.top));
newMesh.vertices.Add(new Vector3(rect.left, rect.bottom));
newMesh.vertices.Add(new Vector3(rect.left, rect.top));
newMesh.triangles = ItemPoolManager.alloc<uiList<int>>();
newMesh.triangles.AddRange(_boundsTriangles);
newMesh.rawBounds = rect;
newMesh._bounds = newMesh.rawBounds;
return newMesh;
}
public static uiMeshMesh create(uiMatrix3 matrix, uiList<Vector3> vertices, uiList<int> triangles, uiList<Vector2> uv = null,
Rect rawBounds = null) {
D.assert(vertices != null);
D.assert(vertices.Count >= 0);
D.assert(triangles != null);
D.assert(triangles.Count >= 0);
D.assert(uv == null || uv.Count == vertices.Count);
uiMeshMesh newMesh = ItemPoolManager.alloc<uiMeshMesh>();
newMesh.matrix = matrix;
newMesh.vertices = vertices;
newMesh.triangles = triangles;
if (uv != null) {
newMesh.uv = uv;
}
if (rawBounds == null) {
if (vertices.Count > 0) {
float minX = vertices[0].x;
float maxX = vertices[0].x;
float minY = vertices[0].y;
float maxY = vertices[0].y;
for (int i = 1; i < vertices.Count; i++) {
var vertex = vertices[i];
if (vertex.x < minX) {
minX = vertex.x;
}
if (vertex.x > maxX) {
maxX = vertex.x;
}
if (vertex.y < minY) {
minY = vertex.y;
}
if (vertex.y > maxY) {
maxY = vertex.y;
}
}
rawBounds = Rect.fromLTRB(minX, minY, maxX, maxY);
}
else {
rawBounds = Rect.zero;
}
}
newMesh.rawBounds = rawBounds;
return newMesh;
}
public uiMeshMesh duplicate() {
return this.transform(this.matrix);
}
public uiMeshMesh transform(uiMatrix3 matrix) {
var vertices = ItemPoolManager.alloc<uiList<Vector3>>();
vertices.SetCapacity(this.vertices.Count);
vertices.AddRange(this.vertices.data);
var triangles = ItemPoolManager.alloc<uiList<int>>();
triangles.SetCapacity(this.triangles.Count);
triangles.AddRange(this.triangles.data);
uiList<Vector2> uv = null;
if (this.uv != null) {
uv = ItemPoolManager.alloc<uiList<Vector2>>();
uv.SetCapacity(this.uv.Count);
uv.AddRange(this.uv.data);
}
var ret = create(matrix, vertices, triangles, uv, this.rawBounds);
return ret;
}
}
}

11
Runtime/ui/utils/basic_types/mesh_mesh.cs.meta


fileFormatVersion: 2
guid: 2e5b97cbd47ac784790290e5fa696f60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

514
Runtime/ui/utils/basic_types/path_cache.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class uiPathCache : PoolItem {
float _distTol;
float _tessTol;
List<uiPathPath> _paths = new List<uiPathPath>();
List<uiPathPoint> _points = new List<uiPathPoint>();
public static uiPathCache create(float scale) {
uiPathCache newPathCache = ItemPoolManager.alloc<uiPathCache>();
newPathCache._distTol = 0.01f / scale;
newPathCache._tessTol = 0.25f / scale;
return newPathCache;
}
public override void clear() {
foreach (var path in this._paths) {
path.dispose();
}
foreach (var point in this._points) {
point.dispose();
}
this._paths.Clear();
this._points.Clear();
}
public uiPathCache() {
}
public void addPath() {
this._paths.Add(uiPathPath.create(
first : this._points.Count,
winding : uiPathWinding.counterClockwise
));
}
public void addPoint(float x, float y, uiPointFlags flags) {
this._addPoint(uiPathPoint.create(x : x, y : y, flags : flags));
}
void _addPoint(uiPathPoint point) {
if (this._paths.Count == 0) {
this.addPath();
this.addPoint(0, 0, uiPointFlags.corner);
}
var path = this._paths[this._paths.Count - 1];
if (path.count > 0) {
var pt = this._points[this._points.Count - 1];
if (uiPathUtils.ptEquals(pt.x, pt.y, point.x, point.y, this._distTol)) {
pt.flags |= point.flags;
point.dispose();
return;
}
}
this._points.Add(point);
path.count++;
}
public void tessellateBezier(
float x2, float y2,
float x3, float y3, float x4, float y4,
uiPointFlags flags) {
float x1, y1;
if (this._points.Count == 0) {
x1 = 0;
y1 = 0;
}
else {
var pt = this._points[this._points.Count - 1];
x1 = pt.x;
y1 = pt.y;
}
if (x1 == x2 && x1 == x3 && x1 == x4 &&
y1 == y2 && y1 == y3 && y1 == y4) {
return;
}
var points = uiTessellationGenerator.tessellateBezier(x1, y1, x2, y2, x3, y3, x4, y4, this._tessTol);
D.assert(points.Count > 0);
for (int i = 0; i < points.Count; i++) {
var point = points[i];
if (i == points.Count - 1) {
this._addPoint(uiPathPoint.create(
x : point.x + x1,
y : point.y + y1,
flags : flags
));
} else {
this._addPoint(uiPathPoint.create(
x : point.x + x1,
y : point.y + y1
));
}
}
}
public void closePath() {
if (this._paths.Count == 0) {
return;
}
var path = this._paths[this._paths.Count - 1];
path.closed = true;
}
public void pathWinding(uiPathWinding winding) {
if (this._paths.Count == 0) {
return;
}
var path = this._paths[this._paths.Count - 1];
path.winding = winding;
}
public void normalize() {
var points = this._points;
var paths = this._paths;
for (var j = 0; j < paths.Count; j++) {
var path = paths[j];
if (path.count <= 1) {
continue;
}
var ip0 = path.first + path.count - 1;
var ip1 = path.first;
var p0 = points[ip0];
var p1 = points[ip1];
if (uiPathUtils.ptEquals(p0.x, p0.y, p1.x, p1.y, this._distTol)) {
path.count--;
path.closed = true;
}
if (path.count > 2) {
if (path.winding == uiPathWinding.clockwise) {
uiPathUtils.polyReverse(points, path.first, path.count);
}
}
}
}
uiList<Vector3> _expandFill() {
var points = this._points;
var paths = this._paths;
for (var j = 0; j < paths.Count; j++) {
var path = paths[j];
if (path.count <= 2) {
continue;
}
var ip0 = path.first + path.count - 1;
var ip1 = path.first;
for (var i = 0; i < path.count; i++) {
var p0 = points[ip0];
var p1 = points[ip1];
p0.dx = p1.x - p0.x; // no need to normalize
p0.dy = p1.y - p0.y;
ip0 = ip1++;
}
path.convex = true;
ip0 = path.first + path.count - 1;
ip1 = path.first;
for (var i = 0; i < path.count; i++) {
var p0 = points[ip0];
var p1 = points[ip1];
float cross = p1.dx * p0.dy - p0.dx * p1.dy;
if (cross < 0.0f) {
path.convex = false;
}
ip0 = ip1++;
}
}
var cvertices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
cvertices += path.count;
}
var _vertices = ItemPoolManager.alloc<uiList<Vector3>>();
_vertices.SetCapacity(cvertices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
path.ifill = _vertices.Count;
for (var j = 0; j < path.count; j++) {
var p = points[path.first + j];
_vertices.Add(new Vector2(p.x, p.y));
}
path.nfill = _vertices.Count - path.ifill;
}
return _vertices;
}
public uiMeshMesh getFillMesh(out bool convex) {
var vertices = this._expandFill();
var paths = this._paths;
var cindices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
if (path.nfill > 0) {
D.assert(path.nfill >= 2);
cindices += (path.nfill - 2) * 3;
}
}
var indices = ItemPoolManager.alloc<uiList<int>>();
indices.SetCapacity(cindices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
if (path.nfill > 0) {
for (var j = 2; j < path.nfill; j++) {
indices.Add(path.ifill);
indices.Add(path.ifill + j);
indices.Add(path.ifill + j - 1);
}
}
}
D.assert(indices.Count == cindices);
var mesh = uiMeshMesh.create(null, vertices, indices);
var _fillMesh = mesh;
var _fillConvex = false;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
if (_fillConvex) {
// if more than two paths, convex is false.
_fillConvex = false;
break;
}
if (!path.convex) {
// if not convex, convex is false.
break;
}
_fillConvex = true;
}
convex = _fillConvex;
return _fillMesh;
}
void _calculateJoins(float w, StrokeJoin lineJoin, float miterLimit) {
float iw = w > 0.0f ? 1.0f / w : 0.0f;
var points = this._points;
var paths = this._paths;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
var ip0 = path.first + path.count - 1;
var ip1 = path.first;
for (var j = 0; j < path.count; j++) {
var p0 = points[ip0];
var p1 = points[ip1];
p0.dx = p1.x - p0.x;
p0.dy = p1.y - p0.y;
p0.len = uiPathUtils.normalize(ref p0.dx, ref p0.dy);
ip0 = ip1++;
}
ip0 = path.first + path.count - 1;
ip1 = path.first;
for (var j = 0; j < path.count; j++) {
var p0 = points[ip0];
var p1 = points[ip1];
float dlx0 = p0.dy;
float dly0 = -p0.dx;
float dlx1 = p1.dy;
float dly1 = -p1.dx;
// Calculate extrusions
p1.dmx = (dlx0 + dlx1) * 0.5f;
p1.dmy = (dly0 + dly1) * 0.5f;
float dmr2 = p1.dmx * p1.dmx + p1.dmy * p1.dmy;
if (dmr2 > 0.000001f) {
float scale = 1.0f / dmr2;
if (scale > 600.0f) {
scale = 600.0f;
}
p1.dmx *= scale;
p1.dmy *= scale;
}
// Clear flags, but keep the corner.
p1.flags &= uiPointFlags.corner;
// Keep track of left turns.
float cross = p1.dx * p0.dy - p0.dx * p1.dy;
if (cross > 0.0f) {
p1.flags |= uiPointFlags.left;
}
// Calculate if we should use bevel or miter for inner join.
float limit = Mathf.Max(1.01f, Mathf.Min(p0.len, p1.len) * iw);
if (dmr2 * limit * limit < 1.0f) {
p1.flags |= uiPointFlags.innerBevel;
}
// Check to see if the corner needs to be beveled.
if ((p1.flags & uiPointFlags.corner) != 0) {
if (lineJoin == StrokeJoin.bevel ||
lineJoin == StrokeJoin.round || dmr2 * miterLimit * miterLimit < 1.0f) {
p1.flags |= uiPointFlags.bevel;
}
}
ip0 = ip1++;
}
}
}
uiList<Vector3> _expandStroke(float w, StrokeCap lineCap, StrokeJoin lineJoin, float miterLimit) {
this._calculateJoins(w, lineJoin, miterLimit);
int ncap = 0;
if (lineCap == StrokeCap.round || lineJoin == StrokeJoin.round) {
ncap = uiPathUtils.curveDivs(w, Mathf.PI, this._tessTol);
}
var points = this._points;
var paths = this._paths;
var cvertices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
cvertices += path.count * 2;
cvertices += 4;
}
var _vertices = ItemPoolManager.alloc<uiList<Vector3>>();
_vertices.SetCapacity(cvertices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
path.istroke = _vertices.Count;
int s, e, ip0, ip1;
if (path.closed) {
ip0 = path.first + path.count - 1;
ip1 = path.first;
s = 0;
e = path.count;
}
else {
ip0 = path.first;
ip1 = path.first + 1;
s = 1;
e = path.count - 1;
}
var p0 = points[ip0];
var p1 = points[ip1];
if (!path.closed) {
if (lineCap == StrokeCap.butt) {
_vertices.buttCapStart(p0, p0.dx, p0.dy, w, 0.0f);
}
else if (lineCap == StrokeCap.square) {
_vertices.buttCapStart(p0, p0.dx, p0.dy, w, w);
}
else {
// round
_vertices.roundCapStart(p0, p0.dx, p0.dy, w, ncap);
}
}
for (var j = s; j < e; j++) {
p0 = points[ip0];
p1 = points[ip1];
if ((p1.flags & (uiPointFlags.bevel | uiPointFlags.innerBevel)) != 0) {
if (lineJoin == StrokeJoin.round) {
_vertices.roundJoin(p0, p1, w, w, ncap);
}
else {
_vertices.bevelJoin(p0, p1, w, w);
}
}
else {
_vertices.Add(new Vector2(p1.x + p1.dmx * w, p1.y + p1.dmy * w));
_vertices.Add(new Vector2(p1.x - p1.dmx * w, p1.y - p1.dmy * w));
}
ip0 = ip1++;
}
if (!path.closed) {
p0 = points[ip0];
p1 = points[ip1];
if (lineCap == StrokeCap.butt) {
_vertices.buttCapEnd(p1, p0.dx, p0.dy, w, 0.0f);
}
else if (lineCap == StrokeCap.square) {
_vertices.buttCapEnd(p1, p0.dx, p0.dy, w, w);
}
else {
// round
_vertices.roundCapEnd(p1, p0.dx, p0.dy, w, ncap);
}
}
else {
_vertices.Add(_vertices[path.istroke]);
_vertices.Add(_vertices[path.istroke + 1]);
}
path.nstroke = _vertices.Count - path.istroke;
}
return _vertices;
}
public uiMeshMesh getStrokeMesh(float strokeWidth, StrokeCap lineCap, StrokeJoin lineJoin, float miterLimit) {
var vertices = this._expandStroke(strokeWidth, lineCap, lineJoin, miterLimit);
var paths = this._paths;
var cindices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
if (path.nstroke > 0) {
D.assert(path.nstroke >= 2);
cindices += (path.nstroke - 2) * 3;
}
}
var indices = ItemPoolManager.alloc<uiList<int>>();
indices.SetCapacity(cindices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
if (path.nstroke > 0) {
for (var j = 2; j < path.nstroke; j++) {
if ((j & 1) == 0) {
indices.Add(path.istroke + j - 1);
indices.Add(path.istroke + j - 2);
indices.Add(path.istroke + j);
}
else {
indices.Add(path.istroke + j - 2);
indices.Add(path.istroke + j - 1);
indices.Add(path.istroke + j);
}
}
}
}
D.assert(indices.Count == cindices);
var _strokeMesh = uiMeshMesh.create(null, vertices, indices);
return _strokeMesh;
}
}
}

11
Runtime/ui/utils/basic_types/path_cache.cs.meta


fileFormatVersion: 2
guid: c97372c9ed12471459d1a3ed41a3b2fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

331
Runtime/ui/utils/basic_types/path_utils.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public enum uiPathWinding {
counterClockwise = 1, // which just means the order as the input is.
clockwise = 2, // which just means the reversed order.
}
enum uiPathCommand {
moveTo,
lineTo,
bezierTo,
close,
winding,
}
[Flags]
enum uiPointFlags {
corner = 0x01,
left = 0x02,
bevel = 0x04,
innerBevel = 0x08,
}
class uiPathPoint : PoolItem {
public float x, y;
public float dx, dy;
public float len;
public float dmx, dmy;
public uiPointFlags flags;
public static uiPathPoint create(float x = 0, float y = 0, float dx = 0, float dy = 0, float len = 0,
float dmx = 0, float dmy = 0,
uiPointFlags flags = uiPointFlags.corner) {
uiPathPoint newPoint = ItemPoolManager.alloc<uiPathPoint>();
newPoint.x = x;
newPoint.y = y;
newPoint.dx = dx;
newPoint.dy = dy;
newPoint.len = len;
newPoint.dmx = dmx;
newPoint.dmy = dmy;
newPoint.flags = flags;
return newPoint;
}
public uiPathPoint() {
}
}
class uiPathPath : PoolItem {
public int first;
public int count;
public bool closed;
public int ifill;
public int nfill;
public int istroke;
public int nstroke;
public uiPathWinding winding;
public bool convex;
public static uiPathPath create(int first = 0, int count = 0, bool closed = false, int ifill = 0, int nfill = 0,
int istroke = 0,
int nstroke = 0, uiPathWinding winding = uiPathWinding.counterClockwise, bool convex = false) {
uiPathPath newPath = ItemPoolManager.alloc<uiPathPath>();
newPath.first = first;
newPath.count = count;
newPath.closed = closed;
newPath.ifill = ifill;
newPath.nfill = nfill;
newPath.istroke = istroke;
newPath.nstroke = nstroke;
newPath.winding = winding;
newPath.convex = convex;
return newPath;
}
public uiPathPath() {
}
}
static class uiPathUtils {
public static bool ptEquals(float x1, float y1, float x2, float y2, float tol) {
float dx = x2 - x1;
float dy = y2 - y1;
if (dx <= -tol || dx >= tol || dy <= -tol || dy >= tol) {
return false;
}
return dx * dx + dy * dy < tol * tol;
}
public static void polyReverse(List<uiPathPoint> pts, int s, int npts) {
int i = s, j = s + npts - 1;
while (i < j) {
var tmp = pts[i];
pts[i] = pts[j];
pts[j] = tmp;
i++;
j--;
}
}
public static float normalize(ref float x, ref float y) {
float d = Mathf.Sqrt(x * x + y * y);
if (d > 1e-6f) {
float id = 1.0f / d;
x *= id;
y *= id;
}
return d;
}
public static void buttCapStart(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, float d) {
float px = p.x - dx * d;
float py = p.y - dy * d;
float dlx = dy;
float dly = -dx;
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
}
public static void buttCapEnd(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, float d) {
float px = p.x + dx * d;
float py = p.y + dy * d;
float dlx = dy;
float dly = -dx;
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
}
public static void roundCapStart(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, int ncap) {
float px = p.x;
float py = p.y;
float dlx = dy;
float dly = -dx;
for (var i = 0; i < ncap; i++) {
float a = (float) i / (ncap - 1) * Mathf.PI;
float ax = Mathf.Cos(a) * w, ay = Mathf.Sin(a) * w;
dst.Add(new Vector2(px - dlx * ax - dx * ay, py - dly * ax - dy * ay));
dst.Add(new Vector2(px, py));
}
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
}
public static void roundCapEnd(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, int ncap) {
float px = p.x;
float py = p.y;
float dlx = dy;
float dly = -dx;
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
for (var i = 0; i < ncap; i++) {
float a = (float) i / (ncap - 1) * Mathf.PI;
float ax = Mathf.Cos(a) * w, ay = Mathf.Sin(a) * w;
dst.Add(new Vector2(px, py));
dst.Add(new Vector2(px - dlx * ax + dx * ay, py - dly * ax + dy * ay));
}
}
public static void chooseBevel(bool bevel, uiPathPoint p0, uiPathPoint p1, float w,
out float x0, out float y0, out float x1, out float y1) {
if (bevel) {
x0 = p1.x + p0.dy * w;
y0 = p1.y - p0.dx * w;
x1 = p1.x + p1.dy * w;
y1 = p1.y - p1.dx * w;
}
else {
x0 = p1.x + p1.dmx * w;
y0 = p1.y + p1.dmy * w;
x1 = p1.x + p1.dmx * w;
y1 = p1.y + p1.dmy * w;
}
}
public static int curveDivs(float r, float arc, float tol) {
float da = Mathf.Acos(r / (r + tol)) * 2.0f;
return Mathf.Max(2, Mathf.CeilToInt(arc / da));
}
public static void roundJoin(this uiList<Vector3> dst, uiPathPoint p0, uiPathPoint p1,
float lw, float rw, int ncap) {
float dlx0 = p0.dy;
float dly0 = -p0.dx;
float dlx1 = p1.dy;
float dly1 = -p1.dx;
if ((p1.flags & uiPointFlags.left) != 0) {
float lx0, ly0, lx1, ly1;
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, lw,
out lx0, out ly0, out lx1, out ly1);
float a0 = Mathf.Atan2(-dly0, -dlx0);
float a1 = Mathf.Atan2(-dly1, -dlx1);
if (a1 > a0) {
a1 -= Mathf.PI * 2;
}
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw));
var n = Mathf.CeilToInt((a0 - a1) / Mathf.PI * ncap).clamp(2, ncap);
for (var i = 0; i < n; i++) {
float u = (float) i / (n - 1);
float a = a0 + u * (a1 - a0);
float rx = p1.x + Mathf.Cos(a) * rw;
float ry = p1.y + Mathf.Sin(a) * rw;
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(rx, ry));
}
dst.Add(new Vector2(lx1, ly1));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
else {
float rx0, ry0, rx1, ry1;
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, -rw,
out rx0, out ry0, out rx1, out ry1);
float a0 = Mathf.Atan2(dly0, dlx0);
float a1 = Mathf.Atan2(dly1, dlx1);
if (a1 < a0) {
a1 += Mathf.PI * 2;
}
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(rx0, ry0));
var n = Mathf.CeilToInt((a1 - a0) / Mathf.PI * ncap).clamp(2, ncap);
for (var i = 0; i < n; i++) {
float u = (float) i / (n - 1);
float a = a0 + u * (a1 - a0);
float lx = p1.x + Mathf.Cos(a) * lw;
float ly = p1.y + Mathf.Sin(a) * lw;
dst.Add(new Vector2(lx, ly));
dst.Add(new Vector2(p1.x, p1.y));
}
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(rx1, ry1));
}
}
public static void bevelJoin(this uiList<Vector3> dst, uiPathPoint p0, uiPathPoint p1,
float lw, float rw) {
float rx0, ry0, rx1, ry1;
float lx0, ly0, lx1, ly1;
float dlx0 = p0.dy;
float dly0 = -p0.dx;
float dlx1 = p1.dy;
float dly1 = -p1.dx;
if ((p1.flags & uiPointFlags.left) != 0) {
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, lw,
out lx0, out ly0, out lx1, out ly1);
dst.Add(new Vector2 {x = lx0, y = ly0});
dst.Add(new Vector2 {x = p1.x - dlx0 * rw, y = p1.y - dly0 * rw});
if ((p1.flags & uiPointFlags.bevel) != 0) {
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw));
dst.Add(new Vector2(lx1, ly1));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
else {
rx0 = p1.x - p1.dmx * rw;
ry0 = p1.y - p1.dmy * rw;
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw));
dst.Add(new Vector2(rx0, ry0));
dst.Add(new Vector2(rx0, ry0));
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
dst.Add(new Vector2(lx1, ly1));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
else {
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, -rw,
out rx0, out ry0, out rx1, out ry1);
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(rx0, ry0));
if ((p1.flags & uiPointFlags.bevel) != 0) {
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(rx0, ry0));
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(rx1, ry1));
}
else {
lx0 = p1.x + p1.dmx * lw;
ly0 = p1.y + p1.dmy * lw;
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(p1.x, p1.y));
}
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(rx1, ry1));
}
}
}
}

11
Runtime/ui/utils/basic_types/path_utils.cs.meta


fileFormatVersion: 2
guid: 2557784b74abe7142984ee42c406a414
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存