using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class BeadDrawer : MonoBehaviour { private enum ExitSide { None = 0, Left = 1, Right = 2, Top = 3, Bottom = 4 } public static BeadDrawer instance; public GameObject beadPrefab; public Collider2D drawArea; public AudioClip beadSound; public AudioSource myAudioSource; public float minPitch = 0.5f; public float maxPitch = 2f; [SerializeField] private float constantDistance = 0.01f; [SerializeField] private float beadSizeMultiplier = 5.5f; [SerializeField] private float movingPlatformTimeLimit = 5f; private Vector3 previousPoint; private GameObject parentObject; private bool isDrawing; private int beadsSpawned; public bool cantHitBorder; private Camera mainCamera; private bool IsGameStarted; private bool IsLineDrawn; private PhysicsMaterial2D linePhysicsMat; private bool hasMoved; private bool _drawingBlocked; private bool _externalDragStart; private float lastVibrateTime; private const float vibrateInterval = 0.1f; private Vector2 touchDownScreenPos; private bool touchDownRecorded; private const float minMovePixels = 12f; private ExitSide currentExitSide; private float exitLockValue; private float lastBeadTime = -1f; private const float soundPauseDelay = 0.05f; private int _arrayCapacity = 3000; private Mesh drawMesh; private MeshFilter meshFilter; private MeshRenderer meshRenderer; private Material beadMaterial; private Vector3[] _verts; private Vector2[] _uvs; private int[] _tris; private int _quadCount; private Vector2 uvBL; private Vector2 uvBR; private Vector2 uvTR; private Vector2 uvTL; private float beadHalfSize; private Vector3[] _allBeadPosArr; private int _beadPosCount; private float _constantDistanceSq; private float _invConstantDistance; private Vector3 _boundsMin; private Vector3 _boundsMax; [SerializeField] [Header("Draw Blocking")] private LayerMask drawBlockingLayers; [Header("Tool Level")] public bool isToolLevel; public Rigidbody2D[] toolRigidbodies; public bool testMode; private const int COLLIDER_CHUNK_SIZE = 60; private const int MAX_COLLIDER_POINTS = 120; private readonly List _colliderPool = new List(); private int _activeChunks; public float LinemovedThreshold = 0.1f; public int DrawnBeadCount => _beadPosCount; public Rigidbody2D LineRigidbody => (parentObject != null) ? parentObject.GetComponent() : null; private void Awake() { instance = this; EyeBallTracker.LookTarget = null; } private void Start() { parentObject = UnityEngine.Object.Instantiate(GameManager.Instance.lineParentTr); if (parentObject != null) { EdgeCollider2D component = parentObject.GetComponent(); if (component != null) { component.enabled = false; _colliderPool.Add(component); } } mainCamera = Camera.main; beadHalfSize = constantDistance * beadSizeMultiplier * 0.5f; GameObject gameObject = new GameObject("BeadMesh"); gameObject.transform.SetParent(parentObject.transform, false); meshFilter = gameObject.AddComponent(); meshRenderer = gameObject.AddComponent(); _verts = new Vector3[_arrayCapacity * 4]; _uvs = new Vector2[_arrayCapacity * 4]; _tris = new int[_arrayCapacity * 6]; _allBeadPosArr = new Vector3[_arrayCapacity]; for (int i = 0; i < _arrayCapacity; i++) { _tris[i * 6] = i * 4; _tris[i * 6 + 1] = i * 4 + 2; _tris[i * 6 + 2] = i * 4 + 1; _tris[i * 6 + 3] = i * 4; _tris[i * 6 + 4] = i * 4 + 3; _tris[i * 6 + 5] = i * 4 + 2; } _constantDistanceSq = constantDistance * constantDistance; _invConstantDistance = 1f / constantDistance; drawMesh = new Mesh(); drawMesh.MarkDynamic(); meshFilter.mesh = drawMesh; if (beadPrefab != null) { SpriteRenderer component2 = beadPrefab.GetComponent(); if (component2 != null) { meshRenderer.sortingLayerID = component2.sortingLayerID; meshRenderer.sortingOrder = component2.sortingOrder; } } SetupBeadMaterial(PersistableData.Instance.shopItemSprite[PersistableData.Instance.itemsData.currentShopItemId]); } private void SetupBeadMaterial(Sprite sprite) { if (sprite == null) { return; } if (beadMaterial == null) { beadMaterial = new Material(Shader.Find("Sprites/Default")); } beadMaterial.mainTexture = sprite.texture; beadMaterial.color = new Color(0f, 0f, 0f, 1f); meshRenderer.material = beadMaterial; Rect textureRect = sprite.textureRect; Texture2D texture = sprite.texture; uvBL = new Vector2(textureRect.x / (float)texture.width, textureRect.y / (float)texture.height); uvTR = new Vector2((textureRect.x + textureRect.width) / (float)texture.width, (textureRect.y + textureRect.height) / (float)texture.height); uvBR = new Vector2((textureRect.x + textureRect.width) / (float)texture.width, textureRect.y / (float)texture.height); uvTL = new Vector2(textureRect.x / (float)texture.width, (textureRect.y + textureRect.height) / (float)texture.height); if (_verts != null) { RefillUVArray(); } } private void RefillUVArray() { for (int i = 0; i < _arrayCapacity; i++) { _uvs[i * 4] = uvBL; _uvs[i * 4 + 1] = uvBR; _uvs[i * 4 + 2] = uvTR; _uvs[i * 4 + 3] = uvTL; } } public void UpdatePooledBeadSprite(Sprite newSprite) { SetupBeadMaterial(newSprite); } private void OnEnable() { GameManager.OnGameStarts += OnGameStarts; GameManager.OnLineDrawingComplete += IsLineDrawingComplete; } private void OnDisable() { GameManager.OnGameStarts -= OnGameStarts; GameManager.OnLineDrawingComplete -= IsLineDrawingComplete; } private void OnGameStarts() { linePhysicsMat = GameManager.Instance.lineDrawPhysics2dMat; IsGameStarted = true; } private void IsLineDrawingComplete() { IsLineDrawn = true; } private void Update() { if (!IsGameStarted) { return; } if (AppConstants.IsDialogueOpened) { return; } if (AppConstants.IsAnyPanelOpen) { return; } if (Input.touchCount > 0) { HandleTouchInput(); } else { HandleMouseInput(); } if (!hasMoved) { return; } if (myAudioSource == null) { return; } if (!AppConstants.isSound) { return; } if (isDrawing && Time.time - lastBeadTime < soundPauseDelay) { if (!myAudioSource.isPlaying) { myAudioSource.UnPause(); } } else if (myAudioSource.isPlaying) { myAudioSource.Pause(); } } private void HandleMouseInput() { if (Input.GetMouseButtonDown(0)) { touchDownScreenPos = Input.mousePosition; touchDownRecorded = true; return; } if (Input.GetMouseButton(0)) { if (IsLineDrawn) { return; } bool flag = IsMouseInsideDrawArea(); bool flag2 = isDrawing; if (flag) { if (!flag2) { Vector3 mousePosition = Input.mousePosition; float num = mousePosition.x - touchDownScreenPos.x; float num2 = mousePosition.y - touchDownScreenPos.y; if (Mathf.Sqrt(num * num + num2 * num2) < minMovePixels) { return; } StartDrawing(); } if (currentExitSide != ExitSide.None) { currentExitSide = ExitSide.None; } ContinueDrawing(); return; } if (!flag2) { return; } if (cantHitBorder) { StopDrawing(); return; } DetectExitSide(Input.mousePosition); ContinueDrawing(); return; } if (Input.GetMouseButtonUp(0)) { bool isLineDrawn = IsLineDrawn; touchDownRecorded = false; currentExitSide = ExitSide.None; if (isLineDrawn) { return; } if (!isDrawing) { return; } if (beadsSpawned >= 1) { if (GameManager.OnLineDrawingComplete != null) { GameManager.OnLineDrawingComplete(); } changeAction(); } StopDrawing(); } } private void HandleTouchInput() { if (Input.touchCount == 0) { return; } Touch touch = Input.GetTouch(0); TouchPhase phase = touch.phase; if (phase != TouchPhase.Ended && phase != TouchPhase.Canceled) { if (phase == TouchPhase.Moved) { if (IsLineDrawn) { return; } Vector2 position = touch.position; bool flag = IsTouchInsideDrawArea(position); bool flag2 = isDrawing; if (flag) { if (!flag2) { Vector2 vector = touch.position; float num = vector.x - touchDownScreenPos.x; float num2 = vector.y - touchDownScreenPos.y; if (Mathf.Sqrt(num * num + num2 * num2) < minMovePixels) { return; } StartDrawing(); } if (currentExitSide != ExitSide.None) { currentExitSide = ExitSide.None; } ContinueDrawing(); return; } if (!flag2) { return; } if (cantHitBorder) { StopDrawing(); return; } DetectExitSide(touch.position); ContinueDrawing(); return; } if (phase != TouchPhase.Began) { return; } touchDownScreenPos = touch.position; touchDownRecorded = true; return; } bool isLineDrawn = IsLineDrawn; touchDownRecorded = false; currentExitSide = ExitSide.None; if (isLineDrawn) { return; } if (!isDrawing) { return; } if (beadsSpawned >= 1) { if (GameManager.OnLineDrawingComplete != null) { GameManager.OnLineDrawingComplete(); } changeAction(); } StopDrawing(); } private bool IsMouseInsideDrawArea() { Vector3 mousePosition = Input.mousePosition; return drawArea.OverlapPoint(mainCamera.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, 10f))); } private bool IsTouchInsideDrawArea(Vector2 touchPosition) { return drawArea.OverlapPoint(mainCamera.ScreenToWorldPoint(new Vector3(touchPosition.x, touchPosition.y, 10f))); } private void StartDrawing() { previousPoint = GetInputWorldPoint(); _boundsMin = new Vector3(float.MaxValue, float.MaxValue, -1f); _boundsMax = new Vector3(-3.4028235E+38f, -3.4028235E+38f, 1f); _beadPosCount = 0; _quadCount = 0; drawMesh.Clear(); beadsSpawned = 0; hasMoved = false; _drawingBlocked = false; EyeBallTracker.IsDrawBlocked = false; if (drawBlockingLayers != 0) { Vector3 vector = mainCamera.ScreenToWorldPoint(new Vector3(touchDownScreenPos.x, touchDownScreenPos.y, 10f)); _externalDragStart = Physics2D.OverlapPoint(vector, drawBlockingLayers) != null; } else { _externalDragStart = false; } isDrawing = true; if (GameManager.OnLineDrawingStarts != null) { GameManager.OnLineDrawingStarts(); } if (GameManager.OnHintHideCalled != null) { GameManager.OnHintHideCalled(LevelScript.Instance.isWheelLevel); } if (CharacterAction.EnemyAction != null) { CharacterAction.EnemyAction(1); } EyeBallTracker.LookTarget = null; } private void changeAction() { if (CharacterAction.EnemyAction != null) { CharacterAction.EnemyAction(2); } if (isToolLevel && toolRigidbodies != null && toolRigidbodies.Length > 0 && toolRigidbodies[0] != null) { EyeBallTracker.LookTarget = toolRigidbodies[0].transform; } else { EyeBallTracker.LookTarget = null; } } private void ContinueDrawing() { Vector3 vector = GetEffectiveDrawPosition(); if (_externalDragStart) { bool flag = drawBlockingLayers != 0 && Physics2D.OverlapPoint(vector, drawBlockingLayers) != null; previousPoint = vector; if (flag) { return; } _externalDragStart = false; } if (drawBlockingLayers != 0 && (Physics2D.OverlapPoint(vector, drawBlockingLayers) != null || Physics2D.Linecast(previousPoint, vector, drawBlockingLayers).collider != null)) { _drawingBlocked = true; EyeBallTracker.IsDrawBlocked = true; EyeBallTracker.DrawBlockedLookPoint = previousPoint; return; } if (_drawingBlocked) { float num = vector.x - previousPoint.x; float num2 = vector.y - previousPoint.y; if (Mathf.Sqrt(num * num + num2 * num2) > constantDistance * 512f) { return; } if (Physics2D.Linecast(previousPoint, vector, drawBlockingLayers).collider != null) { return; } _drawingBlocked = false; EyeBallTracker.IsDrawBlocked = false; vector = previousPoint + (vector - previousPoint) * 0.25f; } Vector3 vector2 = vector - previousPoint; float num3 = vector2.x * vector2.x + vector2.y * vector2.y + vector2.z * vector2.z; if (num3 < _constantDistanceSq) { return; } int num4 = (int)(Mathf.Sqrt(num3) * _invConstantDistance) + 2; float num5 = ((num4 >= 2) ? (1f / (float)(num4 - 1)) : 0f); if (!hasMoved) { if (AppConstants.isSound) { myAudioSource.clip = SoundManager.instance.Drawing; myAudioSource.loop = true; myAudioSource.Play(); } hasMoved = true; } Vector3 p = previousPoint + vector2 * 0.1f; Vector3 p2 = vector - vector2 * 0.1f; for (int i = 0; i < num4; i++) { AddBeadToMesh(CubicBezierLerp(previousPoint, p, p2, vector, (float)i * num5)); beadsSpawned++; } ApplyMesh(); if (Time.time - lastVibrateTime >= vibrateInterval) { AppConstants.AndroidVibrate(10L); lastVibrateTime = Time.time; } previousPoint = vector; } private void GrowArrays() { int arrayCapacity = _arrayCapacity; int num = arrayCapacity * 2; Array.Resize(ref _verts, num * 4); Array.Resize(ref _uvs, num * 4); Array.Resize(ref _tris, num * 6); Array.Resize(ref _allBeadPosArr, num); for (int i = arrayCapacity; i < num; i++) { _tris[i * 6] = i * 4; _tris[i * 6 + 1] = i * 4 + 2; _tris[i * 6 + 2] = i * 4 + 1; _tris[i * 6 + 3] = i * 4; _tris[i * 6 + 4] = i * 4 + 3; _tris[i * 6 + 5] = i * 4 + 2; } for (int j = arrayCapacity * 4; j < num * 4; j += 4) { _uvs[j] = uvBL; _uvs[j + 1] = uvBR; _uvs[j + 2] = uvTR; _uvs[j + 3] = uvTL; } _arrayCapacity = num; } private void AddBeadToMesh(Vector3 pos) { if (_quadCount >= _arrayCapacity) { GrowArrays(); } _allBeadPosArr[_beadPosCount++] = pos; int num = _quadCount * 4; float x = pos.x; float y = pos.y; _verts[num] = new Vector3(x - beadHalfSize, y - beadHalfSize, pos.z); _verts[num + 1] = new Vector3(x + beadHalfSize, y - beadHalfSize, pos.z); _verts[num + 2] = new Vector3(x + beadHalfSize, y + beadHalfSize, pos.z); _verts[num + 3] = new Vector3(x - beadHalfSize, y + beadHalfSize, pos.z); if (x - beadHalfSize < _boundsMin.x) { _boundsMin.x = x - beadHalfSize; } if (y - beadHalfSize < _boundsMin.y) { _boundsMin.y = y - beadHalfSize; } if (x + beadHalfSize > _boundsMax.x) { _boundsMax.x = x + beadHalfSize; } if (y + beadHalfSize > _boundsMax.y) { _boundsMax.y = y + beadHalfSize; } _quadCount++; } private void ApplyMesh() { if (_quadCount == 0) { return; } drawMesh.Clear(); int num = _quadCount * 4; drawMesh.SetVertices(_verts, 0, num); drawMesh.SetUVs(0, _uvs, 0, num); drawMesh.SetTriangles(_tris, 0, _quadCount * 6, 0); drawMesh.bounds = new Bounds((_boundsMax + _boundsMin) * 0.5f, (_boundsMax - _boundsMin) * 0.5f); } public void SetLineStatic() { if (parentObject == null) { return; } Rigidbody2D component = parentObject.GetComponent(); if (component != null) { component.bodyType = RigidbodyType2D.Static; } if (toolRigidbodies == null) { return; } for (int i = 0; i < toolRigidbodies.Length; i++) { Rigidbody2D rigidbody2D = toolRigidbodies[i]; if (rigidbody2D != null) { rigidbody2D.bodyType = RigidbodyType2D.Static; } } } private void StopDrawing() { isDrawing = false; hasMoved = false; _drawingBlocked = false; _externalDragStart = false; EyeBallTracker.IsDrawBlocked = false; if (myAudioSource != null) { myAudioSource.loop = false; myAudioSource.Stop(); } if (_beadPosCount == 0) { return; } Vector2[] array = new Vector2[_beadPosCount]; Vector2 vector = Vector2.zero; for (int i = 0; i < _beadPosCount; i++) { array[i] = _allBeadPosArr[i]; vector += array[i]; } Vector3 position = parentObject.transform.position; Vector2 vector2 = array[0] - array[array.Length - 1]; float num = Mathf.Sqrt(vector2.x * vector2.x + vector2.y * vector2.y); bool flag = num < 0.6f; bool flag2 = LevelScript.Instance != null && LevelScript.Instance.isMovingPlatformLevel; bool flag3 = LevelScript.Instance != null && LevelScript.Instance.isWheelLevel; float num2 = (flag ? 0.08f : 0.15f); int num3 = ((flag3 || flag2) ? MAX_COLLIDER_POINTS : 30); Vector2[] array2 = SimplifyPoints(array, num2); while (num2 < 2f && num3 < array2.Length) { num2 *= 2f; array2 = SimplifyPoints(array, num2); } if (flag) { Vector2[] array3 = new Vector2[array2.Length + 1]; Array.Copy(array2, array3, array2.Length); array3[array3.Length - 1] = array2[0]; array2 = array3; } Debug.Log(string.Format("Original: {0} | Simplified: {1} | Closed: {2} | Tol: {3:F4} | MovingPlatform: {4}", _beadPosCount, array2.Length, flag, num2, flag2)); SetupChunkedColliders(array2); if (testMode) { return; } Rigidbody2D rigidbody2D = parentObject.GetComponent(); if (rigidbody2D != null) { rigidbody2D.interpolation = RigidbodyInterpolation2D.None; rigidbody2D.centerOfMass = new Vector2(vector.x / (float)_beadPosCount - position.x, vector.y / (float)_beadPosCount - position.y); rigidbody2D.collisionDetectionMode = CollisionDetectionMode2D.Continuous; rigidbody2D.bodyType = RigidbodyType2D.Dynamic; rigidbody2D.velocity = Vector2.zero; rigidbody2D.angularVelocity = 0f; StartCoroutine(RestoreInterpolation(rigidbody2D)); StartCoroutine(CheckLineStuck(rigidbody2D)); } } private IEnumerator RestoreInterpolation(Rigidbody2D rb) { yield return new WaitForFixedUpdate(); if (rb != null) { rb.interpolation = RigidbodyInterpolation2D.Interpolate; } } private IEnumerator CheckLineStuck(Rigidbody2D rb) { yield return new WaitForSeconds(1f); bool flag = LevelScript.Instance != null && LevelScript.Instance.isMovingPlatformLevel; float num = 0f; bool flag2 = isToolLevel && toolRigidbodies != null && toolRigidbodies.Length > 0; int num2 = (flag2 ? toolRigidbodies.Length : 0); float num3 = 0f; Vector2 vector = rb.position; Camera cam = Camera.main; float[] array = new float[num2]; Vector2[] array2 = new Vector2[num2]; float[] array3 = new float[num2]; for (int i = 0; i < num2; i++) { Rigidbody2D rigidbody2D = toolRigidbodies[i]; array2[i] = ((rigidbody2D != null) ? rigidbody2D.position : Vector2.zero); array3[i] = ((rigidbody2D != null) ? rigidbody2D.rotation : 0f); } float num4 = 0f; while (GameManager.Instance != null && !GameManager.Instance.IsGameEnded && rb != null) { num += 0.25f; if (flag && num >= movingPlatformTimeLimit) { goto LineStuckFail; } Vector2 position = rb.position; bool flag3 = false; if (cam != null) { Vector3 vector2 = cam.WorldToViewportPoint(position); flag3 = vector2.y > 1.5f || vector2.y < -0.5f || vector2.x < -0.5f || vector2.x > 1.5f; } if (flag3) { num4 += 0.25f; } else { num4 = 0f; } if (cam != null && !flag3 && flag2) { for (int j = 0; j < num2; j++) { Rigidbody2D rigidbody2D2 = toolRigidbodies[j]; if (rigidbody2D2 == null) { continue; } Vector3 vector3 = cam.WorldToViewportPoint(rigidbody2D2.position); if (vector3.y > 1.5f || vector3.y < -0.5f || vector3.x < -0.5f || vector3.x > 1.5f) { array[j] += 0.25f; } else { array[j] = 0f; } if (array[j] >= 0.5f && (num4 >= 0.5f || (position - vector).magnitude < LinemovedThreshold)) { goto LineStuckFail; } } } if (flag3 && !flag2 && num4 >= 0.5f) { goto LineStuckFail; } if (num4 >= 0.5f && num2 > 0) { for (int k = 0; k < num2; k++) { Rigidbody2D rigidbody2D3 = toolRigidbodies[k]; if (rigidbody2D3 == null) { continue; } Vector2 position2 = rigidbody2D3.position; float rotation = rigidbody2D3.rotation; float num5 = Mathf.DeltaAngle(rotation, array3[k]); if ((position2 - array2[k]).magnitude < LinemovedThreshold && Mathf.Abs(num5) < 0.2f) { goto LineStuckFail; } } } Vector2 vector4 = vector; vector = position; float linemovedThreshold = LinemovedThreshold; bool flag4 = true; if (flag2 && num2 > 0) { for (int l = 0; l < num2; l++) { Rigidbody2D rigidbody2D4 = toolRigidbodies[l]; if (rigidbody2D4 == null) { continue; } Vector2 vector5 = rigidbody2D4.position; Vector2 vector6 = array2[l]; float rotation2 = rigidbody2D4.rotation; float num6 = Mathf.DeltaAngle(rotation2, array3[l]); array2[l] = vector5; array3[l] = rotation2; if (Mathf.Abs(num6) >= 0.2f || (vector5 - vector6).magnitude >= linemovedThreshold) { flag4 = false; break; } } } if (flag4 && (position - vector4).magnitude < linemovedThreshold) { num3 += 0.25f; if (!flag && num3 >= 0.5f) { goto LineStuckFail; } } else { num3 = 0f; } yield return new WaitForSeconds(0.25f); } yield break; LineStuckFail: if (!GameManager.Instance.IsGameEnded && GameManager.EnemyList.Count >= 1) { GameManager.Instance.CheckLevelFailed(); } yield break; } private Vector3 CubicBezierLerp(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) { float num = 1f - t; float num2 = num * num; float num3 = num2 * num; float num4 = t * t; float num5 = num4 * t; return num3 * p0 + 3f * num2 * t * p1 + 3f * num * num4 * p2 + num5 * p3; } private Vector2[] SimplifyPoints(Vector2[] points, float tolerance) { if (points.Length < 3) { return points; } List list = new List(); RDP(points, 0, points.Length - 1, tolerance * tolerance, list); list.Add(points[points.Length - 1]); return list.ToArray(); } private void RDP(Vector2[] pts, int s, int e, float tolSq, List result) { if (s + 1 < e) { float num = 0f; int num2 = s; for (int i = s + 1; i < e; i++) { float num3 = PerpendicularDistanceSq(pts[i], pts[s], pts[e]); if (num3 > num) { num2 = i; num = num3; } } if (num > tolSq) { RDP(pts, s, num2, tolSq, result); RDP(pts, num2, e, tolSq, result); return; } } result.Add(pts[s]); } private void SetupChunkedColliders(Vector2[] points) { int num = points.Length; int num2 = Mathf.CeilToInt((float)(num - 1) / 60f); while (_colliderPool.Count < num2) { EdgeCollider2D edgeCollider2D = parentObject.AddComponent(); edgeCollider2D.enabled = false; _colliderPool.Add(edgeCollider2D); } if (num2 < _activeChunks) { for (int i = num2; i < _activeChunks; i++) { _colliderPool[i].enabled = false; } } _activeChunks = num2; for (int j = 0; j < num2; j++) { int num3 = j * 59; int num4 = Mathf.Min(num3 + 60, points.Length) - num3; Vector2[] array = new Vector2[num4]; Array.Copy(points, num3, array, 0, num4); EdgeCollider2D edgeCollider2D2 = _colliderPool[j]; edgeCollider2D2.sharedMaterial = linePhysicsMat; edgeCollider2D2.points = array; edgeCollider2D2.enabled = true; } } private float PerpendicularDistanceSq(Vector2 point, Vector2 lineStart, Vector2 lineEnd) { Vector2 vector = lineEnd - lineStart; float num = vector.x * vector.x + vector.y * vector.y; float num2 = point.x - lineStart.x; float num3 = point.y - lineStart.y; if (num == 0f) { return num2 * num2 + num3 * num3; } float num4 = Mathf.Clamp01((num2 * vector.x + num3 * vector.y) / num); Vector2 vector2 = lineStart + vector * num4; float num5 = point.x - vector2.x; float num6 = point.y - vector2.y; return num5 * num5 + num6 * num6; } private Vector3 GetEffectiveDrawPosition() { Vector3 result = GetInputWorldPoint(); if (currentExitSide != ExitSide.None) { Bounds bounds = drawArea.bounds; Vector3 center = bounds.center; Vector3 extents = bounds.extents; float num = center.x + extents.x; float num2 = center.x - extents.x; float num3 = center.y + extents.y; float num4 = center.y - extents.y; if (currentExitSide == ExitSide.Left || currentExitSide == ExitSide.Right) { result.x = exitLockValue; result.y = Mathf.Clamp(result.y, num4, num3); } else if (currentExitSide == ExitSide.Top || currentExitSide == ExitSide.Bottom) { result.x = Mathf.Clamp(result.x, num2, num); result.y = exitLockValue; } } return result; } private void DetectExitSide(Vector2 screenPos) { Vector3 vector = mainCamera.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, 10f)); Bounds bounds = drawArea.bounds; Vector3 center = bounds.center; Vector3 extents = bounds.extents; float num = center.x + extents.x; float num2 = center.x - extents.x; float num3 = center.y + extents.y; float num4 = center.y - extents.y; float x = vector.x; float y = vector.y; ExitSide exitSide; float num5; if (x <= num && x >= num2 && y < num4) { exitSide = ExitSide.Bottom; num5 = num4; } else if (x <= num && x >= num2 && y > num3) { exitSide = ExitSide.Top; num5 = num3; } else if (y <= num3 && y >= num4 && x < num2) { exitSide = ExitSide.Left; num5 = num2; } else if (y <= num3 && y >= num4 && x > num) { exitSide = ExitSide.Right; num5 = num; } else { float num6 = num2 - x; float num7 = x - num; float num8 = num4 - y; float num9 = y - num3; float[] array = new float[4]; array[0] = ((x < num2) ? num6 : float.MaxValue); array[1] = ((x > num) ? num7 : float.MaxValue); array[2] = ((y < num4) ? num8 : float.MaxValue); array[3] = ((y > num3) ? num9 : float.MaxValue); float num10 = Mathf.Min(array); if (y < num4 && Mathf.Approximately(num10, num8)) { exitSide = ExitSide.Bottom; num5 = num4; } else if (y > num3 && Mathf.Approximately(num10, num9)) { exitSide = ExitSide.Top; num5 = num3; } else if (x < num2 && Mathf.Approximately(num10, num6)) { exitSide = ExitSide.Left; num5 = num2; } else { exitSide = ExitSide.Right; num5 = num; } } if (currentExitSide != exitSide) { currentExitSide = exitSide; exitLockValue = num5; } } private Vector3 GetInputWorldPoint() { Vector2 screenPos = Input.touchCount > 0 ? Input.GetTouch(0).position : new Vector2(Input.mousePosition.x, Input.mousePosition.y); return mainCamera.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, 10f)); } }