ColorPicker.cs 41 KB

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