Files
eggs/BeadDrawer.cs
2026-09-22 10:29:55 +00:00

1114 lines
27 KiB
C#

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<EdgeCollider2D> _colliderPool = new List<EdgeCollider2D>();
private int _activeChunks;
public float LinemovedThreshold = 0.1f;
public int DrawnBeadCount => _beadPosCount;
public Rigidbody2D LineRigidbody => (parentObject != null) ? parentObject.GetComponent<Rigidbody2D>() : 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<EdgeCollider2D>();
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<MeshFilter>();
meshRenderer = gameObject.AddComponent<MeshRenderer>();
_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<SpriteRenderer>();
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<Rigidbody2D>();
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<Rigidbody2D>();
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<Vector2> list = new List<Vector2>();
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<Vector2> 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>();
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));
}
}