207 lines
9.4 KiB
C#
207 lines
9.4 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
|
|
namespace VolumetricFogAndMist2 {
|
|
|
|
public partial class VolumetricFogEditor {
|
|
|
|
bool mouseIsDown;
|
|
|
|
private void OnSceneGUI_FogOfWar() {
|
|
|
|
Event e = Event.current;
|
|
if (fog == null || !fog.enableFogOfWar || !maskEditorEnabled.boolValue || e == null || fog.fogOfWarTexture == null) {
|
|
return;
|
|
}
|
|
|
|
Camera sceneCamera = null;
|
|
SceneView sceneView = SceneView.lastActiveSceneView;
|
|
if (sceneView != null) sceneCamera = sceneView.camera;
|
|
if (sceneCamera == null) return;
|
|
|
|
Vector2 mousePos = Event.current.mousePosition;
|
|
if (mousePos.x < 0 || mousePos.x > sceneCamera.pixelWidth || mousePos.y < 0 || mousePos.y > sceneCamera.pixelHeight) return;
|
|
|
|
Selection.activeGameObject = fog.gameObject;
|
|
fog.UpdateMaterialPropertiesNow();
|
|
|
|
Ray ray = HandleUtility.GUIPointToWorldRay(mousePos);
|
|
Bounds bounds = new Bounds(fog.transform.position, new Vector3(fog.transform.lossyScale.x, 0.01f, fog.transform.lossyScale.z));
|
|
if (bounds.IntersectRay(ray, out float distance)) {
|
|
Vector3 hitPoint = ray.origin + ray.direction * distance;
|
|
float handleSize = HandleUtility.GetHandleSize(hitPoint) * 0.5f;
|
|
Handles.color = new Color(0, 0, 1, 0.5f);
|
|
Handles.SphereHandleCap(0, hitPoint, Quaternion.identity, handleSize, EventType.Repaint);
|
|
HandleUtility.Repaint();
|
|
|
|
Handles.color = new Color(1, 1, 0, 0.85f);
|
|
Handles.DrawWireDisc(hitPoint, Vector3.up, maskBrushWidth.intValue * 0.995f);
|
|
Handles.color = new Color(0, 0, 1, 0.85f);
|
|
Handles.DrawWireDisc(hitPoint, Vector3.up, maskBrushWidth.intValue);
|
|
|
|
if (e.isMouse && e.button == 0) {
|
|
int controlID = GUIUtility.GetControlID(FocusType.Passive);
|
|
EventType eventType = e.GetTypeForControl(controlID);
|
|
|
|
if (eventType == EventType.MouseDown) {
|
|
GUIUtility.hotControl = controlID;
|
|
mouseIsDown = true;
|
|
} else if (eventType == EventType.MouseUp) {
|
|
GUIUtility.hotControl = controlID;
|
|
mouseIsDown = false;
|
|
}
|
|
}
|
|
|
|
if (mouseIsDown && e.type == EventType.Repaint) {
|
|
PaintOnMaskPosition(hitPoint);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#region Mask Texture support functions
|
|
|
|
private void CreateNewMaskTexture() {
|
|
int width = Mathf.Clamp(fog.fogOfWarTextureWidth, 256, 8192);
|
|
int height = Mathf.Clamp(fog.fogOfWarTextureHeight, 256, 8192);
|
|
Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false, true);
|
|
tex.wrapMode = TextureWrapMode.Clamp;
|
|
int len = width * height;
|
|
Color32[] cc = new Color32[len];
|
|
Color32 opaque = new Color32(255, 255, 255, 255);
|
|
int ccLength = cc.Length;
|
|
for (int k = 0; k < ccLength; k++) {
|
|
cc[k] = opaque;
|
|
}
|
|
tex.SetPixels32(cc);
|
|
tex.Apply();
|
|
|
|
string fileName = AssetDatabase.GenerateUniqueAssetPath("Assets/FogOfWarTexture.asset");
|
|
AssetDatabase.CreateAsset(tex, fileName);
|
|
AssetDatabase.SaveAssets();
|
|
fog.fogOfWarTexture = tex;
|
|
fog.maskBrushMode = MaskTextureBrushMode.RemoveFog;
|
|
EditorUtility.SetDirty(fog);
|
|
EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
|
|
EditorGUIUtility.PingObject(tex);
|
|
}
|
|
|
|
void PaintOnMaskPosition(Vector3 pos) {
|
|
if (maskBrushMode.intValue == (int)MaskTextureBrushMode.ColorFog) {
|
|
PaintColorOnMaskPosition(pos);
|
|
} else {
|
|
PaintAlphaOnMaskPosition(pos);
|
|
}
|
|
}
|
|
|
|
private void PaintAlphaOnMaskPosition(Vector3 pos) {
|
|
// Get texture location
|
|
Color32[] maskColors = fog.fogOfWarTextureData;
|
|
if (maskColors == null) {
|
|
fog.ReloadFogOfWarTexture();
|
|
maskColors = fog.fogOfWarTextureData;
|
|
}
|
|
if (maskColors == null) {
|
|
EditorUtility.DisplayDialog("Fog Of War Editor", "Re-enable fog of war to create the underline texture.", "Ok");
|
|
return;
|
|
}
|
|
Vector3 fogOfWarCenter = fog.anchoredFogOfWarCenter;
|
|
float x = (pos.x - fogOfWarCenter.x) / fog.fogOfWarSize.x + 0.5f;
|
|
float z = (pos.z - fogOfWarCenter.z) / fog.fogOfWarSize.z + 0.5f;
|
|
int textureWidth = fog.fogOfWarTextureWidth;
|
|
int textureHeight = fog.fogOfWarTextureHeight;
|
|
int tx = Mathf.Clamp((int)(x * textureWidth), 0, textureWidth - 1);
|
|
int ty = Mathf.Clamp((int)(z * textureHeight), 0, textureHeight - 1);
|
|
|
|
// Prepare brush data
|
|
int brushWidth = Mathf.FloorToInt(fog.fogOfWarTextureWidth * maskBrushWidth.intValue / fog.fogOfWarSize.x);
|
|
int brushHeight = Mathf.FloorToInt(fog.fogOfWarTextureHeight * maskBrushWidth.intValue / fog.fogOfWarSize.z);
|
|
byte color = maskBrushMode.intValue == (int)MaskTextureBrushMode.AddFog ? (byte)255 : (byte)0;
|
|
float brushOpacity = 1f - maskBrushOpacity.floatValue * 0.2f;
|
|
float fuzziness = 1.1f - maskBrushFuzziness.floatValue;
|
|
byte colort = (byte)(color * (1f - brushOpacity));
|
|
float radiusSqr = brushWidth * brushHeight;
|
|
// Paint!
|
|
for (int j = ty - brushHeight; j < ty + brushHeight; j++) {
|
|
if (j < 0) continue; else if (j >= textureHeight) break;
|
|
int jj = j * textureWidth;
|
|
int dj = (j - ty) * (j - ty);
|
|
for (int k = tx - brushWidth; k < tx + brushWidth; k++) {
|
|
if (k < 0) continue; else if (k >= textureWidth) break;
|
|
int distSqr = dj + (k - tx) * (k - tx);
|
|
float op = distSqr / radiusSqr;
|
|
float threshold = UnityEngine.Random.value;
|
|
if (op <= 1f && threshold * op < fuzziness) {
|
|
maskColors[jj + k].a = (byte)(colort + maskColors[jj + k].a * brushOpacity);
|
|
}
|
|
}
|
|
}
|
|
fog.UpdateFogOfWar(true);
|
|
}
|
|
|
|
|
|
private void PaintColorOnMaskPosition(Vector3 pos) {
|
|
// Get texture location
|
|
Color32[] maskColors = fog.fogOfWarTextureData;
|
|
if (maskColors == null) {
|
|
fog.ReloadFogOfWarTexture();
|
|
maskColors = fog.fogOfWarTextureData;
|
|
}
|
|
if (maskColors == null) {
|
|
EditorUtility.DisplayDialog("Fog Of War Editor", "Re-enable fog of war to create the underline texture.", "Ok");
|
|
return;
|
|
}
|
|
Vector3 fogOfWarCenter = fog.anchoredFogOfWarCenter;
|
|
float x = (pos.x - fogOfWarCenter.x) / fog.fogOfWarSize.x + 0.5f;
|
|
float z = (pos.z - fogOfWarCenter.z) / fog.fogOfWarSize.z + 0.5f;
|
|
int textureWidth = fog.fogOfWarTextureWidth;
|
|
int textureHeight = fog.fogOfWarTextureHeight;
|
|
int tx = Mathf.Clamp((int)(x * textureWidth), 0, textureWidth - 1);
|
|
int ty = Mathf.Clamp((int)(z * textureHeight), 0, textureHeight - 1);
|
|
|
|
// Prepare brush data
|
|
int brushWidth = Mathf.FloorToInt(fog.fogOfWarTextureWidth * maskBrushWidth.intValue / fog.fogOfWarSize.x);
|
|
int brushHeight = Mathf.FloorToInt(fog.fogOfWarTextureHeight * maskBrushWidth.intValue / fog.fogOfWarSize.z);
|
|
float brushOpacity = 1f - maskBrushOpacity.floatValue * 0.2f;
|
|
float fuzziness = 1.1f - maskBrushFuzziness.floatValue;
|
|
byte rt = (byte)(maskBrushColor.colorValue.r * (1f - brushOpacity) * 255f);
|
|
byte gt = (byte)(maskBrushColor.colorValue.g * (1f - brushOpacity) * 255f);
|
|
byte bt = (byte)(maskBrushColor.colorValue.b * (1f - brushOpacity) * 255f);
|
|
Color32 colort = new Color32(rt, gt, bt, 255);
|
|
float radiusSqr = brushWidth * brushHeight;
|
|
|
|
int j0 = ty - brushHeight;
|
|
if (j0 < 0) j0 = 0;
|
|
int j1 = ty + brushHeight;
|
|
if (j1 >= textureHeight) j1 = textureHeight - 1;
|
|
|
|
int k0 = tx - brushWidth;
|
|
if (k0 < 0) k0 = 0;
|
|
int k1 = tx + brushWidth;
|
|
if (k1 >= textureWidth) k1 = textureWidth - 1;
|
|
|
|
// Paint!
|
|
for (int j = j0; j <= j1; j++) {
|
|
int jj = j * textureWidth;
|
|
int dj = (j - ty) * (j - ty);
|
|
for (int k = k0; k <= k1; k++) {
|
|
int distSqr = dj + (k - tx) * (k - tx);
|
|
float op = distSqr / radiusSqr;
|
|
float threshold = Random.value;
|
|
if (op <= 1f && threshold * op < fuzziness) {
|
|
maskColors[jj + k].r = (byte)(colort.r + maskColors[jj + k].r * brushOpacity);
|
|
maskColors[jj + k].g = (byte)(colort.g + maskColors[jj + k].g * brushOpacity);
|
|
maskColors[jj + k].b = (byte)(colort.b + maskColors[jj + k].b * brushOpacity);
|
|
}
|
|
}
|
|
}
|
|
fog.UpdateFogOfWar(true);
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
} |