PageRenderTime 146ms CodeModel.GetById 39ms RepoModel.GetById 1ms app.codeStats 0ms

/ProgTestExport/Export/Assets/Scripts/Editor/CustomUtilities/BakeTexture.cs

https://gitlab.com/Legato/SpaceShooter
C# | 253 lines | 237 code | 14 blank | 2 comment | 81 complexity | a4bffff8b3d046a0d12a00d60ee345e6 MD5 | raw file
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. namespace JBooth.VertexPainterPro
  6. {
  7. public class BakeTexture : IVertexPainterUtility
  8. {
  9. public string GetName()
  10. {
  11. return "Texture Baker";
  12. }
  13. public void OnGUI(PaintJob[] jobs)
  14. {
  15. bakingTex = EditorGUILayout.ObjectField("Texture", bakingTex, typeof(Texture2D), false) as Texture2D;
  16. bakeSourceUV = (BakeSourceUV)EditorGUILayout.EnumPopup("Source UVs", bakeSourceUV);
  17. bakeChannel = (BakeChannel)EditorGUILayout.EnumPopup("Bake To", bakeChannel);
  18. if (bakeSourceUV == BakeSourceUV.WorldSpaceXY || bakeSourceUV == BakeSourceUV.WorldSpaceXZ || bakeSourceUV == BakeSourceUV.WorldSpaceYZ)
  19. {
  20. worldSpaceLower = EditorGUILayout.Vector2Field("Lower world position", worldSpaceLower);
  21. worldSpaceUpper = EditorGUILayout.Vector2Field("Upper world position", worldSpaceUpper);
  22. }
  23. EditorGUILayout.BeginHorizontal();
  24. EditorGUILayout.Space();
  25. if (GUILayout.Button("Bake"))
  26. {
  27. if (bakingTex != null)
  28. {
  29. BakeFromTexture(jobs);
  30. }
  31. else
  32. {
  33. EditorUtility.DisplayDialog("Error", "Baking texture is not set", "ok");
  34. }
  35. }
  36. EditorGUILayout.Space();
  37. EditorGUILayout.EndHorizontal();
  38. }
  39. public enum BakeChannel
  40. {
  41. None,
  42. Color,
  43. UV0,
  44. UV1,
  45. UV2,
  46. UV3
  47. }
  48. public enum BakeSourceUV
  49. {
  50. UV0,
  51. UV1,
  52. UV2,
  53. UV3,
  54. WorldSpaceXY,
  55. WorldSpaceXZ,
  56. WorldSpaceYZ
  57. }
  58. Texture2D bakingTex = null;
  59. BakeSourceUV bakeSourceUV = BakeSourceUV.UV0;
  60. BakeChannel bakeChannel = BakeChannel.Color;
  61. Vector2 worldSpaceLower = new Vector2(0, 0);
  62. Vector2 worldSpaceUpper = new Vector2(1, 1);
  63. void InitBakeChannel(BakeChannel bc, PaintJob[] jobs)
  64. {
  65. foreach (PaintJob job in jobs)
  66. {
  67. if (bc == BakeChannel.Color)
  68. {
  69. if (job.stream.colors == null || job.stream.colors.Length != job.verts.Length)
  70. {
  71. job.stream.SetColor(Color.black, job.verts.Length);
  72. }
  73. }
  74. else if (bc == BakeChannel.UV0)
  75. {
  76. if (job.stream.uv0 == null || job.stream.uv0.Count!= job.verts.Length)
  77. {
  78. job.stream.SetUV0(Vector4.zero, job.verts.Length);
  79. }
  80. }
  81. else if (bc == BakeChannel.UV1)
  82. {
  83. if (job.stream.uv1 == null || job.stream.uv1.Count != job.verts.Length)
  84. {
  85. job.stream.SetUV1(Vector4.zero, job.verts.Length);
  86. }
  87. }
  88. else if (bc == BakeChannel.UV2)
  89. {
  90. if (job.stream.uv2 == null || job.stream.uv2.Count != job.verts.Length)
  91. {
  92. job.stream.SetUV2(Vector4.zero, job.verts.Length);
  93. }
  94. }
  95. else if (bc == BakeChannel.UV3)
  96. {
  97. if (job.stream.uv3 == null || job.stream.uv3.Count != job.verts.Length)
  98. {
  99. job.stream.SetUV3(Vector4.zero, job.verts.Length);
  100. }
  101. }
  102. EditorUtility.SetDirty(job.stream);
  103. EditorUtility.SetDirty(job.stream.gameObject);
  104. }
  105. }
  106. void BakeColor(PaintJob job, BakeChannel bc, Vector4 val, int i)
  107. {
  108. switch (bc)
  109. {
  110. case BakeChannel.Color:
  111. {
  112. job.stream.colors[i] = new Color(val.x, val.y, val.z, val.w); break;
  113. }
  114. case BakeChannel.UV0:
  115. {
  116. job.stream.uv0[i] = val;
  117. break;
  118. }
  119. case BakeChannel.UV1:
  120. {
  121. job.stream.uv1[i] = val;
  122. break;
  123. }
  124. case BakeChannel.UV2:
  125. {
  126. job.stream.uv2[i] = val;
  127. break;
  128. }
  129. case BakeChannel.UV3:
  130. {
  131. job.stream.uv3[i] = val;
  132. break;
  133. }
  134. }
  135. }
  136. void BakeFromTexture(PaintJob[] jobs)
  137. {
  138. // make sure we have the channels we're baking to..
  139. InitBakeChannel(bakeChannel, jobs);
  140. // lets avoid the whole read/write texture thing, because it's lame to require that..
  141. int w = bakingTex.width;
  142. int h = bakingTex.height;
  143. RenderTexture rt = RenderTexture.GetTemporary(w, h, 0, RenderTextureFormat.ARGB32);
  144. Graphics.Blit(bakingTex, rt);
  145. Texture2D tex = new Texture2D(w, h, TextureFormat.ARGB32, false);
  146. RenderTexture.active = rt;
  147. tex.ReadPixels(new Rect(0,0,w,h), 0, 0);
  148. foreach (PaintJob job in jobs)
  149. {
  150. List<Vector4> srcUV0 = new List<Vector4>();
  151. List<Vector4> srcUV1 = new List<Vector4>();
  152. List<Vector4> srcUV2 = new List<Vector4>();
  153. List<Vector4> srcUV3 = new List<Vector4>();
  154. job.meshFilter.sharedMesh.GetUVs(0, srcUV0);
  155. job.meshFilter.sharedMesh.GetUVs(1, srcUV1);
  156. job.meshFilter.sharedMesh.GetUVs(2, srcUV2);
  157. job.meshFilter.sharedMesh.GetUVs(3, srcUV3);
  158. for (int i = 0; i < job.verts.Length; ++i)
  159. {
  160. Vector4 uv = Vector4.zero;
  161. switch (bakeSourceUV)
  162. {
  163. case BakeSourceUV.UV0:
  164. {
  165. if (job.stream.uv0 != null && job.stream.uv0.Count == job.verts.Length)
  166. uv = job.stream.uv0[i];
  167. else if (srcUV0 != null && srcUV0.Count == job.verts.Length)
  168. uv = srcUV0[i];
  169. break;
  170. }
  171. case BakeSourceUV.UV1:
  172. {
  173. if (job.stream.uv1 != null && job.stream.uv1.Count == job.verts.Length)
  174. uv = job.stream.uv1[i];
  175. else if (srcUV1 != null && srcUV1.Count == job.verts.Length)
  176. uv = srcUV1[i];
  177. break;
  178. }
  179. case BakeSourceUV.UV2:
  180. {
  181. if (job.stream.uv2 != null && job.stream.uv2.Count == job.verts.Length)
  182. uv = job.stream.uv2[i];
  183. else if (srcUV2 != null && srcUV2.Count == job.verts.Length)
  184. uv = srcUV2[i];
  185. break;
  186. }
  187. case BakeSourceUV.UV3:
  188. {
  189. if (job.stream.uv3 != null && job.stream.uv3.Count == job.verts.Length)
  190. uv = job.stream.uv3[i];
  191. else if (srcUV3 != null && srcUV3.Count == job.verts.Length)
  192. uv = srcUV3[i];
  193. break;
  194. }
  195. case BakeSourceUV.WorldSpaceXY:
  196. {
  197. Vector3 pos = job.stream.transform.localToWorldMatrix.MultiplyPoint(job.GetPosition(i));
  198. Vector2 p = new Vector2(pos.x, pos.y) - worldSpaceLower;
  199. Vector2 scale = worldSpaceUpper - worldSpaceLower;
  200. scale.x = Mathf.Max(0.000001f, scale.x);
  201. scale.y = Mathf.Max(0.000001f, scale.y);
  202. uv = p;
  203. uv.x /= scale.x;
  204. uv.y /= scale.y;
  205. break;
  206. }
  207. case BakeSourceUV.WorldSpaceXZ:
  208. {
  209. Vector3 pos = job.stream.transform.localToWorldMatrix.MultiplyPoint(job.GetPosition(i));
  210. Vector2 p = new Vector2(pos.x, pos.z) - worldSpaceLower;
  211. Vector2 scale = worldSpaceUpper - worldSpaceLower;
  212. scale.x = Mathf.Max(0.000001f, scale.x);
  213. scale.y = Mathf.Max(0.000001f, scale.y);
  214. uv = p;
  215. uv.x /= scale.x;
  216. uv.y /= scale.y;
  217. break;
  218. }
  219. case BakeSourceUV.WorldSpaceYZ:
  220. {
  221. Vector3 pos = job.stream.transform.localToWorldMatrix.MultiplyPoint(job.GetPosition(i));
  222. Vector2 p = new Vector2(pos.y, pos.z) - worldSpaceLower;
  223. Vector2 scale = worldSpaceUpper - worldSpaceLower;
  224. scale.x = Mathf.Max(0.000001f, scale.x);
  225. scale.y = Mathf.Max(0.000001f, scale.y);
  226. uv = p;
  227. uv.x /= scale.x;
  228. uv.y /= scale.y;
  229. break;
  230. }
  231. }
  232. Color c = tex.GetPixel((int)(uv.x*w), (int)(uv.y*w));
  233. BakeColor(job, bakeChannel, new Vector4(c.r, c.g, c.b, c.a), i);
  234. }
  235. job.stream.Apply();
  236. }
  237. }
  238. }
  239. }