ColorPicker.cs 41 KB

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