@@ -93,118 +93,153 @@ public static Color GetNodeInspectorBackgroundColor()
9393
9494 #region Node Color
9595
96- public static Color GetNodeInspectorTextColor ( )
96+ private static readonly IReadOnlyDictionary < Type , Color32 > _specialTypeColors = new Dictionary < Type , Color32 > ( )
9797 {
98- return EditorGUIUtility . isProSkin
99- ? new Color32 ( 255 , 255 , 255 , 255 )
100- : // dark
101- new Color32 ( 0 , 0 , 0 , 255 ) ; // light
102- }
98+ { typeof ( AnimationClipPlayable ) , new Color32 ( 0 , 255 , 100 , 255 ) } ,
99+ { typeof ( AnimationMixerPlayable ) , new Color32 ( 0 , 190 , 255 , 255 ) } ,
100+ { typeof ( AnimationLayerMixerPlayable ) , new Color32 ( 0 , 115 , 255 , 255 ) } ,
101+ { typeof ( AnimatorControllerPlayable ) , new Color32 ( 255 , 145 , 0 , 255 ) } ,
102+ { typeof ( AnimationScriptPlayable ) , new Color32 ( 0 , 255 , 145 , 255 ) } ,
103+ { typeof ( AnimationPlayableOutput ) , new Color32 ( 200 , 255 , 80 , 255 ) } ,
104+
105+ { typeof ( ScriptPlayableOutput ) , new Color32 ( 55 , 255 , 20 , 255 ) } ,
106+
107+ { typeof ( AudioClipPlayable ) , new Color32 ( 255 , 190 , 19 , 255 ) } ,
108+ { typeof ( AudioMixerPlayable ) , new Color32 ( 170 , 255 , 0 , 255 ) } ,
109+ { typeof ( AudioPlayableOutput ) , new Color32 ( 255 , 135 , 0 , 255 ) } ,
110+ } ;
103111
104- public static Color GetNodeInvalidColor ( )
105- {
106- return Color . red ;
107- }
108112
109- // (0, ?, 255, 255) for PlayableOutput nodes
110- public static Color GetPlayableOutputNodeColor ( this ref PlayableOutput playableOutput )
113+ public static readonly byte MinRGB = 50 ;
114+ public static readonly byte MaxRGB = 200 ;
115+
116+ public static Color32 GetNodeColor ( Type playableType )
111117 {
112- if ( playableOutput . IsPlayableOutputOfType < AnimationPlayableOutput > ( ) )
118+ if ( ! _specialTypeColors . TryGetValue ( playableType , out var color ) &&
119+ ! _colorCache . TryGetValue ( playableType , out color ) )
113120 {
114- return new Color32 ( 0 , 240 , 255 , 255 ) ;
121+ color = GenerateRandomPlayableColor ( _colorCache . Values ) ;
115122 }
116123
117- if ( playableOutput . IsPlayableOutputOfType < AudioPlayableOutput > ( ) )
118- {
119- return new Color32 ( 0 , 190 , 255 , 255 ) ;
120- }
124+ _colorCache [ playableType ] = color ;
121125
122- if ( playableOutput . IsPlayableOutputOfType < ScriptPlayableOutput > ( ) )
123- {
124- return new Color32 ( 0 , 140 , 255 , 255 ) ;
125- }
126-
127- return GetRandomColorForType ( playableOutput . GetPlayableOutputType ( ) ) ;
126+ return color ;
128127 }
129128
130- // (0, 255, ?, 255) for Playable nodes
131- public static Color GetPlayableNodeColor ( this ref Playable playable )
129+ public static Color32 GenerateRandomPlayableColor ( IEnumerable < Color32 > existedColors )
132130 {
133- if ( playable . IsPlayableOfType < AnimationClipPlayable > ( ) )
131+ while ( true )
134132 {
135- return new Color32 ( 0 , 255 , 25 , 255 ) ;
133+ Color32 color ;
134+ var leader = URandom . Range ( 0 , 3 ) ;
135+ switch ( leader )
136+ {
137+ case 0 : // R
138+ color = new Color32
139+ {
140+ r = MaxRGB ,
141+ g = ( byte ) URandom . Range ( MinRGB , MaxRGB + 1 ) ,
142+ b = ( byte ) URandom . Range ( MinRGB , MaxRGB + 1 ) ,
143+ a = 255 ,
144+ } ;
145+ break ;
146+ case 1 : // G
147+ color = new Color32
148+ {
149+ r = ( byte ) URandom . Range ( MinRGB , MaxRGB + 1 ) ,
150+ g = MaxRGB ,
151+ b = ( byte ) URandom . Range ( MinRGB , MaxRGB + 1 ) ,
152+ a = 255 ,
153+ } ;
154+ break ;
155+
156+ case 2 : // B
157+ color = new Color32
158+ {
159+ r = ( byte ) URandom . Range ( MinRGB , MaxRGB + 1 ) ,
160+ g = ( byte ) URandom . Range ( MinRGB , MaxRGB + 1 ) ,
161+ b = MaxRGB ,
162+ a = 255 ,
163+ } ;
164+ break ;
165+
166+ default : throw new IndexOutOfRangeException ( ) ;
167+ }
168+
169+ if ( IsCloseRGB ( color ) )
170+ {
171+ continue ;
172+ }
173+
174+ var hasSimilarColor = false ;
175+ if ( existedColors != null )
176+ {
177+ // ReSharper disable once PossibleMultipleEnumeration
178+ foreach ( var existedColor in existedColors )
179+ {
180+ if ( IsSimilarColor ( existedColor , color ) )
181+ {
182+ hasSimilarColor = true ;
183+ break ;
184+ }
185+ }
186+ }
187+
188+ if ( ! hasSimilarColor )
189+ {
190+ return color ;
191+ }
136192 }
193+ }
137194
138- // Audio
139- if ( playable . IsPlayableOfType < AudioClipPlayable > ( ) )
140- {
141- return new Color32 ( 0 , 255 , 60 , 255 ) ;
142- }
195+ public static bool IsCloseRGB ( Color32 color , byte threshold = 50 )
196+ {
197+ var rg = Mathf . Abs ( color . r - color . g ) ;
198+ var gb = Mathf . Abs ( color . g - color . b ) ;
199+ var br = Mathf . Abs ( color . b - color . r ) ;
143200
144- if ( playable . IsPlayableOfType < AnimationMixerPlayable > ( ) )
145- {
146- return new Color32 ( 0 , 255 , 95 , 255 ) ;
147- }
201+ return rg <= threshold && gb <= threshold && br <= threshold ;
202+ }
148203
149- // Audio
150- if ( playable . IsPlayableOfType < AudioMixerPlayable > ( ) )
151- {
152- return new Color32 ( 0 , 255 , 130 , 255 ) ;
153- }
204+ public static bool IsSimilarColor ( Color32 a , Color32 b , byte threshold = 10 )
205+ {
206+ return Mathf . Abs ( a . r - b . r ) < threshold &&
207+ Mathf . Abs ( a . g - b . g ) < threshold &&
208+ Mathf . Abs ( a . b - b . b ) < threshold &&
209+ Mathf . Abs ( a . a - b . a ) < threshold ;
210+ }
154211
155- if ( playable . IsPlayableOfType < AnimationLayerMixerPlayable > ( ) )
156- {
157- return new Color32 ( 0 , 255 , 165 , 255 ) ;
158- }
212+ public static Color GetNodeInspectorTextColor ( )
213+ {
214+ return EditorGUIUtility . isProSkin
215+ ? new Color32 ( 255 , 255 , 255 , 255 )
216+ : // dark
217+ new Color32 ( 0 , 0 , 0 , 255 ) ; // light
218+ }
159219
160- if ( playable . IsPlayableOfType < AnimationScriptPlayable > ( ) )
161- {
162- return new Color32 ( 0 , 255 , 200 , 255 ) ;
163- }
220+ public static Color GetNodeInvalidColor ( )
221+ {
222+ return Color . red ;
223+ }
164224
165- if ( playable . IsPlayableOfType < AnimatorControllerPlayable > ( ) )
166- {
167- return new Color32 ( 0 , 255 , 235 , 255 ) ;
168- }
225+ public static Color GetPlayableOutputNodeColor ( this PlayableOutput playableOutput )
226+ {
227+ return GetNodeColor ( playableOutput . GetPlayableOutputType ( ) ) ;
228+ }
169229
170- return GetRandomColorForType ( playable . GetPlayableType ( ) ) ;
230+ public static Color GetPlayableNodeColor ( this Playable playable )
231+ {
232+ return GetNodeColor ( playable . GetPlayableType ( ) ) ;
171233 }
172234
173235 #endregion
174236
175237
176- // reserve (0, ?, 255, 255) for PlayableOutput nodes
177- // reserve (0, 255, ?, 255) for Playable nodes
178- public static readonly IReadOnlyList < Color32 > ColorPool = new Color32 [ ]
179- {
180- new Color32 ( 255 , 0 , 255 , 255 ) , new Color32 ( 255 , 0 , 153 , 255 ) ,
181- new Color32 ( 153 , 255 , 0 , 255 ) , new Color32 ( 204 , 255 , 0 , 255 ) ,
182- new Color32 ( 255 , 255 , 0 , 255 ) , new Color32 ( 255 , 204 , 0 , 255 ) ,
183- new Color32 ( 255 , 153 , 0 , 255 ) , new Color32 ( 255 , 102 , 0 , 255 ) ,
184- new Color32 ( 153 , 204 , 255 , 255 ) , new Color32 ( 153 , 255 , 102 , 255 ) ,
185- new Color32 ( 153 , 255 , 153 , 255 ) , new Color32 ( 153 , 255 , 204 , 255 ) ,
186- new Color32 ( 204 , 255 , 102 , 255 ) , new Color32 ( 204 , 255 , 255 , 255 ) ,
187- } ;
188-
189238 private static readonly Dictionary < Type , Color32 > _colorCache = new Dictionary < Type , Color32 > ( ) ;
190239
191-
192- public static Color GetRandomColorForType ( this Type type )
193- {
194- if ( _colorCache . TryGetValue ( type , out var color ) )
195- {
196- return color ;
197- }
198-
199- color = ColorPool [ URandom . Range ( 0 , ColorPool . Count ) ] ;
200- _colorCache [ type ] = color ;
201-
202- return color ;
203- }
204-
205240 public static void ClearGlobalCache ( )
206241 {
207242 _colorCache . Clear ( ) ;
208243 }
209244 }
210- }
245+ }
0 commit comments