VolumetricFogEditor.FoW.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditor.SceneManagement;
  4. namespace VolumetricFogAndMist2 {
  5. public partial class VolumetricFogEditor {
  6. bool mouseIsDown;
  7. private void OnSceneGUI() {
  8. Event e = Event.current;
  9. if (fog == null || !fog.enableFogOfWar || !maskEditorEnabled.boolValue || e == null || fog.fogOfWarTexture == null) {
  10. return;
  11. }
  12. Camera sceneCamera = null;
  13. SceneView sceneView = SceneView.lastActiveSceneView;
  14. if (sceneView != null) sceneCamera = sceneView.camera;
  15. if (sceneCamera == null) return;
  16. Vector2 mousePos = Event.current.mousePosition;
  17. if (mousePos.x < 0 || mousePos.x > sceneCamera.pixelWidth || mousePos.y < 0 || mousePos.y > sceneCamera.pixelHeight) return;
  18. Selection.activeGameObject = fog.gameObject;
  19. fog.UpdateMaterialPropertiesNow();
  20. Ray ray = HandleUtility.GUIPointToWorldRay(mousePos);
  21. Bounds bounds = new Bounds(fog.transform.position, new Vector3(fog.transform.lossyScale.x, 0.01f, fog.transform.lossyScale.z));
  22. if (bounds.IntersectRay(ray, out float distance)) {
  23. Vector3 hitPoint = ray.origin + ray.direction * distance;
  24. float handleSize = HandleUtility.GetHandleSize(hitPoint) * 0.5f;
  25. Handles.color = new Color(0, 0, 1, 0.5f);
  26. Handles.SphereHandleCap(0, hitPoint, Quaternion.identity, handleSize, EventType.Repaint);
  27. HandleUtility.Repaint();
  28. Handles.color = new Color(1, 1, 0, 0.85f);
  29. Handles.DrawWireDisc(hitPoint, Vector3.up, maskBrushWidth.intValue * 0.995f);
  30. Handles.color = new Color(0, 0, 1, 0.85f);
  31. Handles.DrawWireDisc(hitPoint, Vector3.up, maskBrushWidth.intValue);
  32. if (e.isMouse && e.button == 0) {
  33. int controlID = GUIUtility.GetControlID(FocusType.Passive);
  34. EventType eventType = e.GetTypeForControl(controlID);
  35. if (eventType == EventType.MouseDown) {
  36. GUIUtility.hotControl = controlID;
  37. mouseIsDown = true;
  38. } else if (eventType == EventType.MouseUp) {
  39. GUIUtility.hotControl = controlID;
  40. mouseIsDown = false;
  41. }
  42. }
  43. if (mouseIsDown && e.type == EventType.Repaint) {
  44. PaintOnMaskPosition(hitPoint);
  45. }
  46. }
  47. }
  48. #region Mask Texture support functions
  49. private void CreateNewMaskTexture() {
  50. int res = Mathf.Clamp(fog.fogOfWarTextureSize, 256, 8192);
  51. Texture2D tex = new Texture2D(res, res, TextureFormat.RGBA32, false, true);
  52. tex.wrapMode = TextureWrapMode.Clamp;
  53. int len = res * res;
  54. Color32[] cc = new Color32[len];
  55. Color32 opaque = new Color32(255, 255, 255, 255);
  56. for (int k = 0; k < cc.Length; k++) {
  57. cc[k] = opaque;
  58. }
  59. tex.SetPixels32(cc);
  60. tex.Apply();
  61. string fileName = AssetDatabase.GenerateUniqueAssetPath("Assets/FogOfWarTexture.asset");
  62. AssetDatabase.CreateAsset(tex, fileName);
  63. AssetDatabase.SaveAssets();
  64. fog.fogOfWarTexture = tex;
  65. fog.maskBrushMode = MASK_TEXTURE_BRUSH_MODE.RemoveFog;
  66. EditorUtility.SetDirty(fog);
  67. EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
  68. EditorGUIUtility.PingObject(tex);
  69. }
  70. void PaintOnMaskPosition(Vector3 pos) {
  71. if (maskBrushMode.intValue == (int)MASK_TEXTURE_BRUSH_MODE.ColorFog) {
  72. PaintColorOnMaskPosition(pos);
  73. } else {
  74. PaintAlphaOnMaskPosition(pos);
  75. }
  76. }
  77. private void PaintAlphaOnMaskPosition(Vector3 pos) {
  78. // Get texture location
  79. Color32[] maskColors = fog.fogOfWarTextureData;
  80. if (maskColors == null) {
  81. fog.ReloadFogOfWarTexture();
  82. maskColors = fog.fogOfWarTextureData;
  83. }
  84. if (maskColors == null) {
  85. EditorUtility.DisplayDialog("Fog Of War Editor", "Re-enable fog of war to create the underline texture.", "Ok");
  86. return;
  87. }
  88. Vector3 fogOfWarCenter = fog.anchoredFogOfWarCenter;
  89. float x = (pos.x - fogOfWarCenter.x) / fog.fogOfWarSize.x + 0.5f;
  90. float z = (pos.z - fogOfWarCenter.z) / fog.fogOfWarSize.z + 0.5f;
  91. int textureSize = fog.fogOfWarTextureSize;
  92. int tx = Mathf.Clamp((int)(x * textureSize), 0, textureSize - 1);
  93. int ty = Mathf.Clamp((int)(z * textureSize), 0, textureSize - 1);
  94. // Prepare brush data
  95. int brushSize = Mathf.FloorToInt(fog.fogOfWarTextureSize * maskBrushWidth.intValue / fog.fogOfWarSize.x);
  96. byte color = maskBrushMode.intValue == (int)MASK_TEXTURE_BRUSH_MODE.AddFog ? (byte)255 : (byte)0;
  97. float brushOpacity = 1f - maskBrushOpacity.floatValue * 0.2f;
  98. float fuzziness = 1.1f - maskBrushFuzziness.floatValue;
  99. byte colort = (byte)(color * (1f - brushOpacity));
  100. float radiusSqr = brushSize * brushSize;
  101. // Paint!
  102. for (int j = ty - brushSize; j < ty + brushSize; j++) {
  103. if (j < 0) continue; else if (j >= textureSize) break;
  104. int jj = j * textureSize;
  105. int dj = (j - ty) * (j - ty);
  106. for (int k = tx - brushSize; k < tx + brushSize; k++) {
  107. if (k < 0) continue; else if (k >= textureSize) break;
  108. int distSqr = dj + (k - tx) * (k - tx);
  109. float op = distSqr / radiusSqr;
  110. float threshold = UnityEngine.Random.value;
  111. if (op <= 1f && threshold * op < fuzziness) {
  112. maskColors[jj + k].a = (byte)(colort + maskColors[jj + k].a * brushOpacity);
  113. }
  114. }
  115. }
  116. fog.UpdateFogOfWar(true);
  117. }
  118. private void PaintColorOnMaskPosition(Vector3 pos) {
  119. // Get texture location
  120. Color32[] maskColors = fog.fogOfWarTextureData;
  121. if (maskColors == null) {
  122. fog.ReloadFogOfWarTexture();
  123. maskColors = fog.fogOfWarTextureData;
  124. }
  125. if (maskColors == null) {
  126. EditorUtility.DisplayDialog("Fog Of War Editor", "Re-enable fog of war to create the underline texture.", "Ok");
  127. return;
  128. }
  129. Vector3 fogOfWarCenter = fog.anchoredFogOfWarCenter;
  130. float x = (pos.x - fogOfWarCenter.x) / fog.fogOfWarSize.x + 0.5f;
  131. float z = (pos.z - fogOfWarCenter.z) / fog.fogOfWarSize.z + 0.5f;
  132. int textureSize = fog.fogOfWarTextureSize;
  133. int tx = Mathf.Clamp((int)(x * textureSize), 0, textureSize - 1);
  134. int ty = Mathf.Clamp((int)(z * textureSize), 0, textureSize - 1);
  135. // Prepare brush data
  136. int brushSize = Mathf.FloorToInt(fog.fogOfWarTextureSize * maskBrushWidth.intValue / fog.fogOfWarSize.x);
  137. float brushOpacity = 1f - maskBrushOpacity.floatValue * 0.2f;
  138. float fuzziness = 1.1f - maskBrushFuzziness.floatValue;
  139. byte rt = (byte)(maskBrushColor.colorValue.r * (1f - brushOpacity) * 255f);
  140. byte gt = (byte)(maskBrushColor.colorValue.g * (1f - brushOpacity) * 255f);
  141. byte bt = (byte)(maskBrushColor.colorValue.b * (1f - brushOpacity) * 255f);
  142. Color32 colort = new Color32(rt, gt, bt, 255);
  143. float radiusSqr = brushSize * brushSize;
  144. // Paint!
  145. for (int j = ty - brushSize; j < ty + brushSize; j++) {
  146. if (j < 0) continue; else if (j >= textureSize) break;
  147. int jj = j * textureSize;
  148. int dj = (j - ty) * (j - ty);
  149. for (int k = tx - brushSize; k < tx + brushSize; k++) {
  150. if (k < 0) continue; else if (k >= textureSize) break;
  151. int distSqr = dj + (k - tx) * (k - tx);
  152. float op = distSqr / radiusSqr;
  153. float threshold = UnityEngine.Random.value;
  154. if (op <= 1f && threshold * op < fuzziness) {
  155. maskColors[jj + k].r = (byte)(colort.r + maskColors[jj + k].r * brushOpacity);
  156. maskColors[jj + k].g = (byte)(colort.g + maskColors[jj + k].g * brushOpacity);
  157. maskColors[jj + k].b = (byte)(colort.b + maskColors[jj + k].b * brushOpacity);
  158. }
  159. }
  160. }
  161. fog.UpdateFogOfWar(true);
  162. }
  163. #endregion
  164. }
  165. }