Paper.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using JTFold;
  6. using JTFold;
  7. using UnityEngine;
  8. using JTSystems;
  9. public class Paper : MonoBehaviour
  10. {
  11. [HideInInspector] public PossibleCombinationBuilder Builder;
  12. [HideInInspector] public RegexCombinationAnalyzer RegexAnalyzer;
  13. public delegate void OnPaperStateChanged();
  14. public OnPaperStateChanged onPaperStateChanged;
  15. public delegate void OnPaperEvolving();
  16. public OnPaperEvolving onPaperEvolving;
  17. public delegate void OnPaperShowEffect();
  18. public OnPaperShowEffect onPaperShowEffect;
  19. public delegate void PaperStartFold();
  20. public PaperStartFold paperStartFold;
  21. public delegate void PaperStartUnfold();
  22. public PaperStartUnfold paperStartUnfold;
  23. [Header(" Settings ")]
  24. [SerializeField] private bool _test;
  25. [SerializeField] private bool _decalPaper;
  26. public Transform foldingsParent;
  27. private readonly List<Folding> _foldedFolding = new List<Folding>();
  28. private Folding[] _folding;
  29. private bool _canFold = true;
  30. [SerializeField] private Texture2D paperTexture;
  31. [SerializeField] private PaperEffect effect;
  32. [Header(" Rendering ")]
  33. [SerializeField] private MeshRenderer paperBackRenderer;
  34. [SerializeField] private MeshRenderer paperFrontRenderer;
  35. Folding currentFolding;
  36. [Header(" Mesh Manipulation ")] MeshFilter backFilter;
  37. private MeshFilter _frontFilter;
  38. [SerializeField] private float verticesElevationStep;
  39. [SerializeField] private float foldingDuration;
  40. [Header(" Solution ")]
  41. public PossibleCombination[] possibleCombinations;
  42. public IEnumerable<Folding> Folding => foldingsParent.Cast<Transform>().Select(x => x.GetComponent<Folding>());
  43. private Action levelCompleteCallBack;
  44. public Action wrongPaperFolded;
  45. private void Awake()
  46. {
  47. backFilter = paperBackRenderer.GetComponent<MeshFilter>();
  48. _frontFilter = paperFrontRenderer.GetComponent<MeshFilter>();
  49. // Анимация появления
  50. float toPositionZ = transform.position.z;
  51. Vector3 startPosition = transform.position;
  52. startPosition.z = 10;
  53. transform.position = startPosition;
  54. LoadingState.IsLoading = true;
  55. transform.LeanMoveZ(toPositionZ, 1f)
  56. .setOnComplete(() => LoadingState.IsLoading = false);
  57. }
  58. public void setPaperCallBack(Action levelCompleteCallBackTemp, Action wrongPaperFoldedTemp)
  59. {
  60. levelCompleteCallBack = levelCompleteCallBackTemp;
  61. wrongPaperFolded = wrongPaperFoldedTemp;
  62. }
  63. // Start is called before the first frame update
  64. void Start()
  65. {
  66. #if UNITY_EDITOR
  67. if(!FindObjectOfType<DecalMaster>())
  68. #endif
  69. paperFrontRenderer.material.mainTexture = paperTexture;
  70. _folding = GetFoldings();
  71. }
  72. public void TryFold(Folding tappedFolding)
  73. {
  74. if (!_canFold) return;
  75. _canFold = false;
  76. currentFolding = tappedFolding;
  77. if (!tappedFolding.IsFolded())
  78. {
  79. _foldedFolding.Add(currentFolding);
  80. Fold();
  81. }
  82. else
  83. {
  84. // It is folded, unfold it
  85. StartCoroutine(UnfoldingProcedureCoroutine());
  86. }
  87. }
  88. private void Fold()
  89. {
  90. // We need to get the vertices that need to be folded first
  91. // These are the ones inside the folding's tapping zone
  92. StartCoroutine(FoldCoroutine(true));
  93. //StartCoroutine("FoldingCoroutine");
  94. currentFolding.SetFoldedState(true);
  95. Taptic.Light();
  96. onPaperEvolving?.Invoke();
  97. }
  98. private int[] GetVerticesToMove(MeshFilter filter, Folding folding)
  99. {
  100. List<int> verticesInsideTappingZone = new List<int>();
  101. Vector3[] vertices = filter.mesh.vertices;
  102. Plane foldingPlane = folding.GetFoldingPlane();
  103. for (int i = 0; i < vertices.Length; i++)
  104. {
  105. Vector3 vertexWorldPos = filter.transform.TransformPoint(vertices[i]);
  106. if (foldingPlane.GetSide(vertexWorldPos))
  107. verticesInsideTappingZone.Add(i);
  108. }
  109. return verticesInsideTappingZone.ToArray();
  110. }
  111. private bool IsInsideTappingZone(Vector3 vertexLocalPos, BoxCollider tappingZone)
  112. {
  113. Vector3 vertexWorldPos = paperBackRenderer.transform.position + vertexLocalPos;
  114. return tappingZone.bounds.Contains(vertexWorldPos);
  115. }
  116. private Vector3 GetRotatedPoint(Vector3 point, float angle, RotationAxis rotationAxis)
  117. {
  118. Vector3 pivot = rotationAxis.position;
  119. Quaternion q = Quaternion.AngleAxis(angle, rotationAxis.AsVector());
  120. return q * (point - pivot) + pivot;
  121. }
  122. private void Unfold()
  123. {
  124. StartCoroutine(FoldCoroutine(false));
  125. currentFolding.SetFoldedState(false);
  126. currentFolding.ClearFoldedVertices();
  127. }
  128. public void StartUnfolding()
  129. {
  130. if (!_canFold) return;
  131. _canFold = false;
  132. StartCoroutine(UnfoldingProcedureCoroutine());
  133. }
  134. IEnumerator UnfoldingProcedureCoroutine()
  135. {
  136. // 1. Check if there is any folding before this one
  137. for (int i = _foldedFolding.Count - 1; i >= 0; i--)
  138. {
  139. Folding folding = _foldedFolding[i];
  140. if (folding == currentFolding)
  141. {
  142. //Unfold();
  143. Taptic.Light();
  144. onPaperEvolving?.Invoke();
  145. yield return StartCoroutine(FoldCoroutine(false));
  146. currentFolding.SetFoldedState(false);
  147. currentFolding.ClearFoldedVertices();
  148. _foldedFolding.Remove(currentFolding);
  149. break;
  150. }
  151. else
  152. {
  153. currentFolding = folding;
  154. Taptic.Light();
  155. onPaperEvolving?.Invoke();
  156. yield return StartCoroutine(FoldCoroutine(false));
  157. currentFolding.SetFoldedState(false);
  158. currentFolding.ClearFoldedVertices();
  159. _foldedFolding.Remove(currentFolding);
  160. }
  161. }
  162. _canFold = true;
  163. onPaperStateChanged?.Invoke();
  164. yield return null;
  165. }
  166. IEnumerator FoldCoroutine(bool folding)
  167. {
  168. if (folding)
  169. paperStartFold?.Invoke();
  170. else
  171. paperStartUnfold?.Invoke();
  172. int[] backVerticesToMove = folding
  173. ? GetVerticesToMove(backFilter, currentFolding)
  174. : currentFolding.GetBackFoldedVerticesIndices();
  175. int[] frontVerticesToMove = folding
  176. ? GetVerticesToMove(_frontFilter, currentFolding)
  177. : currentFolding.GetFrontFoldedVerticesIndices();
  178. if (folding)
  179. {
  180. currentFolding.SetBackFoldedVerticesIndices(backVerticesToMove);
  181. currentFolding.SetFrontFoldedVerticesIndices(frontVerticesToMove);
  182. }
  183. Vector3[] initialBackVertices = backFilter.mesh.vertices;
  184. Vector3[] backVertices = backFilter.mesh.vertices;
  185. Vector3[] initialFrontVertices = _frontFilter.mesh.vertices;
  186. Vector3[] frontVertices = _frontFilter.mesh.vertices;
  187. if (folding)
  188. {
  189. for (int i = 0; i < frontVerticesToMove.Length; i++)
  190. initialFrontVertices[frontVerticesToMove[i]].y -= verticesElevationStep * (1 + _foldedFolding.Count);
  191. }
  192. float angleMultiplier = folding ? 1 : -1;
  193. float targetAngle = currentFolding.GetRotationAngle() * angleMultiplier;
  194. float timer = 0;
  195. while (timer <= foldingDuration + Time.deltaTime)
  196. {
  197. float angle = Mathf.Clamp01((timer / foldingDuration)) * targetAngle;
  198. for (int i = 0; i < backVerticesToMove.Length; i++)
  199. backVertices[backVerticesToMove[i]] =
  200. GetRotatedLocalVertex(initialBackVertices[backVerticesToMove[i]], angle);
  201. for (int i = 0; i < frontVerticesToMove.Length; i++)
  202. frontVertices[frontVerticesToMove[i]] =
  203. GetRotatedLocalVertex(initialFrontVertices[frontVerticesToMove[i]], angle);
  204. if (!folding)
  205. {
  206. for (int i = 0; i < frontVerticesToMove.Length; i++)
  207. frontVertices[frontVerticesToMove[i]].y += verticesElevationStep * (1 + _foldedFolding.Count);
  208. }
  209. backFilter.mesh.vertices = backVertices;
  210. _frontFilter.mesh.vertices = frontVertices;
  211. timer += Time.deltaTime;
  212. yield return null;
  213. }
  214. for (int i = 0; i < backVerticesToMove.Length; i++)
  215. backVertices[backVerticesToMove[i]] =
  216. GetRotatedLocalVertex(initialBackVertices[backVerticesToMove[i]], targetAngle);
  217. for (int i = 0; i < frontVerticesToMove.Length; i++)
  218. frontVertices[frontVerticesToMove[i]] =
  219. GetRotatedLocalVertex(initialFrontVertices[frontVerticesToMove[i]], targetAngle);
  220. if (!folding)
  221. {
  222. for (int i = 0; i < frontVerticesToMove.Length; i++)
  223. frontVertices[frontVerticesToMove[i]].y += verticesElevationStep * (1 + _foldedFolding.Count);
  224. }
  225. backFilter.mesh.vertices = backVertices;
  226. _frontFilter.mesh.vertices = frontVertices;
  227. _frontFilter.GetComponent<MeshCollider>().sharedMesh = _frontFilter.mesh;
  228. if (folding)
  229. _canFold = true;
  230. if (AvailableFoldingsEnded() && folding)
  231. {
  232. yield return new WaitForSeconds(0.1f);
  233. CheckForLevelComplete();
  234. }
  235. onPaperStateChanged?.Invoke();
  236. }
  237. private void CheckForLevelComplete()
  238. {
  239. if (Builder != null && Builder.Used && Builder.IsCorrect(_foldedFolding))
  240. {
  241. StartCoroutine(SetLevelComplete());
  242. return;
  243. }
  244. if (RegexAnalyzer != null && RegexAnalyzer.IsCorrect(_foldedFolding))
  245. {
  246. StartCoroutine(SetLevelComplete());
  247. return;
  248. }
  249. for (int i = 0; i < possibleCombinations.Length; i++)
  250. {
  251. if (MatchPossibleCombination(possibleCombinations[i]))
  252. {
  253. StartCoroutine(SetLevelComplete());
  254. return;
  255. }
  256. }
  257. StartCoroutine(SetWrongFoldPaper());
  258. }
  259. private bool MatchPossibleCombination(PossibleCombination foldingsCombination)
  260. {
  261. if (_foldedFolding.Count != foldingsCombination.GetFoldings().Length)
  262. return false;
  263. for (int i = 0; i < _foldedFolding.Count; i++)
  264. if (_foldedFolding[i] != foldingsCombination.GetFoldings()[i])
  265. return false;
  266. return true;
  267. }
  268. private IEnumerator SetLevelComplete()
  269. {
  270. Debug.Log("Level Complete");
  271. if (_decalPaper || _test)
  272. yield break;
  273. _canFold = false;
  274. LeanTween.moveZ(gameObject, -20f, 0.7f).setEaseInBack().setOnComplete(() => { });
  275. if (effect.StickerEffect != null)
  276. {
  277. StickerEffect stickerEffect = Instantiate(effect.StickerEffect);
  278. stickerEffect.CachedTransform.position = transform.position;
  279. stickerEffect.CachedSpriteRenderer.flipX = effect.FlipX;
  280. stickerEffect.CachedSpriteRenderer.flipY = effect.FlipY;
  281. onPaperShowEffect?.Invoke();
  282. yield return stickerEffect.ShowEffect(effect.SpriteImage, effect.SpriteSize, effect.SpriteRotate);
  283. yield return new WaitForSeconds(0.5f);
  284. Destroy(stickerEffect.gameObject);
  285. }
  286. UIManager.setLevelCompleteDelegate?.Invoke();
  287. levelCompleteCallBack?.Invoke();
  288. yield break;
  289. }
  290. private IEnumerator SetWrongFoldPaper()
  291. {
  292. bool animationComplete = false;
  293. Debug.Log("Wrong!");
  294. LeanTween.moveLocalX(gameObject, transform.position.x + 0.1f, 0.1f).setEaseShake().setOnComplete(() =>
  295. {
  296. LeanTween.moveLocalX(gameObject, transform.position.x - 0.1f, 0.1f).setEaseShake()
  297. .setOnComplete(() => { animationComplete = true; });
  298. });
  299. yield return new WaitUntil(() => animationComplete);
  300. animationComplete = false;
  301. if (_decalPaper || _test)
  302. yield break;
  303. UnfoldAllFoldings();
  304. UIManager.wrongPaperFolded?.Invoke();
  305. wrongPaperFolded?.Invoke();
  306. yield break;
  307. }
  308. private Vector3 GetRotatedLocalVertex(Vector3 localVertexToMove, float angle)
  309. {
  310. Vector3 vertexWorldPos = paperBackRenderer.transform.TransformPoint(localVertexToMove);
  311. Vector3 rotatedWorldVertex = GetRotatedPoint(vertexWorldPos, angle, currentFolding.GetRotationAxis());
  312. Vector3 rotatedLocalVertex = paperBackRenderer.transform.InverseTransformPoint(rotatedWorldVertex);
  313. return rotatedLocalVertex;
  314. }
  315. public Folding[] GetFoldings(bool includeInactive = true)
  316. {
  317. return foldingsParent.GetComponentsInChildren<Folding>(includeInactive);
  318. }
  319. public MeshRenderer GetFrontRenderer()
  320. {
  321. return paperFrontRenderer;
  322. }
  323. public bool AvailableFoldingsEnded()
  324. {
  325. return _foldedFolding.Count >= _folding.Length;
  326. }
  327. public void UnfoldAllFoldings()
  328. {
  329. if (_foldedFolding.Count <= 0 || !_canFold)
  330. return;
  331. currentFolding = _foldedFolding[0];
  332. _canFold = false;
  333. StartCoroutine(UnfoldingProcedureCoroutine());
  334. }
  335. private void OnDisable()
  336. {
  337. levelCompleteCallBack = null;
  338. }
  339. }
  340. [System.Serializable]
  341. public struct PossibleCombination
  342. {
  343. [SerializeField] private Folding[] foldings;
  344. public Folding[] GetFoldings()
  345. {
  346. return foldings;
  347. }
  348. }
  349. [System.Serializable]
  350. public struct PaperEffect
  351. {
  352. [SerializeField] private StickerEffect _stickerEffect;
  353. [SerializeField] private Sprite _spriteImage;
  354. [SerializeField] private Vector3 _spriteSize;
  355. [SerializeField] private Quaternion _spriteRotate;
  356. [SerializeField] private bool _flipX;
  357. [SerializeField] private bool _flipY;
  358. public StickerEffect StickerEffect => _stickerEffect;
  359. public Sprite SpriteImage => _spriteImage;
  360. public Vector3 SpriteSize => _spriteSize;
  361. public Quaternion SpriteRotate => _spriteRotate;
  362. public bool FlipX => _flipX;
  363. public bool FlipY => _flipY;
  364. }