using UnityEngine; using UnityEditor; namespace UDE_HAND_INTERACTION { [CustomEditor(typeof(InteractableSurface))] public class InteractableSurfaceEditor : Editor { private const int NUM_SEGMENTS = 10; private const float FADE_DISTANCE = 1f; private static readonly Color Color = new Color(0f, 1f, 1f, 0.1f); private static float Interval => FADE_DISTANCE / NUM_SEGMENTS; private InteractableSurface surface; private void OnEnable() { surface = target as InteractableSurface; } public void OnSceneGUI() { Draw(surface); } public override void OnInspectorGUI() { DrawDefaultInspector(); switch((int)surface.surfaceType) { case 0: //surface.Position = EditorGUILayout.Vector3Field("Position", surface.Position); surface._width = EditorGUILayout.FloatField("Width", surface._width); surface._height = EditorGUILayout.FloatField("Height", surface._height); break; case 1: surface._radius = EditorGUILayout.FloatField("Radius", surface._radius); break; case 2: break; } } public static void Draw(InteractableSurface surface) { Vector3 origin = surface.transform.position; if (SceneView.lastActiveSceneView?.camera != null) { Transform camTransform = SceneView.lastActiveSceneView.camera.transform; if (surface.ClosestSurfacePoint(camTransform.position, out SurfaceHit hit, 0)) { Vector3 hitDelta = PoseManager.Delta(surface.transform, new Pose(hit.Point, surface.transform.rotation)).position; hitDelta.x = Mathf.RoundToInt(hitDelta.x / Interval) * Interval; hitDelta.y = Mathf.RoundToInt(hitDelta.y / Interval) * Interval; hitDelta.z = 0f; origin = PoseManager.Multiply(surface.transform.GetPose(), new Pose(hitDelta, Quaternion.identity)).position; } } if((int)surface.surfaceType == 1) { Handles.color = Color.green; Vector3 ArcDir = Quaternion.AngleAxis(0, surface.Normal) * Vector3.ProjectOnPlane(origin, surface.Normal).normalized; Handles.DrawWireArc(origin, surface.Normal, ArcDir, 360, surface._radius); for (int i = 0; i < 12; ++i) { Vector3 Cur_dir = Quaternion.AngleAxis(i * 30, surface.Normal) * ArcDir; Handles.DrawLine(origin, origin + Cur_dir * surface._radius); } } else if((int)surface.surfaceType == 0) { if (!surface.GetLocalBounds(surface.transform, out Bounds localBounds)) { return; } Handles.color = Color.green; Handles.matrix = surface.transform.localToWorldMatrix; Handles.DrawWireCube(localBounds.center, localBounds.size); Vector3 BondSizeX = new(localBounds.size.x / 5, 0, 0); Vector3 BondSizeY = new(0, localBounds.size.y / 5, 0); for (int i = 0; i < 5; ++i) { Handles.DrawLine(localBounds.center - (localBounds.size / 2) + i * BondSizeY, localBounds.center + (localBounds.size / 2) - i * BondSizeX); Handles.DrawLine(localBounds.center - (localBounds.size / 2) + i * BondSizeX, localBounds.center + (localBounds.size / 2) - i * BondSizeY); } } else { DrawLines(origin, surface.Normal, surface.transform.up, Color); DrawLines(origin, surface.Normal, -surface.transform.up, Color); DrawLines(origin, surface.Normal, surface.transform.right, Color); DrawLines(origin, surface.Normal, -surface.transform.right, Color); } } private static void DrawLines(in Vector3 origin, in Vector3 normal, in Vector3 direction, in Color baseColor) { Color prevColor = Handles.color; Color color = baseColor; Vector3 offsetOrigin = origin; for (int i = 0; i < NUM_SEGMENTS; ++i) { Handles.color = color; Vector3 cross = Vector3.Cross(normal, direction).normalized; float interval = Interval; for (int j = -NUM_SEGMENTS; j < NUM_SEGMENTS; ++j) { float horizStart = interval * j; float horizEnd = horizStart + interval; Vector3 start = offsetOrigin + cross * horizStart; Vector3 end = offsetOrigin + cross * horizEnd; color.a = 1f - Mathf.Abs((float)j / NUM_SEGMENTS); color.a *= 1f - ((float)i / NUM_SEGMENTS); color.a *= color.a; Handles.color = color; Handles.DrawLine(start, end); } offsetOrigin += direction * interval; color = baseColor; } Handles.color = prevColor; } } }