rabidus-test/Assets/Dreamteck/Splines/Editor/Components/SplineMeshEditor.cs

480 lines
22 KiB
C#
Raw Permalink Normal View History

2023-07-24 16:38:13 +03:00
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(SplineMesh), true)]
[CanEditMultipleObjects]
public class SplineMeshEditor : MeshGenEditor
{
private int selectedChannel = -1;
SplineMesh.Channel renameChannel = null;
MeshDefinitionWindow definitionWindow = null;
MeshScaleModifierEditor scaleModifierEditor;
private Mesh GetMeshFromObject(Object obj)
{
SplineMesh user = (SplineMesh)target;
if (!(obj is GameObject)) return null;
GameObject gameObj = (GameObject)obj;
MeshFilter filter = gameObj.GetComponent<MeshFilter>();
Mesh returnMesh = null;
if (filter != null && filter.sharedMesh != null) returnMesh = filter.sharedMesh;
MeshRenderer rend = user.GetComponent<MeshRenderer>();
if (rend == null) return returnMesh;
MeshRenderer meshRend = gameObj.GetComponent<MeshRenderer>();
if (meshRend == null) return returnMesh;
bool found = false;
for (int i = 0; i < meshRend.sharedMaterials.Length; i++)
{
for (int j = 0; j < rend.sharedMaterials.Length; j++)
{
if(meshRend.sharedMaterials[i] == rend.sharedMaterials[j])
{
found = true;
break;
}
}
}
if (!found)
{
if(EditorUtility.DisplayDialog("New Materials", "The added object has one or more materials which are not refrenced by the renderer. Would you like to add them?", "Yes", "No")) {
if(rend.sharedMaterial == AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat"))
{
if (EditorUtility.DisplayDialog("Replace Material", "The renderer is using the default material. Replace it?", "Yes", "No")) rend.sharedMaterials = new Material[0];
}
for (int i = 0; i < meshRend.sharedMaterials.Length; i++) AddMaterial(rend, meshRend.sharedMaterials[i]);
}
}
return returnMesh;
}
void AddMaterial(MeshRenderer target, Material material)
{
for (int i = 0; i < target.sharedMaterials.Length; i++)
{
if (target.sharedMaterials[i] == material) return;
}
Material[] newMaterials = new Material[target.sharedMaterials.Length + 1];
target.sharedMaterials.CopyTo(newMaterials, 0);
newMaterials[newMaterials.Length - 1] = material;
target.sharedMaterials = newMaterials;
}
void OnDuplicateChannel(object index)
{
SplineMesh extruder = (SplineMesh)target;
SplineMesh.Channel source = extruder.GetChannel((int)index);
SplineMesh.Channel newChannel = extruder.AddChannel(source.name);
source.CopyTo(newChannel);
}
void OnRenameChannel(object index)
{
SplineMesh extruder = (SplineMesh)target;
renameChannel = extruder.GetChannel((int)index);
Repaint();
}
void OnDeleteChannel(object index)
{
SplineMesh extruder = (SplineMesh)target;
extruder.RemoveChannel((int)index);
Repaint();
}
void OnMoveChannelUp(object index)
{
SplineMesh extruder = (SplineMesh)target;
extruder.SwapChannels((int)index, ((int)index)-1);
Repaint();
}
void OnMoveChannelDown(object index)
{
SplineMesh extruder = (SplineMesh)target;
extruder.SwapChannels((int)index, ((int)index) + 1);
Repaint();
}
protected override void DuringSceneGUI(SceneView currentSceneView)
{
base.DuringSceneGUI(currentSceneView);
if (scaleModifierEditor != null) scaleModifierEditor.DrawScene();
}
protected override void BodyGUI()
{
showSize = false;
showDoubleSided = false;
showFlipFaces = false;
base.BodyGUI();
SplineMesh user = (SplineMesh)target;
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Uv Coordinates", EditorStyles.boldLabel);
user.uvOffset = EditorGUILayout.Vector2Field("UV Offset", user.uvOffset);
user.uvScale = EditorGUILayout.Vector2Field("UV Scale", user.uvScale);
if (targets.Length > 1)
{
EditorGUILayout.HelpBox("Cannot edit channels when multiple objects are selected", MessageType.Info);
return;
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Channels", EditorStyles.boldLabel);
for (int i = 0; i < user.GetChannelCount(); i++)
{
if (ChannelPanel(i))
{
if (Event.current.type == EventType.MouseDown)
{
Repaint();
if (Event.current.button == 0)
{
if (selectedChannel == i)
{
selectedChannel = -1;
}
else
{
selectedChannel = i;
scaleModifierEditor = new MeshScaleModifierEditor(user, this, i);
scaleModifierEditor.alwaysOpen = true;
}
}
else if (Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Rename"), false, OnRenameChannel, i);
menu.AddItem(new GUIContent("Duplicate"), false, OnDuplicateChannel, i);
if (i == 0) menu.AddDisabledItem(new GUIContent("Move Up"));
else menu.AddItem(new GUIContent("Move Up"), false, OnMoveChannelUp, i);
if (i == user.GetChannelCount() - 1) menu.AddDisabledItem(new GUIContent("Move Down"));
else menu.AddItem(new GUIContent("Move Down"), false, OnMoveChannelDown, i);
menu.AddSeparator("");
menu.AddItem(new GUIContent("Delete"), false, OnDeleteChannel, i);
menu.ShowAsContext();
}
}
}
}
if (GUILayout.Button("New Channel")) user.AddChannel("Channel " + (user.GetChannelCount() + 1));
if (EditorGUI.EndChangeCheck()) EditorUtility.SetDirty(user);
}
bool ChannelPanel(int channelIndex)
{
SplineMesh.Channel channel = ((SplineMesh)target).GetChannel(channelIndex);
bool open = selectedChannel == channelIndex;
GUILayout.BeginVertical(EditorStyles.helpBox);
if (renameChannel == channel && Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter))
{
renameChannel = null;
Repaint();
}
if (renameChannel == channel) channel.name = EditorGUILayout.TextField(channel.name);
else EditorGUILayout.LabelField(channel.name, EditorStyles.boldLabel);
if (!open)
{
GUILayout.EndVertical();
return GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition);
}
Rect labelRect = GUILayoutUtility.GetLastRect();
EditorGUI.indentLevel++;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mesh Objects", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 100f;
EditorGUILayout.BeginVertical();
for (int i = 0; i < channel.GetMeshCount(); i++) MeshRow(channel, i);
Object obj = null;
obj = EditorGUILayout.ObjectField("Add Mesh", obj, typeof(Object), true);
if (obj != null)
{
if (obj is Mesh) channel.AddMesh((Mesh)obj);
else
{
Mesh m = GetMeshFromObject(obj);
if (m != null) channel.AddMesh(m);
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
channel.type = (SplineMesh.Channel.Type)EditorGUILayout.EnumPopup("Type", channel.type);
if (channel.autoCount) EditorGUILayout.TextField("Auto Count: " + channel.count);
else channel.count = EditorGUILayout.IntField("Count", channel.count);
channel.autoCount = EditorGUILayout.Toggle("Auto Count", channel.autoCount);
channel.randomOrder = EditorGUILayout.Toggle("Random Order", channel.randomOrder);
if (channel.randomOrder) channel.randomSeed = EditorGUILayout.IntField("Seed", channel.randomSeed);
EditorGUILayout.EndVertical();
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
float clipFrom = (float)channel.clipFrom;
float clipTo = (float)channel.clipTo;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.MinMaxSlider(new GUIContent("Clip Range:"), ref clipFrom, ref clipTo, 0f, 1f);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
channel.clipFrom = clipFrom;
channel.clipTo = clipTo;
EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(30));
channel.clipFrom = EditorGUILayout.FloatField((float)channel.clipFrom);
channel.clipTo = EditorGUILayout.FloatField((float)channel.clipTo);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Geometry", EditorStyles.boldLabel);
if(channel.type != SplineMesh.Channel.Type.Place) channel.spacing = EditorGUILayout.Slider("Spacing", (float)channel.spacing, 0f, 1f);
//Offset
channel.minOffset = EditorGUILayout.Vector2Field(channel.randomOffset ? "Offset Min" : "Offset", channel.minOffset);
if(channel.randomOffset) channel.maxOffset = EditorGUILayout.Vector2Field("Offset Max", channel.maxOffset);
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130f;
channel.randomOffset = EditorGUILayout.Toggle("Randomize Offset", channel.randomOffset);
if (channel.randomOffset) channel.offsetSeed = EditorGUILayout.IntField("Seed", channel.offsetSeed);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
//Rotation
if (channel.type == SplineMesh.Channel.Type.Extrude)
{
Vector3 rot = channel.minRotation;
rot.z = EditorGUILayout.FloatField(channel.randomRotation ? "Rotation Min" : "Rotation", rot.z);
channel.minRotation = rot;
if (channel.randomRotation)
{
rot = channel.maxRotation;
rot.z = EditorGUILayout.FloatField("Rotation Max", rot.z);
channel.maxRotation = rot;
}
}
else
{
channel.minRotation = EditorGUILayout.Vector3Field(channel.randomRotation ? "Rotation Min" : "Rotation", channel.minRotation);
if (channel.randomRotation) channel.maxRotation = EditorGUILayout.Vector3Field("Rotation Max", channel.maxRotation);
}
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130f;
channel.randomRotation = EditorGUILayout.Toggle("Randomize Rotation", channel.randomRotation);
if (channel.randomRotation) channel.rotationSeed = EditorGUILayout.IntField("Seed", channel.rotationSeed);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
//Scale
if (channel.type == SplineMesh.Channel.Type.Extrude)
{
float lastZ = channel.minScale.z;
Vector3 scale = channel.minScale;
scale = EditorGUILayout.Vector2Field(channel.randomScale ? "Scale Min" : "Scale", scale);
scale += Vector3.forward * lastZ;
channel.minScale = scale;
if (channel.randomScale)
{
lastZ = channel.maxScale.z;
scale = channel.maxScale;
scale = EditorGUILayout.Vector2Field("Scale Max", scale);
scale += Vector3.forward * lastZ;
channel.maxScale = scale;
}
}
else
{
channel.minScale = EditorGUILayout.Vector3Field(channel.randomScale ? "Scale Min" : "Scale", channel.minScale);
if (channel.randomScale) channel.maxScale = EditorGUILayout.Vector3Field("Scale Max", channel.maxScale);
}
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130f;
channel.randomScale = EditorGUILayout.Toggle("Randomize Scale", channel.randomScale);
if (channel.randomScale) channel.scaleSeed = EditorGUILayout.IntField("Seed", channel.scaleSeed);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
if (channel.randomScale)
{
EditorGUI.indentLevel++;
EditorGUIUtility.labelWidth = 120f;
channel.uniformRandomScale = EditorGUILayout.Toggle("Uniform", channel.uniformRandomScale);
EditorGUIUtility.labelWidth = 0f;
EditorGUI.indentLevel--;
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("UV Coordinates", EditorStyles.boldLabel);
channel.uvOffset = EditorGUILayout.Vector2Field("UV Offset", channel.uvOffset);
channel.uvScale = EditorGUILayout.Vector2Field("UV Scale", channel.uvScale);
//Override
EditorGUILayout.Space();
EditorGUILayout.LabelField("Override", EditorStyles.boldLabel);
channel.overrideNormal = EditorGUILayout.Toggle("Normal", channel.overrideNormal);
if(channel.overrideNormal) channel.customNormal = EditorGUILayout.Vector3Field("Normal", channel.customNormal);
if (channel.type == SplineMesh.Channel.Type.Extrude)
{
channel.overrideUVs = (SplineMesh.Channel.UVOverride)EditorGUILayout.EnumPopup("UVs", channel.overrideUVs);
if(channel.overrideUVs != SplineMesh.Channel.UVOverride.None)
{
}
}
channel.overrideMaterialID = EditorGUILayout.Toggle("Material IDs", channel.overrideMaterialID);
if (channel.overrideMaterialID) channel.targetMaterialID = EditorGUILayout.IntField("Target ID", channel.targetMaterialID);
if (scaleModifierEditor != null)
{
EditorGUILayout.LabelField("Scale Regions", EditorStyles.boldLabel);
scaleModifierEditor.DrawInspector();
}
EditorGUI.indentLevel--;
GUILayout.EndVertical();
return labelRect.Contains(Event.current.mousePosition);
}
void OnDuplicateMesh(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.DuplicateMesh(link.index);
}
void OnDeleteMesh(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.RemoveMesh(link.index);
Repaint();
}
void OnMoveMeshUp(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.SwapMeshes(link.index, link.index - 1);
Repaint();
}
void OnMoveMeshDown(object mesh)
{
MeshLink link = (MeshLink)mesh;
link.channel.SwapMeshes(link.index, link.index + 1);
Repaint();
}
void MeshRow(SplineMesh.Channel channel, int index)
{
SplineMesh.Channel.MeshDefinition definition = channel.GetMesh(index);
EditorGUILayout.BeginHorizontal();
GUILayout.Space(15);
if(definition.mesh == null) GUILayout.Box("NULL", EditorStyles.helpBox, GUILayout.MinWidth(200));
else GUILayout.Box(definition.mesh.name, EditorStyles.helpBox, GUILayout.MinWidth(200));
EditorGUILayout.EndHorizontal();
Rect rect = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)){
if(Event.current.button == 0)
{
definitionWindow = EditorWindow.GetWindow<MeshDefinitionWindow>(true);
definitionWindow.Init((SplineMesh)target, definition);
}
if(Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Duplicate"), false, OnDuplicateMesh, new MeshLink(index, channel));
if (index == 0) menu.AddDisabledItem(new GUIContent("Move Up"));
else menu.AddItem(new GUIContent("Move Up"), false, OnMoveMeshUp, new MeshLink(index, channel));
if (index == channel.GetMeshCount() - 1) menu.AddDisabledItem(new GUIContent("Move Down"));
else menu.AddItem(new GUIContent("Move Down"), false, OnMoveMeshDown, new MeshLink(index, channel));
menu.AddSeparator("");
menu.AddItem(new GUIContent("Delete"), false, OnDeleteMesh, new MeshLink(index, channel));
menu.ShowAsContext();
}
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if (definitionWindow != null) definitionWindow.Close();
}
internal class MeshLink
{
internal int index = 0;
internal SplineMesh.Channel channel;
internal MeshLink(int i, SplineMesh.Channel l)
{
index = i;
channel = l;
}
}
public class MeshDefinitionWindow : EditorWindow
{
internal SplineMesh.Channel.MeshDefinition definition = null;
internal SplineMesh extrude = null;
internal void Init(SplineMesh e, SplineMesh.Channel.MeshDefinition d)
{
minSize = new Vector2(482, 180);
extrude = e;
definition = d;
if(definition.mesh != null) titleContent = new GUIContent("Configure " + definition.mesh.name);
else titleContent = new GUIContent("Configure Mesh");
}
private void OnGUI()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Geometry", EditorStyles.boldLabel);
definition.mesh = (Mesh)EditorGUILayout.ObjectField(definition.mesh, typeof(Mesh), true);
definition.mirror = (SplineMesh.Channel.MeshDefinition.MirrorMethod)EditorGUILayout.EnumPopup("Mirror", definition.mirror);
definition.offset = EditorGUILayout.Vector3Field("Offset", definition.offset);
definition.rotation = EditorGUILayout.Vector3Field("Rotation", definition.rotation);
definition.scale = EditorGUILayout.Vector3Field("Scale", definition.scale);
var spacing = definition.spacing;
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 40;
EditorGUILayout.LabelField("Spacing");
spacing.front = EditorGUILayout.FloatField("Front", spacing.front);
spacing.back = EditorGUILayout.FloatField("Back", spacing.back);
definition.spacing = spacing;
EditorGUILayout.EndHorizontal();
EditorGUIUtility.labelWidth = 0;
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Faces", EditorStyles.boldLabel);
definition.doubleSided = EditorGUILayout.Toggle("Double sided", definition.doubleSided);
if (definition.doubleSided) definition.flipFaces = false;
else definition.flipFaces = EditorGUILayout.Toggle("Flip Faces", definition.flipFaces);
definition.removeInnerFaces = EditorGUILayout.Toggle("Remove Inner Faces", definition.removeInnerFaces);
EditorGUILayout.LabelField("UVs", EditorStyles.boldLabel);
definition.uvOffset = EditorGUILayout.Vector2Field("UV Offset", definition.uvOffset);
definition.uvScale = EditorGUILayout.Vector2Field("UV Scale", definition.uvScale);
definition.uvRotation = EditorGUILayout.Slider("UV Rotation", definition.uvRotation, -180f, 180f);
definition.vertexGroupingMargin = EditorGUILayout.FloatField("Vertex Grouping Margin", definition.vertexGroupingMargin);
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
if (GUI.changed) extrude.Rebuild();
}
}
}
}