2
0

ColorPicker.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System;
  4. using BansheeEngine;
  5. namespace BansheeEditor
  6. {
  7. /** @addtogroup Windows
  8. * @{
  9. */
  10. /// <summary>
  11. /// A color picker window that allows the user to select from a gamut of colors.
  12. /// </summary>
  13. public class ColorPicker : ModalWindow
  14. {
  15. private const int SliderIndividualWidth = 150;
  16. private const int SliderIndividualHeight = 15;
  17. private const int ColorBoxWidth = 200;
  18. private const int ColorBoxHeight = 200;
  19. private const int SliderSideWidth = 40;
  20. private const int SliderSideHeight = 200;
  21. private float colRed, colGreen, colBlue;
  22. private float colHue, colSaturation, colValue;
  23. private float colAlpha = 1.0f;
  24. private ColorSlider1DHorz sliderR, sliderG, sliderB, sliderA;
  25. private ColorSlider2D colorBox;
  26. private ColorSlider1DVert sideSlider;
  27. private ColorBoxMode colorBoxMode = ColorBoxMode.BG_R;
  28. private SliderMode sliderMode = SliderMode.HSV;
  29. private GUIColorField guiColor;
  30. private GUITexture guiSlider2DTex;
  31. private GUITexture guiSliderVertTex;
  32. private GUITexture guiSliderRHorzTex;
  33. private GUITexture guiSliderGHorzTex;
  34. private GUITexture guiSliderBHorzTex;
  35. private GUITexture guiSliderAHorzTex;
  36. private GUIButton guiColorBoxBtn;
  37. private GUIButton guiColorModeBtn;
  38. private GUISliderV guiSliderVert;
  39. private GUISliderH guiSliderRHorz;
  40. private GUISliderH guiSliderGHorz;
  41. private GUISliderH guiSliderBHorz;
  42. private GUISliderH guiSliderAHorz;
  43. private GUITexture guiSlider2DHandle;
  44. private GUILabel guiLabelR;
  45. private GUILabel guiLabelG;
  46. private GUILabel guiLabelB;
  47. private GUILabel guiLabelA;
  48. private GUIIntField guiInputR;
  49. private GUIIntField guiInputG;
  50. private GUIIntField guiInputB;
  51. private GUIIntField guiInputA;
  52. private GUIButton guiOK;
  53. private GUIButton guiCancel;
  54. private Action<bool, Color> closedCallback;
  55. /// <summary>
  56. /// Determines color gamut shown in the color box.
  57. /// </summary>
  58. public enum ColorBoxMode
  59. {
  60. BG_R,
  61. BR_G,
  62. RG_B,
  63. SV_H,
  64. HV_S,
  65. HS_V
  66. }
  67. /// <summary>
  68. /// Determines color gamut shown in the horizontal sliders.
  69. /// </summary>
  70. public enum SliderMode
  71. {
  72. RGB,
  73. HSV
  74. }
  75. /// <summary>
  76. /// Returns currently selected color as RGBA values.
  77. /// </summary>
  78. public Color SelectedColor
  79. {
  80. get
  81. {
  82. return new Color(colRed, colGreen, colBlue, colAlpha);
  83. }
  84. }
  85. /// <summary>
  86. /// Shows the color picker window.
  87. /// </summary>
  88. /// <param name="closedCallback">Optional callback to trigger when the user selects a color or cancels out
  89. /// of the dialog.</param>
  90. /// <returns>A. instance of the color picker window.</returns>
  91. public static ColorPicker Show(Action<bool, Color> closedCallback = null)
  92. {
  93. ColorPicker picker = new ColorPicker(Color.Black, closedCallback);
  94. return picker;
  95. }
  96. /// <summary>
  97. /// Shows the color picker window and sets the initial color to show.
  98. /// </summary>
  99. /// <param name="color">Initial color to display.</param>
  100. /// <param name="closedCallback">Optional callback to trigger when the user selects a color or cancels out
  101. /// of the dialog.</param>
  102. /// <returns>A. instance of the color picker window.</returns>
  103. public static ColorPicker Show(Color color, Action<bool, Color> closedCallback = null)
  104. {
  105. ColorPicker picker = new ColorPicker(color, closedCallback);
  106. return picker;
  107. }
  108. /// <summary>
  109. /// Constructs a new color picker window.
  110. /// </summary>
  111. /// <param name="color">Initial color to display.</param>
  112. /// <param name="closedCallback">Optional callback to trigger when the user selects a color or cancels out
  113. /// of the dialog.</param>
  114. protected ColorPicker(Color color, Action<bool, Color> closedCallback = null)
  115. : base(false)
  116. {
  117. Title = new LocEdString("Color Picker");
  118. Width = 270;
  119. Height = 400;
  120. colRed = color.r;
  121. colGreen = color.g;
  122. colBlue = color.b;
  123. colAlpha = color.a;
  124. RGBToHSV();
  125. this.closedCallback = closedCallback;
  126. }
  127. private void OnInitialize()
  128. {
  129. guiColor = new GUIColorField("", GUIOption.FixedWidth(100));
  130. guiSlider2DTex = new GUITexture(null, GUIOption.FixedHeight(ColorBoxHeight), GUIOption.FixedWidth(ColorBoxWidth));
  131. guiSliderVertTex = new GUITexture(null, GUIOption.FixedHeight(SliderSideHeight), GUIOption.FixedWidth(SliderSideWidth));
  132. guiSliderRHorzTex = new GUITexture(null, GUIOption.FixedHeight(SliderIndividualHeight));
  133. guiSliderGHorzTex = new GUITexture(null, GUIOption.FixedHeight(SliderIndividualHeight));
  134. guiSliderBHorzTex = new GUITexture(null, GUIOption.FixedHeight(SliderIndividualHeight));
  135. guiSliderAHorzTex = new GUITexture(null, GUIOption.FixedHeight(SliderIndividualHeight));
  136. guiColorBoxBtn = new GUIButton(colorBoxMode.ToString());
  137. guiColorModeBtn = new GUIButton(sliderMode.ToString());
  138. guiSliderVert = new GUISliderV(EditorStyles.ColorSliderVert);
  139. guiSliderRHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
  140. guiSliderGHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
  141. guiSliderBHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
  142. guiSliderAHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
  143. guiSlider2DHandle = new GUITexture(null, EditorStyles.ColorSlider2DHandle);
  144. guiLabelR = new GUILabel(new LocEdString("R"));
  145. guiLabelG = new GUILabel(new LocEdString("G"));
  146. guiLabelB = new GUILabel(new LocEdString("B"));
  147. guiLabelA = new GUILabel(new LocEdString("A"));
  148. guiInputR = new GUIIntField();
  149. guiInputG = new GUIIntField();
  150. guiInputB = new GUIIntField();
  151. guiInputA = new GUIIntField();
  152. guiOK = new GUIButton(new LocEdString("OK"));
  153. guiCancel = new GUIButton(new LocEdString("Cancel"));
  154. guiColorBoxBtn.OnClick += OnColorBoxModeChanged;
  155. guiColorModeBtn.OnClick += OnSliderModeChanged;
  156. guiSliderVert.OnChanged += OnSliderVertChanged;
  157. guiSliderRHorz.OnChanged += OnSliderRHorzChanged;
  158. guiSliderGHorz.OnChanged += OnSliderGHorzChanged;
  159. guiSliderBHorz.OnChanged += OnSliderBHorzChanged;
  160. guiSliderAHorz.OnChanged += OnSliderAHorzChanged;
  161. guiInputR.OnChanged += OnInputRChanged;
  162. guiInputG.OnChanged += OnInputGChanged;
  163. guiInputB.OnChanged += OnInputBChanged;
  164. guiInputA.OnChanged += OnInputAChanged;
  165. guiOK.OnClick += OnOK;
  166. guiCancel.OnClick += OnCancel;
  167. GUIPanel mainPanel = GUI.AddPanel(0);
  168. GUILayout v0 = mainPanel.AddLayoutY();
  169. v0.AddSpace(5);
  170. GUILayout h0 = v0.AddLayoutX();
  171. h0.AddSpace(10);
  172. h0.AddElement(guiColor);
  173. h0.AddFlexibleSpace();
  174. h0.AddElement(guiColorBoxBtn);
  175. h0.AddElement(guiColorModeBtn);
  176. h0.AddSpace(10);
  177. v0.AddSpace(10);
  178. GUILayout h1 = v0.AddLayoutX();
  179. h1.AddSpace(10);
  180. h1.AddElement(guiSlider2DTex);
  181. h1.AddFlexibleSpace();
  182. h1.AddElement(guiSliderVertTex);
  183. h1.AddSpace(10);
  184. v0.AddSpace(10);
  185. GUILayout h2 = v0.AddLayoutX();
  186. h2.AddSpace(10);
  187. h2.AddElement(guiLabelR);
  188. h2.AddFlexibleSpace();
  189. h2.AddElement(guiSliderRHorzTex);
  190. h2.AddFlexibleSpace();
  191. h2.AddElement(guiInputR);
  192. h2.AddSpace(10);
  193. v0.AddSpace(5);
  194. GUILayout h3 = v0.AddLayoutX();
  195. h3.AddSpace(10);
  196. h3.AddElement(guiLabelG);
  197. h3.AddFlexibleSpace();
  198. h3.AddElement(guiSliderGHorzTex);
  199. h3.AddFlexibleSpace();
  200. h3.AddElement(guiInputG);
  201. h3.AddSpace(10);
  202. v0.AddSpace(5);
  203. GUILayout h4 = v0.AddLayoutX();
  204. h4.AddSpace(10);
  205. h4.AddElement(guiLabelB);
  206. h4.AddFlexibleSpace();
  207. h4.AddElement(guiSliderBHorzTex);
  208. h4.AddFlexibleSpace();
  209. h4.AddElement(guiInputB);
  210. h4.AddSpace(10);
  211. v0.AddSpace(5);
  212. GUILayout h5 = v0.AddLayoutX();
  213. h5.AddSpace(10);
  214. h5.AddElement(guiLabelA);
  215. h5.AddFlexibleSpace();
  216. h5.AddElement(guiSliderAHorzTex);
  217. h5.AddFlexibleSpace();
  218. h5.AddElement(guiInputA);
  219. h5.AddSpace(10);
  220. v0.AddSpace(10);
  221. GUILayout h6 = v0.AddLayoutX();
  222. h6.AddFlexibleSpace();
  223. h6.AddElement(guiOK);
  224. h6.AddSpace(10);
  225. h6.AddElement(guiCancel);
  226. h6.AddFlexibleSpace();
  227. v0.AddSpace(5);
  228. GUIPanel overlay = GUI.AddPanel(-1);
  229. overlay.SetWidth(Width);
  230. overlay.SetHeight(Height);
  231. overlay.AddElement(guiSliderVert);
  232. overlay.AddElement(guiSliderRHorz);
  233. overlay.AddElement(guiSliderGHorz);
  234. overlay.AddElement(guiSliderBHorz);
  235. overlay.AddElement(guiSliderAHorz);
  236. overlay.AddElement(guiSlider2DHandle);
  237. colorBox = new ColorSlider2D(guiSlider2DTex, guiSlider2DHandle, ColorBoxWidth, ColorBoxHeight);
  238. sideSlider = new ColorSlider1DVert(guiSliderVertTex, guiSliderVert, SliderSideWidth, SliderSideHeight);
  239. sliderR = new ColorSlider1DHorz(guiSliderRHorzTex, guiSliderRHorz, SliderIndividualWidth, SliderIndividualHeight);
  240. sliderG = new ColorSlider1DHorz(guiSliderGHorzTex, guiSliderGHorz, SliderIndividualWidth, SliderIndividualHeight);
  241. sliderB = new ColorSlider1DHorz(guiSliderBHorzTex, guiSliderBHorz, SliderIndividualWidth, SliderIndividualHeight);
  242. sliderA = new ColorSlider1DHorz(guiSliderAHorzTex, guiSliderAHorz, SliderIndividualWidth, SliderIndividualHeight);
  243. colorBox.OnValueChanged += OnColorBoxValueChanged;
  244. Color startA = new Color(0, 0, 0, 1);
  245. Color stepA = new Color(1, 1, 1, 0);
  246. sliderA.UpdateTexture(startA, stepA, false);
  247. guiInputA.SetRange(0, 255);
  248. guiInputA.Value = 255;
  249. guiSliderAHorz.Percent = 1.0f;
  250. guiColor.Value = SelectedColor;
  251. UpdateInputBoxValues();
  252. Update2DSliderValues();
  253. Update1DSliderValues();
  254. UpdateSliderMode();
  255. Update2DSliderTextures();
  256. Update1DSliderTextures();
  257. }
  258. private void OnEditorUpdate()
  259. {
  260. Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
  261. colorBox.UpdateInput(windowPos);
  262. }
  263. /// <summary>
  264. /// Fills a 2D area with colors using the provided starting point and gradients.
  265. /// </summary>
  266. /// <param name="width">Width of the area to fill.</param>
  267. /// <param name="height">Height of the area to fill.</param>
  268. /// <param name="colors">Array to contain the output. Must be of
  269. /// <paramref name="width"/>*<paramref name="height"/> size.</param>
  270. /// <param name="start">Initial color in the top-left corner of the area.</param>
  271. /// <param name="rightGradient">Gradient towards which the colors increase to the right of the area.</param>
  272. /// <param name="downGradient">Gradient towards which the colors increase to the bottom of the area.</param>
  273. private static void FillArea(int width, int height, Color[] colors, Color start, Color rightGradient, Color downGradient)
  274. {
  275. Color rightDelta = new Color(0, 0, 0, 0);
  276. if (width > 1)
  277. rightDelta = rightGradient / (width - 1);
  278. Color downDelta = new Color(0, 0, 0, 0);
  279. if (height > 1)
  280. downDelta = downGradient / (height - 1);
  281. Color verticalColor = start;
  282. for (int y = 0; y < height; y++)
  283. {
  284. int rowIdx = (height - y - 1) * width;
  285. Color currentColor = verticalColor;
  286. for (int x = 0; x < width; x++)
  287. {
  288. colors[rowIdx + x] = currentColor;
  289. currentColor += rightDelta;
  290. }
  291. verticalColor += downDelta;
  292. }
  293. }
  294. /// <summary>
  295. /// Converts the currently selected color from HSV to RGB color space.
  296. /// </summary>
  297. void HSVToRGB()
  298. {
  299. Color hsv = new Color(colHue, colSaturation, colValue);
  300. Color rgb = Color.HSV2RGB(hsv);
  301. colRed = rgb.r;
  302. colGreen = rgb.g;
  303. colBlue = rgb.b;
  304. }
  305. /// <summary>
  306. /// Converts the currently selected color from RGB to HSV color space.
  307. /// </summary>
  308. void RGBToHSV()
  309. {
  310. Color rgb = new Color(colRed, colGreen, colBlue);
  311. Color hsv = Color.RGB2HSV(rgb);
  312. colHue = hsv.r;
  313. colSaturation = hsv.g;
  314. colValue = hsv.b;
  315. }
  316. /// <summary>
  317. /// Triggered when the user selects a new mode for the color box, changing the gamut of colors displayed in the box.
  318. /// </summary>
  319. void OnColorBoxModeChanged()
  320. {
  321. int maxModes = Enum.GetNames(colorBoxMode.GetType()).Length;
  322. colorBoxMode = (ColorBoxMode)(((int)colorBoxMode + 1) % maxModes);
  323. guiColorBoxBtn.SetContent(colorBoxMode.ToString());
  324. Update2DSliderTextures();
  325. Update2DSliderValues();
  326. }
  327. /// <summary>
  328. /// Triggered when the user selects a new mode for the side slider, changing the gamut of colors displayed in the
  329. /// slider.
  330. /// </summary>
  331. void OnSliderModeChanged()
  332. {
  333. int maxModes = Enum.GetNames(sliderMode.GetType()).Length;
  334. sliderMode = (SliderMode)(((int)sliderMode + 1) % maxModes);
  335. UpdateSliderMode();
  336. guiColorModeBtn.SetContent(sliderMode.ToString());
  337. UpdateInputBoxValues();
  338. Update1DSliderTextures();
  339. Update1DSliderValues();
  340. }
  341. /// <summary>
  342. /// Triggered when the user selects a color in the color box.
  343. /// </summary>
  344. /// <param name="value">Location on the color box that was selected.</param>
  345. void OnColorBoxValueChanged(Vector2 value)
  346. {
  347. switch (colorBoxMode)
  348. {
  349. case ColorBoxMode.BG_R:
  350. colBlue = value.x;
  351. colGreen = value.y;
  352. RGBToHSV();
  353. break;
  354. case ColorBoxMode.BR_G:
  355. colBlue = value.x;
  356. colRed = value.y;
  357. RGBToHSV();
  358. break;
  359. case ColorBoxMode.RG_B:
  360. colRed = value.x;
  361. colGreen = value.y;
  362. RGBToHSV();
  363. break;
  364. case ColorBoxMode.SV_H:
  365. colSaturation = value.x;
  366. colValue = value.y;
  367. HSVToRGB();
  368. break;
  369. case ColorBoxMode.HV_S:
  370. colHue = value.x;
  371. colValue = value.y;
  372. HSVToRGB();
  373. break;
  374. case ColorBoxMode.HS_V:
  375. colHue = value.x;
  376. colSaturation = value.y;
  377. HSVToRGB();
  378. break;
  379. }
  380. guiColor.Value = SelectedColor;
  381. UpdateInputBoxValues();
  382. Update1DSliderTextures();
  383. Update1DSliderValues();
  384. UpdateSideSliderTexture();
  385. Vector2 xy;
  386. float z;
  387. GetColorBoxValues(out xy, out z);
  388. guiSliderVert.Percent = 1.0f - z;
  389. }
  390. /// <summary>
  391. /// Triggered when the user moves the side slider.
  392. /// </summary>
  393. /// <param name="percent">New value of the slider.</param>
  394. void OnSliderVertChanged(float percent)
  395. {
  396. percent = 1.0f - percent;
  397. switch (colorBoxMode)
  398. {
  399. case ColorBoxMode.BG_R:
  400. colRed = percent;
  401. RGBToHSV();
  402. break;
  403. case ColorBoxMode.BR_G:
  404. colGreen = percent;
  405. RGBToHSV();
  406. break;
  407. case ColorBoxMode.RG_B:
  408. colBlue = percent;
  409. RGBToHSV();
  410. break;
  411. case ColorBoxMode.SV_H:
  412. colHue = percent;
  413. HSVToRGB();
  414. break;
  415. case ColorBoxMode.HV_S:
  416. colSaturation = percent;
  417. HSVToRGB();
  418. break;
  419. case ColorBoxMode.HS_V:
  420. colValue = percent;
  421. HSVToRGB();
  422. break;
  423. }
  424. guiColor.Value = SelectedColor;
  425. UpdateInputBoxValues();
  426. Update1DSliderTextures();
  427. Update1DSliderValues();
  428. }
  429. /// <summary>
  430. /// Triggered when the user moves the horizontal Red/Hue slider.
  431. /// </summary>
  432. /// <param name="percent">New value of the slider.</param>
  433. void OnSliderRHorzChanged(float percent)
  434. {
  435. bool isHSV = sliderMode == SliderMode.HSV;
  436. if (isHSV)
  437. {
  438. colHue = percent;
  439. HSVToRGB();
  440. }
  441. else
  442. {
  443. colRed = percent;
  444. RGBToHSV();
  445. }
  446. guiColor.Value = SelectedColor;
  447. UpdateInputBoxValues();
  448. Update2DSliderTextures();
  449. Update2DSliderValues();
  450. }
  451. /// <summary>
  452. /// Triggered when the user moves the horizontal Green/Saturation slider.
  453. /// </summary>
  454. /// <param name="percent">New value of the slider.</param>
  455. void OnSliderGHorzChanged(float percent)
  456. {
  457. bool isHSV = sliderMode == SliderMode.HSV;
  458. if (isHSV)
  459. {
  460. colSaturation = percent;
  461. HSVToRGB();
  462. }
  463. else
  464. {
  465. colGreen = percent;
  466. RGBToHSV();
  467. }
  468. guiColor.Value = SelectedColor;
  469. UpdateInputBoxValues();
  470. Update2DSliderTextures();
  471. Update2DSliderValues();
  472. }
  473. /// <summary>
  474. /// Triggered when the user moves the horizontal Blue/Value slider.
  475. /// </summary>
  476. /// <param name="percent">New value of the slider.</param>
  477. void OnSliderBHorzChanged(float percent)
  478. {
  479. bool isHSV = sliderMode == SliderMode.HSV;
  480. if (isHSV)
  481. {
  482. colValue = percent;
  483. HSVToRGB();
  484. }
  485. else
  486. {
  487. colBlue = percent;
  488. RGBToHSV();
  489. }
  490. guiColor.Value = SelectedColor;
  491. UpdateInputBoxValues();
  492. Update2DSliderTextures();
  493. Update2DSliderValues();
  494. }
  495. /// <summary>
  496. /// Triggered when the user moves the horizontal alpha slider.
  497. /// </summary>
  498. /// <param name="percent">New value of the slider.</param>
  499. void OnSliderAHorzChanged(float percent)
  500. {
  501. colAlpha = percent;
  502. guiColor.Value = SelectedColor;
  503. guiInputA.Value = MathEx.RoundToInt(colAlpha * 255.0f);
  504. }
  505. /// <summary>
  506. /// Triggered when the user inputs new value in the Red/Hue input box.
  507. /// </summary>
  508. /// <param name="value">New value in the input box.</param>
  509. void OnInputRChanged(int value)
  510. {
  511. bool isHSV = sliderMode == SliderMode.HSV;
  512. if (isHSV)
  513. {
  514. colHue = value/359.0f;
  515. HSVToRGB();
  516. }
  517. else
  518. {
  519. colRed = value/255.0f;
  520. RGBToHSV();
  521. }
  522. guiColor.Value = SelectedColor;
  523. Update1DSliderValues();
  524. Update2DSliderTextures();
  525. Update2DSliderValues();
  526. }
  527. /// <summary>
  528. /// Triggered when the user inputs new value in the Green/Saturation input box.
  529. /// </summary>
  530. /// <param name="value">New value in the input box.</param>
  531. void OnInputGChanged(int value)
  532. {
  533. bool isHSV = sliderMode == SliderMode.HSV;
  534. if (isHSV)
  535. {
  536. colSaturation = value / 255.0f;
  537. HSVToRGB();
  538. }
  539. else
  540. {
  541. colGreen = value / 255.0f;
  542. RGBToHSV();
  543. }
  544. guiColor.Value = SelectedColor;
  545. Update1DSliderValues();
  546. Update2DSliderTextures();
  547. Update2DSliderValues();
  548. }
  549. /// <summary>
  550. /// Triggered when the user inputs new value in the Blue/Value input box.
  551. /// </summary>
  552. /// <param name="value">New value in the input box.</param>
  553. void OnInputBChanged(int value)
  554. {
  555. bool isHSV = sliderMode == SliderMode.HSV;
  556. if (isHSV)
  557. {
  558. colValue = value / 255.0f;
  559. HSVToRGB();
  560. }
  561. else
  562. {
  563. colBlue = value / 255.0f;
  564. RGBToHSV();
  565. }
  566. guiColor.Value = SelectedColor;
  567. Update1DSliderValues();
  568. Update2DSliderTextures();
  569. Update2DSliderValues();
  570. }
  571. /// <summary>
  572. /// Triggered when the user inputs new value in the alpha input box.
  573. /// </summary>
  574. /// <param name="value">New value in the input box.</param>
  575. void OnInputAChanged(int value)
  576. {
  577. colAlpha = value/255.0f;
  578. guiColor.Value = SelectedColor;
  579. guiSliderAHorz.Percent = colAlpha;
  580. }
  581. /// <summary>
  582. /// Triggered when the user selects a color and closes the dialog.
  583. /// </summary>
  584. void OnOK()
  585. {
  586. if (closedCallback != null)
  587. closedCallback(true, SelectedColor);
  588. Close();
  589. }
  590. /// <summary>
  591. /// Triggered when the user cancels color selection and closes the dialog.
  592. /// </summary>
  593. void OnCancel()
  594. {
  595. if (closedCallback != null)
  596. closedCallback(false, SelectedColor);
  597. Close();
  598. }
  599. /// <summary>
  600. /// Updates Red/Green/Blue or Hue/Saturation/Value labels and input box ranges depending on currently active mode.
  601. /// </summary>
  602. void UpdateSliderMode()
  603. {
  604. if (sliderMode == SliderMode.RGB)
  605. {
  606. guiLabelR.SetContent(new LocEdString("R"));
  607. guiLabelG.SetContent(new LocEdString("G"));
  608. guiLabelB.SetContent(new LocEdString("B"));
  609. guiInputR.SetRange(0, 255);
  610. guiInputG.SetRange(0, 255);
  611. guiInputB.SetRange(0, 255);
  612. }
  613. else
  614. {
  615. guiLabelR.SetContent(new LocEdString("H"));
  616. guiLabelG.SetContent(new LocEdString("S"));
  617. guiLabelB.SetContent(new LocEdString("V"));
  618. guiInputR.SetRange(0, 359);
  619. guiInputG.SetRange(0, 255);
  620. guiInputB.SetRange(0, 255);
  621. }
  622. }
  623. /// <summary>
  624. /// Updates Red/Green/Blue or Hue/Saturation/Value input boxes with currently selected color.
  625. /// </summary>
  626. void UpdateInputBoxValues()
  627. {
  628. bool isHSV = sliderMode == SliderMode.HSV;
  629. if (isHSV)
  630. {
  631. guiInputR.Value = MathEx.RoundToInt(colHue * 359.0f);
  632. guiInputG.Value = MathEx.RoundToInt(colSaturation * 255.0f);
  633. guiInputB.Value = MathEx.RoundToInt(colValue * 255.0f);
  634. }
  635. else
  636. {
  637. guiInputR.Value = MathEx.RoundToInt(colRed * 255.0f);
  638. guiInputG.Value = MathEx.RoundToInt(colGreen * 255.0f);
  639. guiInputB.Value = MathEx.RoundToInt(colBlue * 255.0f);
  640. }
  641. }
  642. /// <summary>
  643. /// Updates Red/Green/Blue or Hue/Saturation/Value sliders with currently selected color.
  644. /// </summary>
  645. void Update1DSliderValues()
  646. {
  647. bool isHSV = sliderMode == SliderMode.HSV;
  648. if (isHSV)
  649. {
  650. guiSliderRHorz.Percent = colHue;
  651. guiSliderGHorz.Percent = colSaturation;
  652. guiSliderBHorz.Percent = colValue;
  653. }
  654. else
  655. {
  656. guiSliderRHorz.Percent = colRed;
  657. guiSliderGHorz.Percent = colGreen;
  658. guiSliderBHorz.Percent = colBlue;
  659. }
  660. }
  661. /// <summary>
  662. /// Returns the current color in the form of color box and side slider coordinates.
  663. /// </summary>
  664. /// <param name="xy">Coordinates on the color box the current color is located on.</param>
  665. /// <param name="z">Coordinates on the side slider the current color is located on.</param>
  666. void GetColorBoxValues(out Vector2 xy, out float z)
  667. {
  668. xy = Vector2.Zero;
  669. z = 0.0f;
  670. switch (colorBoxMode)
  671. {
  672. case ColorBoxMode.BG_R:
  673. xy.x = colBlue;
  674. xy.y = colGreen;
  675. z = colRed;
  676. break;
  677. case ColorBoxMode.BR_G:
  678. xy.x = colBlue;
  679. xy.y = colRed;
  680. z = colGreen;
  681. break;
  682. case ColorBoxMode.RG_B:
  683. xy.x = colRed;
  684. xy.y = colGreen;
  685. z = colBlue;
  686. break;
  687. case ColorBoxMode.SV_H:
  688. xy.x = colSaturation;
  689. xy.y = colValue;
  690. z = colHue;
  691. break;
  692. case ColorBoxMode.HV_S:
  693. xy.x = colHue;
  694. xy.y = colValue;
  695. z = colSaturation;
  696. break;
  697. case ColorBoxMode.HS_V:
  698. xy.x = colHue;
  699. xy.y = colSaturation;
  700. z = colValue;
  701. break;
  702. }
  703. }
  704. /// <summary>
  705. /// Updates values of the color box and side slider according to the current color.
  706. /// </summary>
  707. void Update2DSliderValues()
  708. {
  709. Vector2 xy = Vector2.Zero;
  710. float z = 0.0f;
  711. GetColorBoxValues(out xy, out z);
  712. colorBox.SetValue(xy);
  713. guiSliderVert.Percent = z;
  714. }
  715. /// <summary>
  716. /// Generates textures to display for all horizontal (RGB/HSV) sliders depending on active slider mode.
  717. /// </summary>
  718. void Update1DSliderTextures()
  719. {
  720. bool isHSV = sliderMode == SliderMode.HSV;
  721. if (isHSV)
  722. {
  723. Color startH = new Color(0, 1, 1);
  724. Color stepH = new Color(1, 0, 0, 0);
  725. sliderR.UpdateTexture(startH, stepH, true);
  726. Color startS = new Color(colHue, 0, MathEx.Max(colValue, 0.2f));
  727. Color stepS = new Color(0, 1, 0, 0);
  728. sliderG.UpdateTexture(startS, stepS, true);
  729. Color startV = new Color(colHue, colSaturation, 0);
  730. Color stepV = new Color(0, 0, 1, 0);
  731. sliderB.UpdateTexture(startV, stepV, true);
  732. }
  733. else
  734. {
  735. Color startR = new Color(0, colGreen, colBlue);
  736. Color stepR = new Color(1, 0, 0, 0);
  737. sliderR.UpdateTexture(startR, stepR, false);
  738. Color startG = new Color(colRed, 0, colBlue);
  739. Color stepG = new Color(0, 1, 0, 0);
  740. sliderG.UpdateTexture(startG, stepG, false);
  741. Color startB = new Color(colRed, colGreen, 0);
  742. Color stepB = new Color(0, 0, 1, 0);
  743. sliderB.UpdateTexture(startB, stepB, false);
  744. }
  745. }
  746. /// <summary>
  747. /// Generates a texture for the side slider depending on active color box mode.
  748. /// </summary>
  749. void UpdateSideSliderTexture()
  750. {
  751. switch (colorBoxMode)
  752. {
  753. case ColorBoxMode.BG_R:
  754. sideSlider.UpdateTexture(new Color(0, colGreen, colBlue, 1), new Color(1, 0, 0, 0), false);
  755. break;
  756. case ColorBoxMode.BR_G:
  757. sideSlider.UpdateTexture(new Color(colRed, 0, colBlue, 1), new Color(0, 1, 0, 0), false);
  758. break;
  759. case ColorBoxMode.RG_B:
  760. sideSlider.UpdateTexture(new Color(colRed, colGreen, 0, 1), new Color(0, 0, 1, 0), false);
  761. break;
  762. case ColorBoxMode.SV_H:
  763. sideSlider.UpdateTexture(new Color(0, 1, 1, 1), new Color(1, 0, 0, 0), true);
  764. break;
  765. case ColorBoxMode.HV_S:
  766. sideSlider.UpdateTexture(new Color(colHue, 0, MathEx.Max(colValue, 0.2f), 1), new Color(0, 1, 0, 0), true);
  767. break;
  768. case ColorBoxMode.HS_V:
  769. sideSlider.UpdateTexture(new Color(colHue, colSaturation, 0, 1), new Color(0, 0, 1, 0), true);
  770. break;
  771. }
  772. }
  773. /// <summary>
  774. /// Generates textures for the color box and the side slider depending on active color box mode.
  775. /// </summary>
  776. void Update2DSliderTextures()
  777. {
  778. UpdateSideSliderTexture();
  779. float[] valueLookup = new float[] { colRed, colGreen, colBlue, colHue, colSaturation, colValue };
  780. colorBox.UpdateTexture(colorBoxMode, valueLookup[(int)colorBoxMode]);
  781. }
  782. /// <summary>
  783. /// Manages GUI for a 1D horizontal slider (used RGB/HSV display).
  784. /// </summary>
  785. public class ColorSlider1DHorz
  786. {
  787. private const int SLIDER_X_OFFSET = 3;
  788. private const int SLIDER_Y_OFFSET = 5;
  789. private int width, height;
  790. private Texture2D texture;
  791. private SpriteTexture spriteTexture;
  792. private GUITexture guiTexture;
  793. private GUISliderH guiSlider;
  794. /// <summary>
  795. /// Creates a new horizontal slider.
  796. /// </summary>
  797. /// <param name="guiTexture">GUI element to display the slider color range on.</param>
  798. /// <param name="guiSlider">Slider rendered on top of the texture that may be moved by the user to select a
  799. /// color.</param>
  800. /// <param name="width">Width of the slider in pixels.</param>
  801. /// <param name="height">Height of the slider in pixels.</param>
  802. public ColorSlider1DHorz(GUITexture guiTexture, GUISliderH guiSlider, int width, int height)
  803. {
  804. this.width = width;
  805. this.height = height;
  806. this.guiTexture = guiTexture;
  807. this.guiSlider = guiSlider;
  808. texture = new Texture2D(width, height);
  809. spriteTexture = new SpriteTexture(texture);
  810. }
  811. /// <summary>
  812. /// Updates the displayed texture with specified color information.
  813. /// </summary>
  814. /// <param name="start">Initial color on the left of the slider.</param>
  815. /// <param name="step">Final color to the right of the slider.</param>
  816. /// <param name="isHSV">Determines are the provided colors in RGB or HSV space.</param>
  817. public void UpdateTexture(Color start, Color step, bool isHSV)
  818. {
  819. Color[] colors = new Color[width * height];
  820. FillArea(width, height, colors, start, step, new Color(0, 0, 0, 0));
  821. if (isHSV)
  822. {
  823. for (int i = 0; i < colors.Length; i++)
  824. colors[i] = Color.HSV2RGB(colors[i]);
  825. }
  826. texture.SetPixels(colors);
  827. guiTexture.SetTexture(spriteTexture);
  828. Rect2I sliderBounds = guiTexture.Bounds;
  829. sliderBounds.x -= SLIDER_X_OFFSET;
  830. sliderBounds.width += SLIDER_X_OFFSET * 2;
  831. sliderBounds.y -= SLIDER_Y_OFFSET;
  832. sliderBounds.height += SLIDER_Y_OFFSET;
  833. guiSlider.Bounds = sliderBounds;
  834. }
  835. }
  836. /// <summary>
  837. /// Manages GUI for a 1D vertical slider (side slider along with the color box).
  838. /// </summary>
  839. public class ColorSlider1DVert
  840. {
  841. private const int SLIDER_X_OFFSET = 5;
  842. private const int SLIDER_Y_OFFSET = 3;
  843. private int width, height;
  844. private Texture2D texture;
  845. private SpriteTexture spriteTexture;
  846. private GUITexture guiTexture;
  847. private GUISliderV guiSlider;
  848. /// <summary>
  849. /// Creates a new vertical slider.
  850. /// </summary>
  851. /// <param name="guiTexture">GUI element to display the slider color range on.</param>
  852. /// <param name="guiSlider">Slider rendered on top of the texture that may be moved by the user to select a
  853. /// color.</param>
  854. /// <param name="width">Width of the slider in pixels.</param>
  855. /// <param name="height">Height of the slider in pixels.</param>
  856. public ColorSlider1DVert(GUITexture guiTexture, GUISliderV guiSlider, int width, int height)
  857. {
  858. this.width = width;
  859. this.height = height;
  860. this.guiTexture = guiTexture;
  861. this.guiSlider = guiSlider;
  862. texture = new Texture2D(width, height);
  863. spriteTexture = new SpriteTexture(texture);
  864. }
  865. /// <summary>
  866. /// Updates the displayed texture with specified color information.
  867. /// </summary>
  868. /// <param name="start">Initial color on the top of the slider.</param>
  869. /// <param name="step">Final color to the bottom of the slider.</param>
  870. /// <param name="isHSV">Determines are the provided colors in RGB or HSV space.</param>
  871. public void UpdateTexture(Color start, Color step, bool isHSV)
  872. {
  873. Color[] colors = new Color[width * height];
  874. FillArea(width, height, colors, start, new Color(0, 0, 0, 0), step);
  875. if (isHSV)
  876. {
  877. for (int i = 0; i < colors.Length; i++)
  878. colors[i] = Color.HSV2RGB(colors[i]);
  879. }
  880. texture.SetPixels(colors);
  881. guiTexture.SetTexture(spriteTexture);
  882. Rect2I sliderBounds = guiTexture.Bounds;
  883. sliderBounds.x -= SLIDER_X_OFFSET;
  884. sliderBounds.width += SLIDER_X_OFFSET;
  885. sliderBounds.y -= SLIDER_Y_OFFSET;
  886. sliderBounds.height += SLIDER_Y_OFFSET * 2;
  887. guiSlider.Bounds = sliderBounds;
  888. }
  889. }
  890. /// <summary>
  891. /// Manages GUI for a 2D color box, as well as manually handling color box input. Color box serves as a 2D sliders
  892. /// as you can portion of it to select a color.
  893. /// </summary>
  894. public class ColorSlider2D
  895. {
  896. private int width, height;
  897. private Texture2D texture;
  898. private SpriteTexture spriteTexture;
  899. private GUITexture guiTexture;
  900. private GUITexture guiSliderHandle;
  901. private Vector2 oldValue = new Vector2(-1, -1);
  902. public delegate void OnValueChangedDelegate(Vector2 value);
  903. public event OnValueChangedDelegate OnValueChanged;
  904. /// <summary>
  905. /// Creates a new color box.
  906. /// </summary>
  907. /// <param name="guiTexture">GUI element to display the 2D color range on.</param>
  908. /// <param name="guiSliderHandle">Texture to be used for displaying the position of the currently selected
  909. /// color.</param>
  910. /// <param name="width">Width of the slider in pixels.</param>
  911. /// <param name="height">Height of the slider in pixels.</param>
  912. public ColorSlider2D(GUITexture guiTexture, GUITexture guiSliderHandle, int width, int height)
  913. {
  914. this.width = width;
  915. this.height = height;
  916. this.guiTexture = guiTexture;
  917. this.guiSliderHandle = guiSliderHandle;
  918. texture = new Texture2D(width, height);
  919. spriteTexture = new SpriteTexture(texture);
  920. }
  921. /// <summary>
  922. /// Updates the texture displayed on the color box.
  923. /// </summary>
  924. /// <param name="mode">Mode determining the color gamut shown in the color box.</param>
  925. /// <param name="value">Value of the third component (normally retrieved from the separate side slider).</param>
  926. public void UpdateTexture(ColorBoxMode mode, float value)
  927. {
  928. Color[] colors = new Color[width * height];
  929. switch (mode)
  930. {
  931. case ColorBoxMode.BG_R:
  932. FillArea(width, height, colors, new Color(value, 0, 0, 1), new Color(0, 0, 1, 0), new Color(0, 1, 0, 0));
  933. break;
  934. case ColorBoxMode.BR_G:
  935. FillArea(width, height, colors, new Color(0, value, 0, 1), new Color(0, 0, 1, 0), new Color(1, 0, 0, 0));
  936. break;
  937. case ColorBoxMode.RG_B:
  938. FillArea(width, height, colors, new Color(0, 0, value, 1), new Color(1, 0, 0, 0), new Color(0, 1, 0, 0));
  939. break;
  940. case ColorBoxMode.SV_H:
  941. FillArea(width, height, colors, new Color(value, 0, 0, 1), new Color(0, 1, 0, 0), new Color(0, 0, 1, 0));
  942. for (int i = 0; i < colors.Length; i++)
  943. colors[i] = Color.HSV2RGB(colors[i]);
  944. break;
  945. case ColorBoxMode.HV_S:
  946. FillArea(width, height, colors, new Color(0, value, 0, 1), new Color(1, 0, 0, 0), new Color(0, 0, 1, 0));
  947. for (int i = 0; i < colors.Length; i++)
  948. colors[i] = Color.HSV2RGB(colors[i]);
  949. break;
  950. case ColorBoxMode.HS_V:
  951. FillArea(width, height, colors, new Color(0, 0, value, 1), new Color(1, 0, 0, 0), new Color(0, 1, 0, 0));
  952. for (int i = 0; i < colors.Length; i++)
  953. colors[i] = Color.HSV2RGB(colors[i]);
  954. break;
  955. }
  956. texture.SetPixels(colors);
  957. guiTexture.SetTexture(spriteTexture);
  958. }
  959. /// <summary>
  960. /// Handles input over the color box, moving the handle as needed.
  961. /// </summary>
  962. /// <param name="windowPos">Position of the pointer relative to the color picker window.</param>
  963. public void UpdateInput(Vector2I windowPos)
  964. {
  965. if (Input.IsPointerButtonHeld(PointerButton.Left))
  966. {
  967. Rect2I bounds = guiTexture.Bounds;
  968. if (bounds.Contains(windowPos))
  969. {
  970. Vector2 newValue = Vector2.Zero;
  971. newValue.x = (windowPos.x - bounds.x) / (float)bounds.width;
  972. newValue.y = 1.0f - (windowPos.y - bounds.y) / (float)bounds.height;
  973. SetValue(newValue);
  974. }
  975. }
  976. }
  977. /// <summary>
  978. /// Moves the handle to a specific location on the color box and selects that color.
  979. /// </summary>
  980. /// <param name="value">Coordinates relative to the color box.</param>
  981. public void SetValue(Vector2 value)
  982. {
  983. Vector2 pos = value;
  984. pos.y = 1.0f - pos.y;
  985. if (oldValue == value)
  986. return;
  987. Rect2I handleBounds = guiSliderHandle.Bounds;
  988. Rect2I boxBounds = guiTexture.Bounds;
  989. handleBounds.x = boxBounds.x + MathEx.RoundToInt(pos.x * boxBounds.width) - handleBounds.width / 2;
  990. handleBounds.y = boxBounds.y + MathEx.RoundToInt(pos.y * boxBounds.height) - handleBounds.height / 2;
  991. guiSliderHandle.Bounds = handleBounds;
  992. oldValue = value;
  993. if (OnValueChanged != null)
  994. OnValueChanged(value);
  995. }
  996. }
  997. }
  998. /** @} */
  999. }