Files
2024-11-20 15:21:28 +01:00

631 lines
20 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
public class VertexPainter : EditorWindow
{
bool drawing = false;
bool showVertexColors = false;
bool showFlowMap = false;
GameObject currentDrawObject;
List<MeshFilter> meshFilters = new List<MeshFilter>();
List<Material> oldMaterials = new List<Material>();
int toolbarInt = 0;
Color drawColor = Color.white;
float drawSize = 0.5f;
float opacity = 1f;
bool drawColorR = true;
bool drawColorG = true;
bool drawColorB = true;
bool drawColorA = true;
public float flowSpeed = 1f;
public float flowDirection = 0f;
public string[] toolbarStrings = new string[] {
"Vertex Color",
"Flow Map"
};
[MenuItem("Tools/Nature Manufacture/Vertex Painter")]
static void Init()
{
// Get existing open window or if none, make a new one:
VertexPainter window = EditorWindow.GetWindow<VertexPainter>("VertexPainter");
window.Show();
}
void OnGUI()
{
toolbarInt = GUILayout.Toolbar(toolbarInt, toolbarStrings);
if (!drawing)
{
if (GUILayout.Button("Start Drawing"))
{
if (Selection.activeGameObject != null)
{
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
meshFilters.Clear();
MeshFilter[] filters = Selection.activeGameObject.GetComponentsInChildren<MeshFilter>();
foreach (var item in filters)
{
currentDrawObject = Selection.activeGameObject;
meshFilters.Add(item);
drawing = true;
Tools.current = Tool.None;
Undo.RecordObject(item.sharedMesh, "Start draw vertex");
}
}
}
}
if (drawing)
{
if (Selection.activeGameObject != currentDrawObject)
{
StopDrawing();
}
if (GUILayout.Button("End Drawing"))
{
StopDrawing();
}
EditorGUILayout.Space();
if (toolbarInt == 0)
{
if (!showVertexColors)
{
if (GUILayout.Button("Show vertex colors"))
{
if (!showFlowMap && !showVertexColors)
oldMaterials.Clear();
for (int i = 0; i < meshFilters.Count; i++)
{
if (!showFlowMap && !showVertexColors)
oldMaterials.Add(meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial);
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("NatureManufacture Shaders/Debug/Vertex color"));
}
ResetMaterial();
showVertexColors = true;
}
}
else
{
if (GUILayout.Button("Hide vertex colors"))
{
ResetMaterial();
for (int i = 0; i < meshFilters.Count; i++)
{
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial = oldMaterials[i];
}
showVertexColors = false;
}
}
if (GUILayout.Button("Reset colors"))
{
RestartColor();
}
EditorGUILayout.HelpBox("River Auto Material -> R Wetness", MessageType.Info);
}
else
{
if (!showFlowMap)
{
if (GUILayout.Button("Show flow directions"))
{
if (!showFlowMap && !showVertexColors)
oldMaterials.Clear();
for (int i = 0; i < meshFilters.Count; i++)
{
if (!showFlowMap && !showVertexColors)
oldMaterials.Add(meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial);
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("NatureManufacture Shaders/Debug/Flowmap Direction"));
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_Direction", Resources.Load<Texture2D>("Debug_Arrow"));
}
ResetMaterial();
showFlowMap = true;
}
}
else
{
if (GUILayout.Button("Hide flow directions"))
{
ResetMaterial();
for (int i = 0; i < meshFilters.Count; i++)
{
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial = oldMaterials[i];
}
showFlowMap = false;
}
}
if (GUILayout.Button("Reset flow"))
{
RestartFlow();
}
}
}
if (toolbarInt == 0)
{
drawColor = EditorGUILayout.ColorField("Draw color", drawColor);
opacity = EditorGUILayout.FloatField("Opacity", opacity);
drawSize = EditorGUILayout.FloatField("Size", drawSize);
if (drawSize < 0)
{
drawSize = 0;
}
drawColorR = EditorGUILayout.Toggle("Draw R", drawColorR);
drawColorG = EditorGUILayout.Toggle("Draw G", drawColorG);
drawColorB = EditorGUILayout.Toggle("Draw B", drawColorB);
drawColorA = EditorGUILayout.Toggle("Draw A", drawColorA);
EditorGUILayout.HelpBox("R - Emission G- Bottom Cover B - Top Cover\n" +
"Paint - Left Mouse Button Click \n" +
"Clean - SHIFT + Left Mouse Button Click \n", MessageType.Info);
EditorGUILayout.Space();
}
else
{
flowSpeed = EditorGUILayout.Slider("Flow U Speed", flowSpeed, -1, 1);
flowDirection = EditorGUILayout.Slider("Flow V Speed", flowDirection, -1, 1);
opacity = EditorGUILayout.FloatField("Opacity", opacity);
drawSize = EditorGUILayout.FloatField("Size", drawSize);
if (drawSize < 0)
{
drawSize = 0;
}
}
}
void ResetMaterial()
{
showFlowMap = false;
showVertexColors = false;
}
void StopDrawing()
{
if (showVertexColors)
{
for (int i = 0; i < meshFilters.Count; i++)
{
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial = oldMaterials[i];
}
showVertexColors = false;
}
if (showFlowMap)
{
for (int i = 0; i < meshFilters.Count; i++)
{
meshFilters[i].GetComponent<MeshRenderer>().sharedMaterial = oldMaterials[i];
}
showFlowMap = false;
}
currentDrawObject = null;
drawing = false;
meshFilters.Clear();
}
protected virtual void OnSceneGUI(SceneView sceneView)
{
if (Selection.activeGameObject != currentDrawObject && drawing)
{
StopDrawing();
}
Color baseColor = Handles.color;
if (currentDrawObject != null)
{
if (drawing)
{
if (toolbarInt == 0)
DrawOnVertexColors();
else
DrawOnFlowMap();
}
}
}
void RestartColor()
{
foreach (var item in meshFilters)
{
Mesh mesh = item.sharedMesh;
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh)))
{
mesh = Instantiate<Mesh>(item.sharedMesh);
item.sharedMesh = mesh;
}
mesh.colors = null;
}
}
void RestartFlow()
{
foreach (var item in meshFilters)
{
Mesh mesh = item.sharedMesh;
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh)))
{
mesh = Instantiate<Mesh>(item.sharedMesh);
item.sharedMesh = mesh;
}
mesh.uv4 = null;
}
}
void DrawOnVertexColors()
{
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
Camera sceneCamera = SceneView.lastActiveSceneView.camera;
//Vector2 mousePos = Event.current.mousePosition;
//mousePos.y = Screen.height - mousePos.y - 40;
//Ray ray = sceneCamera.ScreenPointToRay(mousePos);
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
List<MeshCollider> meshColliders = new List<MeshCollider>();
foreach (var item in meshFilters)
{
meshColliders.Add(item.gameObject.AddComponent<MeshCollider>());
}
RaycastHit[] hits = Physics.RaycastAll(ray, Mathf.Infinity);
Vector3 hitPosition = Vector3.zero;
Vector3 hitNormal = Vector3.zero;
if (hits.Length > 0)
{
foreach (var hit in hits)
{
if (hit.collider is MeshCollider)
{
MeshFilter meshFilter = hit.collider.GetComponent<MeshFilter>();
hitPosition = hit.point;
hitNormal = hit.normal;
Handles.color = new Color(drawColor.r, drawColor.g, drawColor.b, 1);
Handles.DrawLine(hitPosition, hitPosition + hitNormal * 2);
Handles.CircleHandleCap(
GUIUtility.GetControlID(FocusType.Passive),
hitPosition,
Quaternion.LookRotation(hitNormal),
drawSize,
EventType.Repaint
);
Handles.color = Color.black;
Handles.CircleHandleCap(
GUIUtility.GetControlID(FocusType.Passive),
hitPosition,
Quaternion.LookRotation(hitNormal),
drawSize * 0.95f,
EventType.Repaint
);
foreach (var currentMeshFilter in meshFilters)
{
if (meshFilter == currentMeshFilter)
{
if (!(Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag) || Event.current.button != 0)
continue;
if (meshFilter.sharedMesh != null)
{
Mesh mesh = meshFilter.sharedMesh;
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh)))
{
mesh = Instantiate<Mesh>(meshFilter.sharedMesh);
meshFilter.sharedMesh = mesh;
}
int vertLength = mesh.vertices.Length;
Vector3[] vertices = mesh.vertices;
Color[] colors = mesh.colors;
Transform transform = meshFilter.transform;
if (colors.Length == 0)
{
colors = new Color[vertLength];
for (int i = 0; i < colors.Length; i++)
{
colors[i] = Color.white;
}
}
for (int i = 0; i < vertLength; i++)
{
float dist = Vector3.Distance(hitPosition, transform.TransformPoint(vertices[i]));
if (dist < drawSize)
{
if (Event.current.shift)
colors[i] = Color.Lerp(colors[i], Color.white, opacity);
else
colors[i] = Color.Lerp(colors[i], drawColor, opacity);
if (Event.current.shift)
{
if (drawColorR)
colors[i].r = Mathf.Lerp(colors[i].r, 1, opacity);
if (drawColorG)
colors[i].g = Mathf.Lerp(colors[i].g, 1, opacity);
if (drawColorB)
colors[i].b = Mathf.Lerp(colors[i].b, 1, opacity);
if (drawColorA)
colors[i].a = Mathf.Lerp(colors[i].a, 1, opacity);
}
else
{
if (drawColorR)
colors[i].r = Mathf.Lerp(colors[i].r, drawColor.r, opacity);
if (drawColorG)
colors[i].g = Mathf.Lerp(colors[i].g, drawColor.g, opacity);
if (drawColorB)
colors[i].b = Mathf.Lerp(colors[i].b, drawColor.b, opacity);
if (drawColorA)
colors[i].a = Mathf.Lerp(colors[i].a, drawColor.a, opacity);
}
}
}
mesh.colors = colors;
}
}
}
}
}
}
foreach (var item in meshColliders)
{
DestroyImmediate(item);
}
}
void DrawOnFlowMap()
{
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
Camera sceneCamera = SceneView.lastActiveSceneView.camera;
//Vector2 mousePos = Event.current.mousePosition;
//mousePos.y = Screen.height - mousePos.y - 40;
//Ray ray = sceneCamera.ScreenPointToRay(mousePos);
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
List<MeshCollider> meshColliders = new List<MeshCollider>();
foreach (var item in meshFilters)
{
meshColliders.Add(item.gameObject.AddComponent<MeshCollider>());
}
RaycastHit[] hits = Physics.RaycastAll(ray, Mathf.Infinity);
Vector3 hitPosition = Vector3.zero;
Vector3 hitNormal = Vector3.zero;
if (hits.Length > 0)
{
foreach (var hit in hits)
{
if (hit.collider is MeshCollider)
{
MeshFilter meshFilter = hit.collider.GetComponent<MeshFilter>();
hitPosition = hit.point;
hitNormal = hit.normal;
Handles.color = new Color(drawColor.r, drawColor.g, drawColor.b, 1);
Handles.DrawLine(hitPosition, hitPosition + hitNormal * 2);
Handles.CircleHandleCap(
GUIUtility.GetControlID(FocusType.Passive),
hitPosition,
Quaternion.LookRotation(hitNormal),
drawSize,
EventType.Repaint
);
Handles.color = Color.black;
Handles.CircleHandleCap(
GUIUtility.GetControlID(FocusType.Passive),
hitPosition,
Quaternion.LookRotation(hitNormal),
drawSize * 0.95f,
EventType.Repaint
);
foreach (var currentMeshFilter in meshFilters)
{
if (meshFilter == currentMeshFilter)
{
if (!(Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag) || Event.current.button != 0)
continue;
if (meshFilter.sharedMesh != null)
{
Mesh mesh = meshFilter.sharedMesh;
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh)))
{
mesh = Instantiate<Mesh>(meshFilter.sharedMesh);
meshFilter.sharedMesh = mesh;
}
int vertLength = mesh.vertices.Length;
Vector3[] vertices = mesh.vertices;
Vector2[] colorsFlowMap = mesh.uv4;
Transform transform = meshFilter.transform;
if (colorsFlowMap.Length == 0)
{
colorsFlowMap = new Vector2[vertLength];
for (int i = 0; i < colorsFlowMap.Length; i++)
{
colorsFlowMap[i] = new Vector2(0, 0);
}
}
float dist = 0;
float distValue = 0;
for (int i = 0; i < vertLength; i++)
{
dist = Vector3.Distance(hitPosition, transform.TransformPoint(vertices[i]));
if (dist < drawSize)
{
distValue = (drawSize - dist) / (float)drawSize;
if (Event.current.shift)
{
colorsFlowMap[i] = Vector2.Lerp(colorsFlowMap[i], new Vector2(0, 0), opacity);
}
else
{
colorsFlowMap[i] = Vector2.Lerp(colorsFlowMap[i], new Vector2(flowDirection, flowSpeed), opacity * distValue);
}
}
}
mesh.uv4 = colorsFlowMap;
}
}
}
}
}
}
foreach (var item in meshColliders)
{
DestroyImmediate(item);
}
}
void OnFocus()
{
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui -= this.OnSceneGUI;
SceneView.duringSceneGui += this.OnSceneGUI;
#else
SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
SceneView.onSceneGUIDelegate += this.OnSceneGUI;
#endif
}
void OnDestroy()
{
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui -= this.OnSceneGUI;
#else
SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
#endif
if (drawing)
StopDrawing();
}
}