DecalMaster.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. #if UNITY_EDITOR
  5. public class DecalMaster : MonoBehaviour
  6. {
  7. [Header("General")]
  8. [SerializeField] private DecalObject[] _decalObjects;
  9. [Header("Single Paper Mode Settings")]
  10. [SerializeField] private MeshRenderer decalRenderer;
  11. [SerializeField] private MeshRenderer targetObjectRenderer;
  12. [SerializeField] private Transform papersParent;
  13. [SerializeField] private Texture2D[] coloredPapers;
  14. private Texture2D newTargetObjectTexture;
  15. private bool projectingActive;
  16. private Coroutine currentProjectingCoroutine = null;
  17. public bool ProjectingActive => projectingActive;
  18. private IEnumerator ProjectPapersCoroutine()
  19. {
  20. if (_decalObjects == null || _decalObjects.Length < 0)
  21. {
  22. Debug.LogWarning("Not found decal objects!");
  23. yield break;
  24. }
  25. for(int i = 0; i < _decalObjects.Length; i++)
  26. {
  27. if (_decalObjects[i].gameObject.activeInHierarchy)
  28. _decalObjects[i].gameObject.SetActive(false);
  29. }
  30. projectingActive = true;
  31. for (int i = 0; i < _decalObjects.Length; i++)
  32. {
  33. _decalObjects[i].gameObject.SetActive(true);
  34. yield return currentProjectingCoroutine = StartCoroutine(_decalObjects[i].Project());
  35. _decalObjects[i].gameObject.SetActive(false);
  36. Debug.LogWarning($"Finished Printing");
  37. yield return null;
  38. }
  39. projectingActive = false;
  40. yield break;
  41. }
  42. private IEnumerator ProjectSinglePaperCoroutine()
  43. {
  44. projectingActive = true;
  45. yield return currentProjectingCoroutine = StartCoroutine(Project());
  46. projectingActive = false;
  47. }
  48. private IEnumerator Project()
  49. {
  50. // Texture2D decalTexture = decalRenderer.sprite.texture;
  51. Texture2D decalTexture = (Texture2D)decalRenderer.sharedMaterial.mainTexture;
  52. newTargetObjectTexture = new Texture2D(targetObjectRenderer.material.mainTexture.width, targetObjectRenderer.material.mainTexture.height, TextureFormat.RGBA32, false);
  53. Graphics.CopyTexture(targetObjectRenderer.material.mainTexture, newTargetObjectTexture);
  54. targetObjectRenderer.material.mainTexture = newTargetObjectTexture;
  55. int width = decalTexture.width;
  56. int height = decalTexture.height;
  57. for (int x = 0; x < width; x++)
  58. {
  59. for (int y = 0; y < height; y++)
  60. {
  61. if (decalTexture.GetPixel(x, y).a <= 0.1f)
  62. {
  63. continue;
  64. }
  65. ProjectPixel(x, y, decalTexture);
  66. }
  67. Debug.Log("Pixel printed");
  68. yield return null;
  69. }
  70. newTargetObjectTexture.Apply();
  71. SaveTexture();
  72. yield return new WaitForSeconds(10f);
  73. yield return null;
  74. yield break;
  75. }
  76. private void ProjectPixel(int x, int y, Texture2D decalTexture)
  77. {
  78. RaycastHit hit;
  79. Vector3 rayOrigin = GetRayOrigin(x, y, decalTexture);
  80. Vector3 rayDirection = decalRenderer.transform.forward;
  81. Ray ray = new Ray(rayOrigin, rayDirection);
  82. if (!Physics.Raycast(ray, out hit))
  83. return;
  84. Renderer rend = hit.transform.GetComponent<Renderer>();
  85. MeshCollider meshCollider = hit.collider as MeshCollider;
  86. if (rend == null || rend.sharedMaterial == null || rend.sharedMaterial.mainTexture == null || meshCollider == null)
  87. return;
  88. if (rend != targetObjectRenderer)
  89. return;
  90. Texture2D tex = rend.material.mainTexture as Texture2D;
  91. Vector2 pixelUV = hit.textureCoord;
  92. pixelUV.x *= tex.width;
  93. pixelUV.y *= tex.height;
  94. tex.SetPixel((int)pixelUV.x, (int)pixelUV.y, decalTexture.GetPixel(x, y));
  95. tex.Apply();
  96. }
  97. private Vector3 GetRayOrigin(int x, int y, Texture2D decalTexture)
  98. {
  99. float rightPercent = (float)x / decalTexture.width;
  100. float upPercent = (float)y / decalTexture.height;
  101. Vector3 startPosition = decalRenderer.transform.position;
  102. startPosition += decalRenderer.transform.right * (rightPercent - 0.5f) * decalRenderer.transform.localScale.x;
  103. startPosition += decalRenderer.transform.up * (upPercent - 0.5f) * decalRenderer.transform.localScale.y;
  104. return startPosition;
  105. }
  106. private void SaveTexture()
  107. {
  108. JTSystems.Utils.SaveTexture(newTargetObjectTexture, "/DecalToTexture/Fish/");
  109. }
  110. private void ConfigureChild(int paperIndex)
  111. {
  112. Paper currentPaper = papersParent.GetChild(paperIndex).GetComponent<Paper>();
  113. targetObjectRenderer = currentPaper.GetFrontRenderer();
  114. currentPaper.GetFrontRenderer().sharedMaterial.mainTexture = GetRandomColoredPaper();
  115. }
  116. private Texture2D GetRandomColoredPaper()
  117. {
  118. return coloredPapers[Random.Range(0, coloredPapers.Length)];
  119. }
  120. public void EnableNextPaper()
  121. {
  122. int currentActivePaperIndex = 0;
  123. for (int i = 0; i < papersParent.childCount; i++)
  124. {
  125. if (papersParent.GetChild(i).gameObject.activeSelf)
  126. {
  127. currentActivePaperIndex = i;
  128. break;
  129. }
  130. }
  131. currentActivePaperIndex++;
  132. if (currentActivePaperIndex >= papersParent.childCount)
  133. currentActivePaperIndex = 0;
  134. for (int i = 0; i < papersParent.childCount; i++)
  135. {
  136. if (i == currentActivePaperIndex)
  137. papersParent.GetChild(i).gameObject.SetActive(true);
  138. else
  139. papersParent.GetChild(i).gameObject.SetActive(false);
  140. }
  141. ConfigureChild(currentActivePaperIndex);
  142. }
  143. public void ProjectSinglePaper()
  144. {
  145. currentProjectingCoroutine = StartCoroutine(ProjectSinglePaperCoroutine());
  146. }
  147. public void ProjectAllPapers()
  148. {
  149. currentProjectingCoroutine = StartCoroutine(ProjectPapersCoroutine());
  150. }
  151. public void StopCurrentProjecting()
  152. {
  153. StopAllCoroutines();
  154. currentProjectingCoroutine = null;
  155. projectingActive = false;
  156. }
  157. }
  158. #endif