diff options
Diffstat (limited to 'Client/Assembly-CSharp/LightSource.cs')
-rw-r--r-- | Client/Assembly-CSharp/LightSource.cs | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/Client/Assembly-CSharp/LightSource.cs b/Client/Assembly-CSharp/LightSource.cs new file mode 100644 index 0000000..891fcbf --- /dev/null +++ b/Client/Assembly-CSharp/LightSource.cs @@ -0,0 +1,335 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class LightSource : MonoBehaviour +{ + public static Dictionary<GameObject, NoShadowBehaviour> NoShadows = new Dictionary<GameObject, NoShadowBehaviour>(); + + public static Dictionary<GameObject, OneWayShadows> OneWayShadows = new Dictionary<GameObject, OneWayShadows>(); + + [HideInInspector] + private GameObject child; + + [HideInInspector] + private Vector2[] requiredDels; + + [HideInInspector] + private Mesh myMesh; + + public int MinRays = 24; + + public float LightRadius = 3f; + + public Material Material; + + [HideInInspector] + private List<LightSource.VertInfo> verts = new List<LightSource.VertInfo>(256); + + [HideInInspector] + private int vertCount; + + private RaycastHit2D[] buffer = new RaycastHit2D[25]; + + private Collider2D[] hits = new Collider2D[40]; + + private ContactFilter2D filter; + + private Vector3[] vec; + + private Vector2[] uvs; + + private int[] triangles = new int[1200]; + + public float tol = 0.05f; + + private Vector2 del; + + private Vector2 tan; + + private Vector2 side; + + private List<RaycastHit2D> lightHits = new List<RaycastHit2D>(); + + private class VertInfo + { + public float Angle; + + public Vector3 Position; + + internal void Complete(float x, float y) + { + this.Position.x = x; + this.Position.y = y; + this.Angle = LightSource.pseudoAngle(y, x); + } + + internal void Complete(Vector2 point) + { + this.Position.x = point.x; + this.Position.y = point.y; + this.Angle = LightSource.pseudoAngle(point.y, point.x); + } + } + + private class AngleComparer : IComparer<LightSource.VertInfo> + { + public static readonly LightSource.AngleComparer Instance = new LightSource.AngleComparer(); + + public int Compare(LightSource.VertInfo x, LightSource.VertInfo y) + { + if (x.Angle > y.Angle) + { + return 1; + } + if (x.Angle >= y.Angle) + { + return 0; + } + return -1; + } + } + + private class HitDepthComparer : IComparer<RaycastHit2D> + { + public static readonly LightSource.HitDepthComparer Instance = new LightSource.HitDepthComparer(); + + public int Compare(RaycastHit2D x, RaycastHit2D y) + { + if (x.fraction <= y.fraction) + { + return -1; + } + return 1; + } + } + + private void Start() + { + this.filter.useTriggers = true; + this.filter.layerMask = Constants.ShadowMask; + this.filter.useLayerMask = true; + this.requiredDels = new Vector2[this.MinRays]; + for (int i = 0; i < this.requiredDels.Length; i++) + { + this.requiredDels[i] = Vector2.left.Rotate((float)i / (float)this.requiredDels.Length * 360f); + } + this.myMesh = new Mesh(); + this.myMesh.MarkDynamic(); + this.myMesh.name = "ShadowMesh"; + GameObject gameObject = new GameObject("LightChild"); + gameObject.layer = 10; + gameObject.AddComponent<MeshFilter>().mesh = this.myMesh; + Renderer renderer = gameObject.AddComponent<MeshRenderer>(); + this.Material = new Material(this.Material); + renderer.sharedMaterial = this.Material; + this.child = gameObject; + } + + private void Update() + { + this.vertCount = 0; + Vector3 position = base.transform.position; + position.z -= 7f; + this.child.transform.position = position; + Vector2 vector = position; + this.Material.SetFloat("_LightRadius", this.LightRadius); + int num = Physics2D.OverlapCircleNonAlloc(vector, this.LightRadius, this.hits, Constants.ShadowMask); + for (int i = 0; i < num; i++) + { + Collider2D collider2D = this.hits[i]; + if (!collider2D.isTrigger) + { + EdgeCollider2D edgeCollider2D = collider2D as EdgeCollider2D; + if (edgeCollider2D) + { + Vector2[] points = edgeCollider2D.points; + for (int j = 0; j < points.Length; j++) + { + Vector2 vector2 = edgeCollider2D.transform.TransformPoint(points[j]); + this.del.x = vector2.x - vector.x; + this.del.y = vector2.y - vector.y; + this.TestBothSides(vector); + } + } + else + { + PolygonCollider2D polygonCollider2D = collider2D as PolygonCollider2D; + if (polygonCollider2D) + { + Vector2[] points2 = polygonCollider2D.points; + for (int k = 0; k < points2.Length; k++) + { + Vector2 vector3 = polygonCollider2D.transform.TransformPoint(points2[k]); + this.del.x = vector3.x - vector.x; + this.del.y = vector3.y - vector.y; + this.TestBothSides(vector); + } + } + else + { + BoxCollider2D boxCollider2D = collider2D as BoxCollider2D; + if (boxCollider2D) + { + Vector2 b = boxCollider2D.size / 2f; + Vector2 vector4 = boxCollider2D.transform.TransformPoint(boxCollider2D.offset - b) - vector; + Vector2 vector5 = boxCollider2D.transform.TransformPoint(boxCollider2D.offset + b) - vector; + this.del.x = vector4.x; + this.del.y = vector4.y; + this.TestBothSides(vector); + this.del.x = vector5.x; + this.TestBothSides(vector); + this.del.y = vector5.y; + this.TestBothSides(vector); + this.del.x = vector4.x; + this.TestBothSides(vector); + } + } + } + } + } + float d = this.LightRadius * 1.05f; + for (int l = 0; l < this.requiredDels.Length; l++) + { + Vector2 vector6 = d * this.requiredDels[l]; + this.CreateVert(vector, ref vector6); + } + this.verts.Sort(0, this.vertCount, LightSource.AngleComparer.Instance); + this.myMesh.Clear(); + if (this.vec == null || this.vec.Length < this.vertCount + 1) + { + this.vec = new Vector3[this.vertCount + 1]; + this.uvs = new Vector2[this.vec.Length]; + } + this.vec[0] = Vector3.zero; + this.uvs[0] = new Vector2(this.vec[0].x, this.vec[0].y); + for (int m = 0; m < this.vertCount; m++) + { + int num2 = m + 1; + this.vec[num2] = this.verts[m].Position; + this.uvs[num2] = new Vector2(this.vec[num2].x, this.vec[num2].y); + } + int num3 = this.vertCount * 3; + if (num3 > this.triangles.Length) + { + this.triangles = new int[num3]; + Debug.LogWarning("Resized triangles to: " + num3); + } + int num4 = 0; + for (int n = 0; n < this.triangles.Length; n += 3) + { + if (n < num3) + { + this.triangles[n] = 0; + this.triangles[n + 1] = num4 + 1; + if (n == num3 - 3) + { + this.triangles[n + 2] = 1; + } + else + { + this.triangles[n + 2] = num4 + 2; + } + num4++; + } + else + { + this.triangles[n] = 0; + this.triangles[n + 1] = 0; + this.triangles[n + 2] = 0; + } + } + this.myMesh.vertices = this.vec; + this.myMesh.uv = this.uvs; + this.myMesh.SetIndices(this.triangles, MeshTopology.Triangles, 0); + } + + private void TestBothSides(Vector2 myPos) + { + float num = LightSource.length(this.del.x, this.del.x); + this.tan.x = -this.del.y / num * this.tol; + this.tan.y = this.del.x / num * this.tol; + this.side.x = this.del.x + this.tan.x; + this.side.y = this.del.y + this.tan.y; + this.CreateVert(myPos, ref this.side); + this.side.x = this.del.x - this.tan.x; + this.side.y = this.del.y - this.tan.y; + this.CreateVert(myPos, ref this.side); + } + + private void CreateVert(Vector2 myPos, ref Vector2 del) + { + float num = this.LightRadius * 1.5f; + int num2 = Physics2D.Raycast(myPos, del, this.filter, this.buffer, num); + if (num2 > 0) + { + this.lightHits.Clear(); + RaycastHit2D raycastHit2D = default(RaycastHit2D); + Collider2D collider2D = null; + for (int i = 0; i < num2; i++) + { + RaycastHit2D raycastHit2D2 = this.buffer[i]; + Collider2D collider = raycastHit2D2.collider; + OneWayShadows oneWayShadows; + if (!LightSource.OneWayShadows.TryGetValue(collider.gameObject, out oneWayShadows) || !oneWayShadows.IsIgnored(this)) + { + this.lightHits.Add(raycastHit2D2); + if (!collider.isTrigger) + { + raycastHit2D = raycastHit2D2; + collider2D = collider; + break; + } + } + } + for (int j = 0; j < this.lightHits.Count; j++) + { + NoShadowBehaviour noShadowBehaviour; + if (LightSource.NoShadows.TryGetValue(this.lightHits[j].collider.gameObject, out noShadowBehaviour)) + { + noShadowBehaviour.didHit = true; + } + } + if (collider2D && !collider2D.isTrigger) + { + Vector2 point = raycastHit2D.point; + this.GetEmptyVert().Complete(point.x - myPos.x, point.y - myPos.y); + return; + } + } + Vector2 normalized = del.normalized; + this.GetEmptyVert().Complete(normalized.x * num, normalized.y * num); + } + + private LightSource.VertInfo GetEmptyVert() + { + if (this.vertCount < this.verts.Count) + { + List<LightSource.VertInfo> list = this.verts; + int num = this.vertCount; + this.vertCount = num + 1; + return list[num]; + } + LightSource.VertInfo vertInfo = new LightSource.VertInfo(); + this.verts.Add(vertInfo); + this.vertCount = this.verts.Count; + return vertInfo; + } + + private static float length(float x, float y) + { + return Mathf.Sqrt(x * x + y * y); + } + + public static float pseudoAngle(float dx, float dy) + { + if (dx < 0f) + { + float num = -dx; + float num2 = (dy > 0f) ? dy : (-dy); + return 2f - dy / (num + num2); + } + float num3 = (dy > 0f) ? dy : (-dy); + return dy / (dx + num3); + } +} |