2
0

ColorPicker.cs 42 KB

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