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+ private SerializedProperty useLocalTangentPoints ;
32+
33+ private BezierDataProvider bezierData ;
34+
35+ private int selectedHandleIndex = - 1 ;
36+
37+ protected override void OnEnable ( )
38+ {
39+ base . OnEnable ( ) ;
40+
41+ controlPoints = serializedObject . FindProperty ( "controlPoints" ) ;
42+ useLocalTangentPoints = serializedObject . FindProperty ( "useLocalTangentPoints" ) ;
43+
44+ bezierData = ( BezierDataProvider ) target ;
45+ }
46+
47+ public override void OnInspectorGUI ( )
48+ {
49+ base . OnInspectorGUI ( ) ;
50+ serializedObject . Update ( ) ;
51+
52+ // We always draw line points for bezier.
53+ DrawLinePoints = true ;
54+
55+ EditorGUILayout . PropertyField ( controlPoints , true ) ;
56+ EditorGUILayout . PropertyField ( useLocalTangentPoints ) ;
57+
58+ serializedObject . ApplyModifiedProperties ( ) ;
59+ }
60+
61+ protected override void OnSceneGUI ( )
62+ {
63+ base . OnSceneGUI ( ) ;
64+
65+ // We skip the first point as it should always remain at the GameObject's local origin (Pose.ZeroIdentity)
66+ for ( int i = 0 ; i < 4 ; i ++ )
67+ {
68+ bool isTangentHandle = i % 3 != 0 ;
69+
70+ serializedObject . Update ( ) ;
71+
72+ bool isLastPoint = i == 3 ;
73+
74+ var controlPointPosition = LineData . GetPoint ( i ) ;
75+ var controlPointProperty = controlPoints . FindPropertyRelative ( "point" + ( i + 1 ) ) ;
76+
77+ // Draw our tangent lines
78+ Handles . color = Color . gray ;
79+ if ( i == 0 )
80+ {
81+ Handles . DrawLine ( LineData . GetPoint ( 0 ) , LineData . GetPoint ( 1 ) ) ;
82+ }
83+ else if ( ! isTangentHandle )
84+ {
85+ Handles . DrawLine ( LineData . GetPoint ( i ) , LineData . GetPoint ( i - 1 ) ) ;
86+
87+ if ( ! isLastPoint )
88+ {
89+ Handles . DrawLine ( LineData . GetPoint ( i ) , LineData . GetPoint ( i + 1 ) ) ;
90+ }
91+ }
92+
93+ Handles . color = isTangentHandle ? Color . white : Color . green ;
94+ float handleSize = HandleUtility . GetHandleSize ( controlPointPosition ) ;
95+
96+ if ( Handles . Button ( controlPointPosition , Quaternion . identity , handleSize * HandleSizeModifier , handleSize * PickSizeModifier , Handles . DotHandleCap ) )
97+ {
98+ selectedHandleIndex = i ;
99+ }
100+
101+ // Draw our handles
102+ if ( Tools . current == Tool . Move && selectedHandleIndex == i )
103+ {
104+ EditorGUI . BeginChangeCheck ( ) ;
105+
106+ var newTargetPosition = Handles . PositionHandle ( controlPointPosition , Quaternion . identity ) ;
107+
108+ if ( EditorGUI . EndChangeCheck ( ) )
109+ {
110+ Undo . RecordObject ( LineData , "Change Bezier Point Position" ) ;
111+ LineData . SetPoint ( i , newTargetPosition ) ;
112+ }
113+ }
114+
115+ serializedObject . ApplyModifiedProperties ( ) ;
116+ }
117+ }
118+
119+ private void DrawControlPointElement ( Rect rect , int index , bool isActive , bool isFocused )
120+ {
121+ bool lastMode = EditorGUIUtility . wideMode ;
122+ EditorGUIUtility . wideMode = true ;
123+
124+ var lastLabelWidth = EditorGUIUtility . labelWidth ;
125+ EditorGUIUtility . labelWidth = 88f ;
126+
127+ var property = controlPoints . GetArrayElementAtIndex ( index ) ;
128+ var fieldHeight = EditorGUIUtility . singleLineHeight * 0.5f ;
129+ var labelRect = new Rect ( rect . x - 8f , rect . y + fieldHeight * 2 , rect . width , EditorGUIUtility . singleLineHeight ) ;
130+ var positionRect = new Rect ( rect . x , rect . y + fieldHeight , rect . width , EditorGUIUtility . singleLineHeight ) ;
131+ var rotationRect = new Rect ( rect . x , rect . y + fieldHeight * 3 , rect . width , EditorGUIUtility . singleLineHeight ) ;
132+
133+ EditorGUI . LabelField ( labelRect , $ "{ index + 1 } ") ;
134+
135+ EditorGUI . indentLevel ++ ;
136+
137+ GUI . enabled = index != 0 ;
138+
139+ EditorGUI . BeginChangeCheck ( ) ;
140+ EditorGUI . PropertyField ( positionRect , property . FindPropertyRelative ( "position" ) , PositionContent ) ;
141+ bool hasPositionChanged = EditorGUI . EndChangeCheck ( ) ;
142+
143+ if ( hasPositionChanged )
144+ {
145+ EditorUtility . SetDirty ( target ) ;
146+ }
147+
148+ GUI . enabled = true ;
149+ EditorGUI . indentLevel -- ;
150+ EditorGUIUtility . wideMode = lastMode ;
151+ EditorGUIUtility . labelWidth = lastLabelWidth ;
152+ }
153+ }
154+ }
0 commit comments