CGUIColorSelectDialog.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "CGUIColorSelectDialog.h"
  5. #ifdef _IRR_COMPILE_WITH_GUI_
  6. #include "IGUISkin.h"
  7. #include "IGUIEnvironment.h"
  8. #include "IVideoDriver.h"
  9. #include "IGUIButton.h"
  10. #include "IGUIStaticText.h"
  11. #include "IGUIFont.h"
  12. #include "IGUISpriteBank.h"
  13. #include "IFileList.h"
  14. #include "os.h"
  15. #include "fast_atof.h"
  16. namespace irr
  17. {
  18. namespace gui
  19. {
  20. const s32 CSD_WIDTH = 350;
  21. const s32 CSD_HEIGHT = 300;
  22. namespace
  23. {
  24. struct subElementPredefines
  25. {
  26. const wchar_t *pre;
  27. const wchar_t *init;
  28. const wchar_t *post;
  29. int x, y;
  30. int range_down ,range_up;
  31. };
  32. static const subElementPredefines Template [] =
  33. {
  34. { L"A:", L"0", 0,50,165, 0, 255 },
  35. { L"R:", L"0", 0,20,205, 0, 255 },
  36. { L"G:", L"0", 0,20,230, 0, 255 },
  37. { L"B:", L"0", 0,20,255, 0, 255 },
  38. { L"H:", L"0", L"°",80,205, 0, 360 },
  39. { L"S:", L"0", L"%",80,230, 0, 100 },
  40. { L"L:", L"0", L"%",80,255, 0, 100 },
  41. };
  42. }
  43. //! constructor
  44. CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id)
  45. : IGUIColorSelectDialog(environment, parent, id,
  46. core::rect<s32>((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2,
  47. (parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2,
  48. (parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH,
  49. (parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)),
  50. Dragging(false)
  51. {
  52. #ifdef _DEBUG
  53. IGUIElement::setDebugName("CGUIColorSelectDialog");
  54. #endif
  55. Text = title;
  56. IGUISkin* skin = Environment->getSkin();
  57. const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH);
  58. const s32 posx = RelativeRect.getWidth() - buttonw - 4;
  59. CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw),
  60. this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
  61. if (skin && skin->getSpriteBank())
  62. {
  63. CloseButton->setSpriteBank(skin->getSpriteBank());
  64. CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
  65. CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
  66. }
  67. CloseButton->setSubElement(true);
  68. CloseButton->setTabStop(false);
  69. CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
  70. CloseButton->grab();
  71. OKButton = Environment->addButton(
  72. core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
  73. this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
  74. OKButton->setSubElement(true);
  75. OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
  76. OKButton->grab();
  77. CancelButton = Environment->addButton(
  78. core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
  79. this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
  80. CancelButton->setSubElement(true);
  81. CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
  82. CancelButton->grab();
  83. video::IVideoDriver* driver = Environment->getVideoDriver();
  84. ColorRing.Texture = driver->getTexture ( "#colorring" );
  85. if ( 0 == ColorRing.Texture )
  86. {
  87. buildColorRing(core::dimension2d<u32>(128, 128), 1,
  88. Environment->getSkin()->getColor(EGDC_3D_SHADOW));
  89. }
  90. core::rect<s32> r(20,20, 0,0);
  91. ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this);
  92. ColorRing.Control->setSubElement(true);
  93. ColorRing.Control->grab();
  94. for ( u32 i = 0; i != sizeof (Template) / sizeof ( subElementPredefines ); ++i )
  95. {
  96. if ( Template[i].pre )
  97. {
  98. r.UpperLeftCorner.X = Template[i].x;
  99. r.UpperLeftCorner.Y = Template[i].y;
  100. r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
  101. r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
  102. IGUIElement *t = Environment->addStaticText(Template[i].pre, r, false, false, this);
  103. t->setSubElement(true);
  104. }
  105. if ( Template[i].post )
  106. {
  107. r.UpperLeftCorner.X = Template[i].x + 56;
  108. r.UpperLeftCorner.Y = Template[i].y;
  109. r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
  110. r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
  111. IGUIElement *t = Environment->addStaticText( Template[i].post, r, false, false, this);
  112. t->setSubElement(true);
  113. }
  114. r.UpperLeftCorner.X = Template[i].x + 15;
  115. r.UpperLeftCorner.Y = Template[i].y-2;
  116. r.LowerRightCorner.X = r.UpperLeftCorner.X + 40;
  117. r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
  118. gui::IGUISpinBox* spin = Environment->addSpinBox( Template[i].init, r, true, this);
  119. spin->setSubElement(true);
  120. spin->setDecimalPlaces(0);
  121. spin->setRange((f32)Template[i].range_down, (f32)Template[i].range_up);
  122. spin->grab();
  123. Battery.push_back(spin);
  124. }
  125. bringToFront(CancelButton);
  126. bringToFront(OKButton);
  127. }
  128. //! destructor
  129. CGUIColorSelectDialog::~CGUIColorSelectDialog()
  130. {
  131. if (CloseButton)
  132. CloseButton->drop();
  133. if (OKButton)
  134. OKButton->drop();
  135. if (CancelButton)
  136. CancelButton->drop();
  137. for (u32 i = 0; i != Battery.size(); ++i)
  138. Battery[i]->drop();
  139. if (ColorRing.Control)
  140. ColorRing.Control->drop();
  141. }
  142. //! renders a antialiased, colored ring
  143. void CGUIColorSelectDialog::buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor )
  144. {
  145. const core::dimension2d<u32> d(dim.Width * supersample, dim.Height * supersample);
  146. video::IVideoDriver* driver = Environment->getVideoDriver();
  147. video::IImage *RawTexture = driver->createImage(video::ECF_A8R8G8B8, d);
  148. RawTexture->fill ( 0x00808080 );
  149. const s32 radiusOut = ( d.Width / 2 ) - 4;
  150. const s32 fullR2 = radiusOut * radiusOut;
  151. video::SColorf rgb(0,0,0);
  152. video::SColorHSL hsl;
  153. hsl.Luminance = 50;
  154. hsl.Saturation = 100;
  155. core::position2d<s32> p;
  156. for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 )
  157. {
  158. s32 y2 = p.Y * p.Y;
  159. for (p.X = -radiusOut; p.X <= radiusOut; p.X += 1)
  160. {
  161. s32 r2 = y2 + ( p.X * p.X );
  162. // test point in circle
  163. s32 testa = r2 - fullR2;
  164. if ( testa < 0 )
  165. {
  166. // dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a)
  167. const f32 r = sqrtf((f32) r2);
  168. // normalize, dotproduct = xnorm
  169. const f32 xn = r == 0.f ? 0.f : -p.X * core::reciprocal(r);
  170. hsl.Hue = acosf(xn)*core::RADTODEG;
  171. if ( p.Y > 0 )
  172. hsl.Hue = 360 - hsl.Hue;
  173. hsl.Hue -= 90;
  174. const f32 rTest = r / radiusOut;
  175. #if 0
  176. if (rTest < 0.33f)
  177. {
  178. // luminance from 0 to 50
  179. hsl.Luminance = 50*(rTest/0.33);
  180. hsl.Saturation = 0.f;
  181. hsl.toRGB(rgb);
  182. }
  183. else
  184. if ( rTest < 0.66f )
  185. {
  186. // saturation from 0 to 100
  187. hsl.Saturation = 100*(( rTest - 0.33f ) / 0.33f);
  188. hsl.Luminance = 50;
  189. hsl.toRGB(rgb);
  190. }
  191. else
  192. {
  193. // luminance from 50 to 100
  194. hsl.Luminance = 100*(0.5f + ( ( rTest - 0.66f ) / .66f ));
  195. hsl.Saturation = 100;
  196. hsl.toRGB(rgb);
  197. }
  198. // borders should be slightly transparent
  199. if ( rTest >= 0.95f )
  200. rgb.a = (1.f-rTest)*20;
  201. else
  202. rgb.a=1.f;
  203. #else
  204. if ( rTest > 0.5f )
  205. {
  206. hsl.Saturation = 100;
  207. hsl.Luminance = 50;
  208. hsl.toRGB(rgb);
  209. }
  210. // borders should be slightly transparent
  211. if ( rTest < 0.5f )
  212. rgb.a = 0;
  213. else if ( rTest >= 0.95f )
  214. rgb.a = (1.f-rTest)*20;
  215. else if ( rTest <= 0.55f )
  216. rgb.a = (rTest-0.5f)*20;
  217. else
  218. rgb.a=1.f;
  219. #endif
  220. RawTexture->setPixel(4+p.X+radiusOut, 4+p.Y+radiusOut, rgb.toSColor());
  221. }
  222. }
  223. }
  224. RawTexture->unlock ();
  225. if ( supersample > 1 )
  226. {
  227. video::IImage * filter = driver->createImage(video::ECF_A8R8G8B8, dim );
  228. RawTexture->copyToScalingBoxFilter(filter);
  229. RawTexture->drop();
  230. RawTexture = filter;
  231. }
  232. bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
  233. driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false);
  234. ColorRing.Texture = driver->addTexture ( "#colorring", RawTexture);
  235. RawTexture->drop();
  236. driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels);
  237. }
  238. //! called if an event happened.
  239. bool CGUIColorSelectDialog::OnEvent(const SEvent& event)
  240. {
  241. if (isEnabled())
  242. {
  243. switch(event.EventType)
  244. {
  245. case EET_GUI_EVENT:
  246. switch(event.GUIEvent.EventType)
  247. {
  248. case EGET_SPINBOX_CHANGED:
  249. {
  250. for ( u32 i = 0; i!= Battery.size (); ++i )
  251. {
  252. if ( event.GUIEvent.Caller == Battery[i] )
  253. {
  254. if (i<4)
  255. {
  256. video::SColor rgb((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
  257. (u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
  258. video::SColorHSL hsl;
  259. video::SColorf rgb2(rgb);
  260. hsl.fromRGB(rgb2);
  261. Battery[4]->setValue(hsl.Hue);
  262. Battery[5]->setValue(hsl.Saturation);
  263. Battery[6]->setValue(hsl.Luminance);
  264. }
  265. else
  266. {
  267. video::SColorHSL hsl(Battery[4]->getValue(), Battery[5]->getValue(),
  268. Battery[6]->getValue());
  269. video::SColorf rgb2;
  270. hsl.toRGB(rgb2);
  271. video::SColor rgb = rgb2.toSColor();
  272. Battery[1]->setValue((f32)rgb.getRed());
  273. Battery[2]->setValue((f32)rgb.getGreen());
  274. Battery[3]->setValue((f32)rgb.getBlue());
  275. }
  276. }
  277. }
  278. return true;
  279. }
  280. case EGET_ELEMENT_FOCUS_LOST:
  281. Dragging = false;
  282. break;
  283. case EGET_BUTTON_CLICKED:
  284. if (event.GUIEvent.Caller == CloseButton ||
  285. event.GUIEvent.Caller == CancelButton)
  286. {
  287. sendCancelEvent();
  288. remove();
  289. return true;
  290. }
  291. else
  292. if (event.GUIEvent.Caller == OKButton)
  293. {
  294. sendSelectedEvent();
  295. remove();
  296. return true;
  297. }
  298. break;
  299. case EGET_LISTBOX_CHANGED:
  300. case EGET_LISTBOX_SELECTED_AGAIN:
  301. default:
  302. break;
  303. }
  304. break;
  305. case EET_MOUSE_INPUT_EVENT:
  306. switch(event.MouseInput.Event)
  307. {
  308. case EMIE_LMOUSE_PRESSED_DOWN:
  309. DragStart.X = event.MouseInput.X;
  310. DragStart.Y = event.MouseInput.Y;
  311. Dragging = true;
  312. Environment->setFocus(this);
  313. return true;
  314. case EMIE_LMOUSE_LEFT_UP:
  315. Dragging = false;
  316. Environment->removeFocus(this);
  317. return true;
  318. case EMIE_MOUSE_MOVED:
  319. if (Dragging)
  320. {
  321. // gui window should not be dragged outside its parent
  322. if (Parent)
  323. if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
  324. event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
  325. event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
  326. event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
  327. return true;
  328. move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
  329. DragStart.X = event.MouseInput.X;
  330. DragStart.Y = event.MouseInput.Y;
  331. return true;
  332. }
  333. default:
  334. break;
  335. }
  336. default:
  337. break;
  338. }
  339. }
  340. return IGUIElement::OnEvent(event);
  341. }
  342. //! draws the element and its children
  343. void CGUIColorSelectDialog::draw()
  344. {
  345. if (!IsVisible)
  346. return;
  347. IGUISkin* skin = Environment->getSkin();
  348. core::rect<s32> rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
  349. AbsoluteRect, &AbsoluteClippingRect);
  350. if (Text.size())
  351. {
  352. rect.UpperLeftCorner.X += 2;
  353. rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
  354. IGUIFont* font = skin->getFont(EGDF_WINDOW);
  355. if (font)
  356. font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true,
  357. &AbsoluteClippingRect);
  358. }
  359. IGUIElement::draw();
  360. // draw color selector after the window elements
  361. core::vector2di pos(ColorRing.Control->getAbsolutePosition().UpperLeftCorner);
  362. pos.X += ColorRing.Texture->getOriginalSize().Width/2;
  363. pos.Y += ColorRing.Texture->getOriginalSize().Height/2;
  364. #if 0
  365. const f32 h = Battery[4]->getValue();
  366. const f32 s = Battery[5]->getValue();
  367. const f32 l = Battery[6]->getValue();
  368. const f32 factor = 58.f*(((s==0)&&(l<50))?(l*0.33f/50):(
  369. (s<100)?((.33f+(s*0.33f/100))):((0.66f+(l-50)*0.33f/50))));
  370. #else
  371. const f32 factor = 44;
  372. #endif
  373. pos.X += core::round32(sinf(Battery[4]->getValue()*core::DEGTORAD)*factor);
  374. pos.Y -= core::round32(cosf(Battery[4]->getValue()*core::DEGTORAD)*factor);
  375. Environment->getVideoDriver()->draw2DPolygon(pos, 4, 0xffffffff, 4);
  376. }
  377. video::SColor CGUIColorSelectDialog::getColor()
  378. {
  379. return video::SColor((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
  380. (u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
  381. }
  382. video::SColorHSL CGUIColorSelectDialog::getColorHSL()
  383. {
  384. return video::SColorHSL(Battery[4]->getValue(), Battery[5]->getValue(),
  385. Battery[6]->getValue());
  386. }
  387. //! sends the event that the file has been selected.
  388. void CGUIColorSelectDialog::sendSelectedEvent()
  389. {
  390. SEvent event;
  391. event.EventType = EET_GUI_EVENT;
  392. event.GUIEvent.Caller = this;
  393. event.GUIEvent.Element = 0;
  394. event.GUIEvent.EventType = EGET_FILE_SELECTED;
  395. Parent->OnEvent(event);
  396. }
  397. //! sends the event that the file choose process has been canceld
  398. void CGUIColorSelectDialog::sendCancelEvent()
  399. {
  400. SEvent event;
  401. event.EventType = EET_GUI_EVENT;
  402. event.GUIEvent.Caller = this;
  403. event.GUIEvent.Element = 0;
  404. event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
  405. Parent->OnEvent(event);
  406. }
  407. } // end namespace gui
  408. } // end namespace irr
  409. #endif // _IRR_COMPILE_WITH_GUI_