33using KSPShaderTools ;
44using System ;
55using System . Collections . Generic ;
6+ using System . Linq ;
67using System . Reflection ;
78using UnityEngine ;
89
@@ -23,6 +24,14 @@ public class LazyPainterIMGUI : MonoBehaviour
2324 private int windowID ;
2425 public static int windowWidth = 340 ;
2526
27+ // Shouldn't have these magic numbers, but can't be bothered. Will do Unity UI version later.
28+ // Most of these have to exist because of using GUI.DrawTexture
29+ public static float colourSlotWidth = 89 ;
30+ public static float colourSlotSpacing = 16 ;
31+ public static float presetTextFieldWidthConstant = 52 ;
32+ public static float hexStringWidth = 70 ;
33+ public static float centeredLabelHeightConstant = 46 ;
34+
2635 // Styles.
2736 private static GUIStyle boxStyle ;
2837 private static GUIStyle questionStyle ;
@@ -31,6 +40,7 @@ public class LazyPainterIMGUI : MonoBehaviour
3140 private static GUIStyle buttonStyle ;
3241 private static GUIStyle textBoxStyle ;
3342 private static GUIStyle topButtonStyle ;
43+ private static GUIStyle centeredLabelStyle ;
3444
3545 // Scroll.
3646 private Vector2 presetColorScrollPos ;
@@ -46,9 +56,20 @@ public class LazyPainterIMGUI : MonoBehaviour
4656 private static Texture2D [ ] colourTextures ;
4757
4858 // HSV or RGB.
49- private int colourMode = 0 ;
50- private string [ ] colourModes = new string [ ] { "HSV" , "RGB" } ;
51- private bool UseRGB => colourMode == 1 ;
59+ public enum ColourMode
60+ {
61+ HSV = 0 ,
62+ RGB = 1 ,
63+ Hex = 2 ,
64+ }
65+
66+ private ColourMode colourMode = ColourMode . HSV ;
67+ private string [ ] colourModes = new string [ ] { "HSV" , "RGB" , "Hex" } ;
68+
69+ // Hex field preset lookup.
70+ private string hexLookupLast = default ;
71+ private RecoloringDataPreset hexLookupMatch = default ;
72+ private bool hexLookupMatched = false ;
5273
5374 // Preset browser.
5475 private static int groupIndex = 0 ;
@@ -185,7 +206,7 @@ public void DrawGUI()
185206 Mathf . Clamp ( windowRect . position . y , 0 , Screen . height - windowRect . height )
186207 ) ;
187208
188- windowRect = GUILayout . Window ( windowID , windowRect , FillWindow , windowTitle , GUILayout . Height ( 1 ) , GUILayout . Width ( windowWidth ) ) ;
209+ windowRect = GUILayout . Window ( windowID , windowRect , FillWindow , windowTitle , GUILayout . Height ( 1 ) , GUILayout . Width ( windowWidth ) , GUILayout . MaxWidth ( windowWidth ) ) ;
189210 clickBlocker . UpdateRect ( windowRect ) ;
190211 }
191212
@@ -311,9 +332,6 @@ private void Warning()
311332 GUILayout . EndHorizontal ( ) ;
312333 }
313334
314- public static float colourSlotWidth = 89 ;
315- public static float colourSlotSpacing = 16 ;
316-
317335 private void MainSection ( )
318336 {
319337 // Selection count.
@@ -382,35 +400,39 @@ private void MainSection()
382400 GUI . DrawTexture ( rect , colourTextures [ i ] , ScaleMode . StretchToFill , true ) ;
383401 }
384402
385-
386403 // Colour slider section.
387404
388405 bool update = false ;
389406
390407 GUILayout . BeginHorizontal ( ) ;
391- GUILayout . Space ( 100 ) ;
392- colourMode = GUILayout . SelectionGrid ( colourMode , colourModes , 2 ) ;
393- GUILayout . Space ( 100 ) ;
408+ GUILayout . FlexibleSpace ( ) ;
409+ colourMode = ( ColourMode ) GUILayout . SelectionGrid ( ( int ) colourMode , colourModes , colourModes . Length ) ;
410+ GUILayout . FlexibleSpace ( ) ;
394411 GUILayout . EndHorizontal ( ) ;
395412
396413 ModalColour editingColour = lp . colourData [ lp . editingColour ] ;
397414 float scalar = display255 ? 255 : 1 ;
398415
399- if ( ! UseRGB )
416+ GUILayout . Space ( 10 ) ;
417+ switch ( colourMode )
400418 {
401- HSV hsv = editingColour . HSV ;
402- SliderSetting ( "Hue" , ref hsv . hue , 0 , 1f , ref update , scalar ) ;
403- SliderSetting ( "Saturation" , ref hsv . saturation , 0 , 1f , ref update , scalar ) ;
404- SliderSetting ( "Value" , ref hsv . value , 0 , 1f , ref update , scalar ) ;
405- if ( update ) editingColour . HSV = hsv ;
406- }
407- else
408- {
409- Color colour = editingColour . Colour ;
410- SliderSetting ( "Red" , ref colour . r , 0 , 1f , ref update , scalar ) ;
411- SliderSetting ( "Green" , ref colour . g , 0 , 1f , ref update , scalar ) ;
412- SliderSetting ( "Blue" , ref colour . b , 0 , 1f , ref update , scalar ) ;
413- if ( update ) editingColour . Colour = colour ;
419+ case ColourMode . HSV :
420+ HSV hsv = editingColour . HSV ;
421+ SliderSetting ( "Hue" , ref hsv . hue , 0 , 1f , ref update , scalar ) ;
422+ SliderSetting ( "Saturation" , ref hsv . saturation , 0 , 1f , ref update , scalar ) ;
423+ SliderSetting ( "Value" , ref hsv . value , 0 , 1f , ref update , scalar ) ;
424+ if ( update ) editingColour . HSV = hsv ;
425+ break ;
426+ case ColourMode . RGB :
427+ Color colour = editingColour . Colour ;
428+ SliderSetting ( "Red" , ref colour . r , 0 , 1f , ref update , scalar ) ;
429+ SliderSetting ( "Green" , ref colour . g , 0 , 1f , ref update , scalar ) ;
430+ SliderSetting ( "Blue" , ref colour . b , 0 , 1f , ref update , scalar ) ;
431+ if ( update ) editingColour . Colour = colour ;
432+ break ;
433+ case ColourMode . Hex :
434+ HexInput ( ref editingColour , ref update ) ;
435+ break ;
414436 }
415437
416438 // Material slider section.
@@ -433,16 +455,96 @@ private void MainSection()
433455 if ( showPresetColours )
434456 DrawPresetSection ( ref update , ref editingColour ) ;
435457
458+ lp . colourData [ lp . editingColour ] = editingColour ;
459+
436460 if ( update )
437461 {
438- lp . colourData [ lp . editingColour ] = editingColour ;
439462 UpdateColourBoxes ( ) ;
440463 lp . ApplyRecolouring ( ) ;
441464 }
442465
443466 GUILayout . EndVertical ( ) ;
444467 }
445468
469+ private void HexInput ( ref ModalColour editingColour , ref bool update )
470+ {
471+ string hex = editingColour . Hex ;
472+ string oldHex = hex ;
473+
474+ // Find match.
475+
476+ if ( ! string . IsNullOrEmpty ( hex ) && ! editingColour . hexValid && hex . FirstOrDefault ( ) != '#' && hex != hexLookupLast )
477+ {
478+ List < RecoloringDataPreset > matches = PresetColor . getColorList ( ) . Where ( p => p . title . IndexOf ( hex , StringComparison . OrdinalIgnoreCase ) == 0 ) . ToList ( ) ;
479+ hexLookupLast = hex ;
480+
481+ if ( matches . Count == 1 )
482+ {
483+ hexLookupMatch = matches . First ( ) ;
484+ hexLookupMatched = true ;
485+ }
486+ else
487+ hexLookupMatched = false ;
488+ }
489+
490+ // Display info.
491+
492+ bool applyMatch = false ;
493+ if ( hexLookupMatched )
494+ {
495+ CenteredLabel ( $ "<color=#cccccc>Press enter for <b>{ hexLookupMatch . title } </b>.</color>", centeredLabelHeightConstant ) ;
496+
497+ if ( Event . current . Equals ( Event . KeyboardEvent ( "return" ) ) )
498+ {
499+ lp . EnableRecolouring ( true , false ) ;
500+
501+ hex = "#" + ColorUtility . ToHtmlStringRGB ( hexLookupMatch . color ) ;
502+ editingColour = hexLookupMatch . getRecoloringData ( ) ;
503+ update = true ;
504+ applyMatch = true ;
505+ }
506+ }
507+ else
508+ {
509+ CenteredLabel ( $ "<color=#b3b3b3>Enter a valid hex code or begin typing\n the name of a colour preset.</color>", centeredLabelHeightConstant ) ;
510+ }
511+
512+ // Display text field.
513+
514+ GUILayout . BeginHorizontal ( ) ;
515+ GUILayout . FlexibleSpace ( ) ;
516+
517+ if ( ! editingColour . hexValid )
518+ GUI . color = Color . red ;
519+
520+ Color oldGUIColour = GUI . color ;
521+
522+ hex = GUILayout . TextField ( hex , textBoxStyle , GUILayout . MinWidth ( 70 ) ) ;
523+ GUI . color = oldGUIColour ;
524+
525+ if ( applyMatch )
526+ try
527+ {
528+ TextEditor editor = ( TextEditor ) GUIUtility . GetStateObject ( typeof ( TextEditor ) , GUIUtility . keyboardControl ) ;
529+ editor . selectIndex = hex . Length ;
530+ editor . cursorIndex = hex . Length ;
531+ }
532+ catch { }
533+
534+ GUILayout . FlexibleSpace ( ) ;
535+ GUILayout . EndHorizontal ( ) ;
536+
537+ // Update hex.
538+
539+ if ( ! update )
540+ {
541+ editingColour . Hex = hex ;
542+
543+ if ( hex != oldHex && editingColour . hexValid )
544+ update = true ;
545+ }
546+ }
547+
446548 private void LoadingScreen ( )
447549 {
448550 GUILayout . BeginVertical ( boxStyle ) ;
@@ -454,11 +556,16 @@ private void LoadingScreen()
454556 GUILayout . EndVertical ( ) ;
455557 }
456558
457- private void CenteredLabel ( string text )
559+ private void CenteredLabel ( string text , float height = 0 )
458560 {
459561 GUILayout . BeginHorizontal ( ) ;
460562 GUILayout . FlexibleSpace ( ) ;
461- GUILayout . Label ( text ) ;
563+
564+ if ( height == 0 )
565+ GUILayout . Label ( text , centeredLabelStyle ) ;
566+ else
567+ GUILayout . Label ( text , centeredLabelStyle , GUILayout . Height ( height ) ) ;
568+
462569 GUILayout . FlexibleSpace ( ) ;
463570 GUILayout . EndHorizontal ( ) ;
464571 }
@@ -507,6 +614,11 @@ private void InitStyles()
507614 {
508615 alignment = TextAnchor . MiddleCenter
509616 } ;
617+
618+ centeredLabelStyle = new GUIStyle ( GUI . skin . label )
619+ {
620+ alignment = TextAnchor . MiddleCenter
621+ } ;
510622 }
511623
512624 public void Refresh ( )
@@ -578,7 +690,8 @@ private void DrawPresetSection(ref bool update, ref ModalColour editingColour)
578690
579691 if ( groupName == "Custom" )
580692 {
581- presetSaveString = GUILayout . TextField ( presetSaveString ) ;
693+ float width = windowWidth - 190 - presetTextFieldWidthConstant ;
694+ presetSaveString = GUILayout . TextField ( presetSaveString , GUILayout . MaxWidth ( width ) ) ;
582695 }
583696 else
584697 {
0 commit comments