using System; using System.Collections.Generic; using System.Linq; using o0.Geometry2D; using o0.Geometry2D.Float; using UnityEngine; namespace ZIM.Unity { // 屏幕识别使用,记录摄像机画面内的四边形 public class QuadrilateralInCamera { public Vector CameraSize; public OrdinalQuadrilateral Quad; // 固定的顶点顺序: 左下,右下,左上,右上 public QuadrilateralInCamera(Vector2 a, Vector2 b, Vector2 c, Vector2 d, Vector2 cameraSize) { CameraSize = cameraSize.o0Vector(); Quad = new OrdinalQuadrilateral(a.o0Vector(), b.o0Vector(), c.o0Vector(), d.o0Vector()); } // 固定的顶点顺序: 左下,右下,左上,右上 public QuadrilateralInCamera(Vector a, Vector b, Vector c, Vector d, Vector cameraSize) { CameraSize = cameraSize; Quad = new OrdinalQuadrilateral(a, b, c, d); } // 固定的顶点顺序: 左下,右下,左上,右上 public QuadrilateralInCamera(IEnumerable enumable, Vector cameraSize) { CameraSize = cameraSize; Quad = new OrdinalQuadrilateral(enumable); } // 固定的顶点顺序: 左下,右下,左上,右上 public QuadrilateralInCamera(IEnumerable enumable, Vector cameraSize) { CameraSize = cameraSize; Quad = new OrdinalQuadrilateral(enumable.Select((i => i.o0Vector()))); } public QuadrilateralInCamera(OrdinalQuadrilateral quad, Vector cameraSize) { CameraSize = cameraSize; Quad = quad; } public string SizeString => $"({CameraSize.x}, {CameraSize.y})"; public string QuadString => $"[({Quad.A.x}, {Quad.A.y}), ({Quad.B.x}, {Quad.B.y}), ({Quad.C.x}, {Quad.C.y}), ({Quad.D.x}, {Quad.D.y})]"; public override string ToString() => $"CameraSize: {SizeString}, Vertices: {QuadString}"; // 需要标准化的坐标(即数值范围0-1)时使用,会自动根据当前的CameraSize转换 private List ScreenVertexListNormalized { get { return new List { Quad.A / CameraSize, Quad.B / CameraSize, Quad.C / CameraSize, Quad.D / CameraSize }; } set { for (int i = 0; i < Quad.Count; i++) Quad[i] = value[i] * CameraSize; } } // 这里是标准化坐标(即数值范围0-1) public List GetUnityVertexNormalizedList() { return new List() { new Vector2(Quad.A.x / CameraSize.x, Quad.A.y / CameraSize.y), new Vector2(Quad.B.x / CameraSize.x, Quad.B.y / CameraSize.y), new Vector2(Quad.C.x / CameraSize.x, Quad.C.y / CameraSize.y), new Vector2(Quad.D.x / CameraSize.x, Quad.D.y / CameraSize.y) }; } // 线段顺序: 下、右、上、左 public Line[] GetLines() => new Line[4] { new Line(Quad.A, Quad.B), new Line(Quad.B, Quad.D), new Line(Quad.C, Quad.D), new Line(Quad.A, Quad.C) }; // 摄像机分辨率变化时调用 public void ReSize(Vector sizeNew, AspectRatioSetting viewAspectRatioSetting) { if (CameraSize != sizeNew) { float ratio; Func Translate; List vertices; switch (viewAspectRatioSetting) { case AspectRatioSetting.FixedAll: var scale = new Vector(sizeNew.x / CameraSize.x, sizeNew.y / CameraSize.y); CameraSize = sizeNew; for (int i = 0; i < Quad.Count; i++) Quad[i] *= scale; break; case AspectRatioSetting.FixedHeight: var wOld = CameraSize.x / CameraSize.y; // 宽度比高度 var wNew = sizeNew.x / sizeNew.y; ratio = wOld / wNew; Translate = (v) => { var x = v.x - 0.5f; return new Vector(x * ratio + 0.5f, v.y); }; vertices = ScreenVertexListNormalized; for (int i = 0; i < vertices.Count; i++) vertices[i] = Translate(vertices[i]); CameraSize = sizeNew; // 这里要先设置Size ScreenVertexListNormalized = vertices; break; case AspectRatioSetting.FixedWidth: var hOld = CameraSize.y / CameraSize.x; // 高度比宽度 var hNew = sizeNew.y / sizeNew.x; ratio = hOld / hNew; Translate = (v) => { var y = v.y - 0.5f; return new Vector(v.x, y * ratio + 0.5f); }; vertices = ScreenVertexListNormalized; for (int i = 0; i < vertices.Count; i++) vertices[i] = Translate(vertices[i]); CameraSize = sizeNew; ScreenVertexListNormalized = vertices; break; } } } // 四边形是否完整的在屏幕内 public bool IsQuadComplete() { if (Quad.A.x < Quad.B.x && Quad.A.y < Quad.C.y && Quad.B.y < Quad.D.y && Quad.C.x < Quad.D.x && Quad.A.x > 0 && Quad.A.y > 0 && Quad.B.x < CameraSize.x && Quad.B.y > 0 && Quad.C.x > 0 && Quad.C.y < CameraSize.y && Quad.D.x < CameraSize.x && Quad.D.y < CameraSize.y) return true; return false; } } }