1+ // Copyright (c) Microsoft Corporation. All rights reserved.
2+ // Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+ using Microsoft . MixedReality . Toolkit . Core . Definitions . Utilities ;
5+ using Microsoft . MixedReality . Toolkit . Core . Utilities . Lines . DataProviders ;
6+ using System . Collections . Generic ;
7+ using UnityEditor ;
8+ using UnityEditorInternal ;
9+ using UnityEngine ;
10+
11+ namespace Microsoft . MixedReality . Toolkit . Core . Inspectors . Utilities . Lines
12+ {
13+ [ CustomEditor ( typeof ( BezierDataProvider ) ) ]
14+ public class BezierDataProviderInspector : BaseLineDataProviderInspector
15+ {
16+ private const float OverlappingPointThreshold = 0.015f ;
17+ private const float HandleSizeModifier = 0.04f ;
18+ private const float PickSizeModifier = 0.06f ;
19+
20+ private static readonly HashSet < int > OverlappingPointIndexes = new HashSet < int > ( ) ;
21+
22+ private static readonly Vector2 ControlPointButtonSize = new Vector2 ( 16 , 16 ) ;
23+ private static readonly Vector2 LeftControlPointPositionOffset = Vector2 . left * 12 ;
24+ private static readonly Vector2 RightControlPointPositionOffset = Vector2 . right * 24 ;
25+
26+ private static readonly Vector2 ControlPointButtonHandleOffset = Vector3 . up * 24 ;
27+
28+ private static readonly GUIContent PositionContent = new GUIContent ( "Position" ) ;
29+
30+ private SerializedProperty controlPoints ;
31+
32+ private BezierDataProvider bezierData ;
33+
34+ private int selectedHandleIndex = - 1 ;
35+
36+ protected override void OnEnable ( )
37+ {
38+ base . OnEnable ( ) ;
39+
40+ controlPoints = serializedObject . FindProperty ( "controlPoints" ) ;
41+
42+ bezierData = ( BezierDataProvider ) target ;
43+ }
44+
45+ public override void OnInspectorGUI ( )
46+ {
47+ base . OnInspectorGUI ( ) ;
48+ serializedObject . Update ( ) ;
49+
50+ // We always draw line points for bezier.
51+ DrawLinePoints = true ;
52+
53+ EditorGUILayout . PropertyField ( controlPoints , true ) ;
54+
55+ serializedObject . ApplyModifiedProperties ( ) ;
56+ }
57+
58+ protected override void OnSceneGUI ( )
59+ {
60+ base . OnSceneGUI ( ) ;
61+
62+ // We skip the first point as it should always remain at the GameObject's local origin (Pose.ZeroIdentity)
63+ for ( int i = 0 ; i < 4 ; i ++ )
64+ {
65+ bool isTangentHandle = i % 3 != 0 ;
66+
67+ serializedObject . Update ( ) ;
68+
69+ bool isLastPoint = i == 3 ;
70+
71+ var controlPointPosition = LineData . GetPoint ( i ) ;
72+ var controlPointProperty = controlPoints . FindPropertyRelative ( "point" + ( i + 1 ) ) ;
73+
74+ // Draw our tangent lines
75+ Handles . color = Color . gray ;
76+ if ( i == 0 )
77+ {
78+ Handles . DrawLine ( LineData . GetPoint ( 0 ) , LineData . GetPoint ( 1 ) ) ;
79+ }
80+ else if ( ! isTangentHandle )
81+ {
82+ Handles . DrawLine ( LineData . GetPoint ( i ) , LineData . GetPoint ( i - 1 ) ) ;
83+
84+ if ( ! isLastPoint )
85+ {
86+ Handles . DrawLine ( LineData . GetPoint ( i ) , LineData . GetPoint ( i + 1 ) ) ;
87+ }
88+ }
89+
90+ Handles . color = isTangentHandle ? Color . white : Color . green ;
91+ float handleSize = HandleUtility . GetHandleSize ( controlPointPosition ) ;
92+
93+ if ( Handles . Button ( controlPointPosition , Quaternion . identity , handleSize * HandleSizeModifier , handleSize * PickSizeModifier , Handles . DotHandleCap ) )
94+ {
95+ selectedHandleIndex = i ;
96+ }
97+
98+ // Draw our handles
99+ if ( Tools . current == Tool . Move && selectedHandleIndex == i )
100+ {
101+ EditorGUI . BeginChangeCheck ( ) ;
102+
103+ var newTargetPosition = Handles . PositionHandle ( controlPointPosition , Quaternion . identity ) ;
104+
105+ if ( EditorGUI . EndChangeCheck ( ) )
106+ {
107+ Undo . RecordObject ( LineData , "Change Bezier Point Position" ) ;
108+ LineData . SetPoint ( i , newTargetPosition ) ;
109+ }
110+ }
111+
112+ serializedObject . ApplyModifiedProperties ( ) ;
113+ }
114+ }
115+
116+ private void DrawControlPointElement ( Rect rect , int index , bool isActive , bool isFocused )
117+ {
118+ bool lastMode = EditorGUIUtility . wideMode ;
119+ EditorGUIUtility . wideMode = true ;
120+
121+ var lastLabelWidth = EditorGUIUtility . labelWidth ;
122+ EditorGUIUtility . labelWidth = 88f ;
123+
124+ var property = controlPoints . GetArrayElementAtIndex ( index ) ;
125+ var fieldHeight = EditorGUIUtility . singleLineHeight * 0.5f ;
126+ var labelRect = new Rect ( rect . x - 8f , rect . y + fieldHeight * 2 , rect . width , EditorGUIUtility . singleLineHeight ) ;
127+ var positionRect = new Rect ( rect . x , rect . y + fieldHeight , rect . width , EditorGUIUtility . singleLineHeight ) ;
128+ var rotationRect = new Rect ( rect . x , rect . y + fieldHeight * 3 , rect . width , EditorGUIUtility . singleLineHeight ) ;
129+
130+ EditorGUI . LabelField ( labelRect , $ "{ index + 1 } ") ;
131+
132+ EditorGUI . indentLevel ++ ;
133+
134+ GUI . enabled = index != 0 ;
135+
136+ EditorGUI . BeginChangeCheck ( ) ;
137+ EditorGUI . PropertyField ( positionRect , property . FindPropertyRelative ( "position" ) , PositionContent ) ;
138+ bool hasPositionChanged = EditorGUI . EndChangeCheck ( ) ;
139+
140+ if ( hasPositionChanged )
141+ {
142+ EditorUtility . SetDirty ( target ) ;
143+ }
144+
145+ GUI . enabled = true ;
146+ EditorGUI . indentLevel -- ;
147+ EditorGUIUtility . wideMode = lastMode ;
148+ EditorGUIUtility . labelWidth = lastLabelWidth ;
149+ }
150+ }
151+ }
0 commit comments