Theme.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. /*
  2. * Theme.cpp
  3. */
  4. #include "Base.h"
  5. #include "Theme.h"
  6. namespace gameplay
  7. {
  8. static std::vector<Theme*> __themeCache;
  9. Theme::Theme()
  10. {
  11. }
  12. Theme::Theme(const Theme* theme)
  13. {
  14. }
  15. Theme::~Theme()
  16. {
  17. // Destroy all the cursors, styles and , fonts.
  18. for (unsigned int i = 0, count = _styles.size(); i < count; ++i)
  19. {
  20. Style* style = _styles[i];
  21. SAFE_DELETE(style);
  22. }
  23. for (unsigned int i = 0, count = _cursors.size(); i < count; ++i)
  24. {
  25. Cursor* cursor = _cursors[i];
  26. SAFE_RELEASE(cursor);
  27. }
  28. for (unsigned int i = 0, count = _icons.size(); i < count; ++i)
  29. {
  30. Icon* icon = _icons[i];
  31. SAFE_RELEASE(icon);
  32. }
  33. for (unsigned int i = 0, count = _sliders.size(); i < count; ++i)
  34. {
  35. SliderIcon* slider = _sliders[i];
  36. SAFE_RELEASE(slider);
  37. }
  38. for (unsigned int i = 0, count = _containers.size(); i < count; ++i)
  39. {
  40. ContainerRegion* container = _containers[i];
  41. SAFE_RELEASE(container);
  42. }
  43. SAFE_DELETE(_spriteBatch);
  44. SAFE_RELEASE(_texture);
  45. // Remove ourself from the theme cache.
  46. std::vector<Theme*>::iterator itr = find(__themeCache.begin(), __themeCache.end(), this);
  47. if (itr != __themeCache.end())
  48. {
  49. __themeCache.erase(itr);
  50. }
  51. }
  52. Theme* Theme::create(const char* path)
  53. {
  54. assert(path);
  55. // Search theme cache first.
  56. for (unsigned int i = 0, count = __themeCache.size(); i < count; ++i)
  57. {
  58. Theme* t = __themeCache[i];
  59. if (t->_path == path)
  60. {
  61. // Found a match.
  62. t->addRef();
  63. return t;
  64. }
  65. }
  66. // Load theme properties from file path.
  67. Properties* properties = Properties::create(path);
  68. assert(properties);
  69. if (properties == NULL)
  70. {
  71. return NULL;
  72. }
  73. // Check if the Properties is valid and has a valid namespace.
  74. Properties* themeProperties = properties->getNextNamespace();
  75. assert(themeProperties);
  76. if (!themeProperties || !(strcmp(themeProperties->getNamespace(), "theme") == 0))
  77. {
  78. SAFE_DELETE(properties);
  79. return NULL;
  80. }
  81. // Create a new theme.
  82. Theme* theme = new Theme();
  83. theme->_path = path;
  84. // Parse the Properties object and set up the theme.
  85. const char* textureFile = themeProperties->getString("texture");
  86. theme->_texture = Texture::create(textureFile, false);
  87. theme->_spriteBatch = SpriteBatch::create(theme->_texture);
  88. Properties* space = themeProperties->getNextNamespace();
  89. while (space != NULL)
  90. {
  91. // First load all cursors, checkboxes etc. that can be referred to by styles.
  92. const char* spacename = space->getNamespace();
  93. if (strcmp(spacename, "cursor") == 0)
  94. {
  95. Vector4 regionVector;
  96. space->getVector4("region", &regionVector);
  97. const Rectangle region(regionVector.x, regionVector.y, regionVector.z, regionVector.w);
  98. Vector4 color(1, 1, 1, 1);
  99. if (space->exists("color"))
  100. {
  101. space->getColor("color", &color);
  102. }
  103. Theme::Cursor* c = Theme::Cursor::create(space->getId(), *theme->_texture, region, color);
  104. theme->_cursors.push_back(c);
  105. }
  106. else if (strcmp(spacename, "icon") == 0)
  107. {
  108. Vector2 offVec;
  109. Vector2 onVec;
  110. Vector2 size;
  111. space->getVector2("offPosition", &offVec);
  112. space->getVector2("onPosition", &onVec);
  113. space->getVector2("size", &size);
  114. Vector4 color(1, 1, 1, 1);
  115. if (space->exists("color"))
  116. {
  117. space->getColor("color", &color);
  118. }
  119. Icon* icon = Icon::create(space->getId(), *theme->_texture, size, offVec, onVec, color);
  120. theme->_icons.push_back(icon);
  121. }
  122. else if (strcmp(spacename, "slider") == 0)
  123. {
  124. Vector4 minCapRegion;
  125. Vector4 maxCapRegion;
  126. Vector4 trackRegion;
  127. Vector4 markerRegion;
  128. space->getVector4("minCapRegion", &minCapRegion);
  129. space->getVector4("maxCapRegion", &maxCapRegion);
  130. space->getVector4("trackRegion", &trackRegion);
  131. space->getVector4("markerRegion", &markerRegion);
  132. Vector4 color(1, 1, 1, 1);
  133. if (space->exists("color"))
  134. {
  135. space->getColor("color", &color);
  136. }
  137. SliderIcon* sliderIcon = SliderIcon::create(space->getId(), *theme->_texture, minCapRegion, maxCapRegion, markerRegion, trackRegion, color);
  138. theme->_sliders.push_back(sliderIcon);
  139. }
  140. else if (strcmp(spacename, "cursor") == 0)
  141. {
  142. Vector4 regionVector;
  143. space->getVector4("region", &regionVector);
  144. const Rectangle region(regionVector.x, regionVector.y, regionVector.z, regionVector.w);
  145. Vector4 color(1, 1, 1, 1);
  146. if (space->exists("color"))
  147. {
  148. space->getColor("color", &color);
  149. }
  150. Cursor* cursor = Cursor::create(space->getId(), *theme->_texture, region, color);
  151. theme->_cursors.push_back(cursor);
  152. }
  153. else if (strcmp(spacename, "container") == 0)
  154. {
  155. Theme::Border border;
  156. Properties* innerSpace = space->getNextNamespace();
  157. if (innerSpace)
  158. {
  159. const char* innerSpacename = innerSpace->getNamespace();
  160. if (strcmp(innerSpacename, "border") == 0)
  161. {
  162. border.top = innerSpace->getFloat("top");
  163. border.bottom = innerSpace->getFloat("bottom");
  164. border.left = innerSpace->getFloat("left");
  165. border.right = innerSpace->getFloat("right");
  166. }
  167. }
  168. Vector4 regionVector;
  169. space->getVector4("region", &regionVector);
  170. const Rectangle region(regionVector.x, regionVector.y, regionVector.z, regionVector.w);
  171. Vector4 color(1, 1, 1, 1);
  172. if (space->exists("color"))
  173. {
  174. space->getColor("color", &color);
  175. }
  176. ContainerRegion* container = ContainerRegion::create(space->getId(), *theme->_texture, region, border, color);
  177. theme->_containers.push_back(container);
  178. }
  179. space = themeProperties->getNextNamespace();
  180. }
  181. themeProperties->rewind();
  182. space = themeProperties->getNextNamespace();
  183. while (space != NULL)
  184. {
  185. const char* spacename = space->getNamespace();
  186. if (strcmp(spacename, "style") == 0)
  187. {
  188. // Each style contains up to MAX_OVERLAYS overlays,
  189. // as well as Border and Padding namespaces.
  190. Theme::Margin margin;
  191. Theme::Padding padding;
  192. Theme::Style::Overlay* normal = NULL;
  193. Theme::Style::Overlay* focus = NULL;
  194. Theme::Style::Overlay* active = NULL;
  195. Theme::Style::Overlay* disabled = NULL;
  196. // Need to load OVERLAY_NORMAL first so that the other overlays can inherit from it.
  197. Properties* innerSpace = space->getNextNamespace();
  198. while (innerSpace != NULL)
  199. {
  200. const char* innerSpacename = innerSpace->getNamespace();
  201. if (strcmp(innerSpacename, "normal") == 0)
  202. {
  203. Vector4 textColor(0, 0, 0, 1);
  204. if (innerSpace->exists("textColor"))
  205. {
  206. innerSpace->getColor("textColor", &textColor);
  207. }
  208. const char* fontPath = innerSpace->getString("font");
  209. Font* font = NULL;
  210. if (fontPath)
  211. {
  212. font = Font::create(fontPath);
  213. }
  214. unsigned int fontSize = innerSpace->getInt("fontSize");
  215. const char* alignmentString = innerSpace->getString("alignment");
  216. Font::Justify alignment = Font::ALIGN_TOP_LEFT;
  217. if (alignmentString)
  218. {
  219. alignment = Font::getJustifyFromString(alignmentString);
  220. }
  221. bool rightToLeft = innerSpace->getBool("rightToLeft");
  222. Icon* checkBoxIcon = NULL;
  223. Icon* radioButtonIcon = NULL;
  224. SliderIcon* sliderIcon = NULL;
  225. Cursor* textCursor = NULL;
  226. Cursor* mouseCursor = NULL;
  227. ContainerRegion* containerRegion = NULL;
  228. theme->lookUpSprites(innerSpace, &checkBoxIcon, &radioButtonIcon, &sliderIcon, &textCursor, &mouseCursor, &containerRegion);
  229. normal = Theme::Style::Overlay::create();
  230. normal->setContainerRegion(containerRegion);
  231. normal->setTextCursor(textCursor);
  232. normal->setMouseCursor(mouseCursor);
  233. normal->setCheckBoxIcon(checkBoxIcon);
  234. normal->setRadioButtonIcon(radioButtonIcon);
  235. normal->setSliderIcon(sliderIcon);
  236. normal->setTextColor(textColor);
  237. normal->setFont(font);
  238. normal->setFontSize(fontSize);
  239. normal->setTextAlignment(alignment);
  240. normal->setTextRightToLeft(rightToLeft);
  241. theme->_fonts.insert(font);
  242. if (font) font->release();
  243. // Done with this pass.
  244. break;
  245. }
  246. innerSpace = space->getNextNamespace();
  247. }
  248. // At least the OVERLAY_NORMAL is required.
  249. assert(normal);
  250. space->rewind();
  251. innerSpace = space->getNextNamespace();
  252. while (innerSpace != NULL)
  253. {
  254. const char* innerSpacename = innerSpace->getNamespace();
  255. if (strcmp(innerSpacename, "margin") == 0)
  256. {
  257. margin.top = innerSpace->getFloat("top");
  258. margin.bottom = innerSpace->getFloat("bottom");
  259. margin.left = innerSpace->getFloat("left");
  260. margin.right = innerSpace->getFloat("right");
  261. }
  262. else if (strcmp(innerSpacename, "padding") == 0)
  263. {
  264. padding.top = innerSpace->getFloat("top");
  265. padding.bottom = innerSpace->getFloat("bottom");
  266. padding.left = innerSpace->getFloat("left");
  267. padding.right = innerSpace->getFloat("right");
  268. }
  269. else if (strcmp(innerSpacename, "normal") != 0)
  270. {
  271. // Either OVERLAY_FOCUS or OVERLAY_ACTIVE.
  272. // If a property isn't specified, it inherits from OVERLAY_NORMAL.
  273. Vector4 textColor;
  274. if (!innerSpace->getColor("textColor", &textColor))
  275. {
  276. textColor.set(normal->getTextColor());
  277. }
  278. const char* fontPath = innerSpace->getString("font");
  279. Font* font = NULL;
  280. if (fontPath)
  281. {
  282. font = Font::create(fontPath);
  283. }
  284. if (!font)
  285. {
  286. font = normal->getFont();
  287. }
  288. unsigned int fontSize;
  289. if (innerSpace->exists("fontSize"))
  290. {
  291. fontSize = innerSpace->getInt("fontSize");
  292. }
  293. else
  294. {
  295. fontSize = normal->getFontSize();
  296. }
  297. const char* alignmentString = innerSpace->getString("alignment");
  298. Font::Justify alignment;
  299. if (alignmentString)
  300. {
  301. alignment = Font::getJustifyFromString(alignmentString);
  302. }
  303. else
  304. {
  305. alignment = normal->getTextAlignment();
  306. }
  307. bool rightToLeft;
  308. if (innerSpace->exists("rightToLeft"))
  309. {
  310. rightToLeft = innerSpace->getBool("rightToLeft");
  311. }
  312. else
  313. {
  314. rightToLeft = normal->getTextRightToLeft();
  315. }
  316. Icon* checkBoxIcon = NULL;
  317. Icon* radioButtonIcon = NULL;
  318. SliderIcon* sliderIcon = NULL;
  319. Cursor* textCursor = NULL;
  320. Cursor* mouseCursor = NULL;
  321. ContainerRegion* containerRegion = NULL;
  322. theme->lookUpSprites(innerSpace, &checkBoxIcon, &radioButtonIcon, &sliderIcon, &textCursor, &mouseCursor, &containerRegion);
  323. if (!checkBoxIcon)
  324. {
  325. checkBoxIcon = normal->getCheckBoxIcon();
  326. }
  327. if (!radioButtonIcon)
  328. {
  329. radioButtonIcon = normal->getRadioButtonIcon();
  330. }
  331. if (!sliderIcon)
  332. {
  333. sliderIcon = normal->getSliderIcon();
  334. }
  335. if (!textCursor)
  336. {
  337. textCursor = normal->getTextCursor();
  338. }
  339. if (!mouseCursor)
  340. {
  341. mouseCursor = normal->getMouseCursor();
  342. }
  343. if (!containerRegion)
  344. {
  345. containerRegion = normal->getContainerRegion();
  346. }
  347. if (strcmp(innerSpacename, "focus") == 0)
  348. {
  349. focus = Theme::Style::Overlay::create();
  350. focus->setContainerRegion(containerRegion);
  351. focus->setCheckBoxIcon(checkBoxIcon);
  352. focus->setTextCursor(textCursor);
  353. focus->setMouseCursor(mouseCursor);
  354. focus->setCheckBoxIcon(checkBoxIcon);
  355. focus->setRadioButtonIcon(radioButtonIcon);
  356. focus->setSliderIcon(sliderIcon);
  357. focus->setTextColor(textColor);
  358. focus->setFont(font);
  359. focus->setFontSize(fontSize);
  360. focus->setTextAlignment(alignment);
  361. focus->setTextRightToLeft(rightToLeft);
  362. theme->_fonts.insert(font);
  363. }
  364. else if (strcmp(innerSpacename, "active") == 0)
  365. {
  366. active = Theme::Style::Overlay::create();
  367. active->setContainerRegion(containerRegion);
  368. active->setTextCursor(textCursor);
  369. active->setMouseCursor(mouseCursor);
  370. active->setCheckBoxIcon(checkBoxIcon);
  371. active->setRadioButtonIcon(radioButtonIcon);
  372. active->setSliderIcon(sliderIcon);
  373. active->setTextColor(textColor);
  374. active->setFont(font);
  375. active->setFontSize(fontSize);
  376. active->setTextAlignment(alignment);
  377. active->setTextRightToLeft(rightToLeft);
  378. theme->_fonts.insert(font);
  379. }
  380. else if (strcmp(innerSpacename, "disabled") == 0)
  381. {
  382. disabled = Theme::Style::Overlay::create();
  383. disabled->setContainerRegion(containerRegion);
  384. disabled->setTextCursor(textCursor);
  385. disabled->setMouseCursor(mouseCursor);
  386. disabled->setCheckBoxIcon(checkBoxIcon);
  387. disabled->setRadioButtonIcon(radioButtonIcon);
  388. disabled->setSliderIcon(sliderIcon);
  389. disabled->setTextColor(textColor);
  390. disabled->setFont(font);
  391. disabled->setFontSize(fontSize);
  392. disabled->setTextAlignment(alignment);
  393. disabled->setTextRightToLeft(rightToLeft);
  394. theme->_fonts.insert(font);
  395. }
  396. }
  397. innerSpace = space->getNextNamespace();
  398. }
  399. if (!focus)
  400. {
  401. focus = normal;
  402. focus->addRef();
  403. }
  404. if (!active)
  405. {
  406. active = normal;
  407. active->addRef();
  408. }
  409. if (!disabled)
  410. {
  411. disabled = normal;
  412. disabled->addRef();
  413. }
  414. Theme::Style* s = new Theme::Style(space->getId(), margin, padding, normal, focus, active, disabled);
  415. theme->_styles.push_back(s);
  416. }
  417. space = themeProperties->getNextNamespace();
  418. }
  419. // Add this theme to the cache.
  420. __themeCache.push_back(theme);
  421. SAFE_DELETE(properties);
  422. return theme;
  423. }
  424. Theme::Style* Theme::getStyle(const char* name) const
  425. {
  426. for (unsigned int i = 0, count = _styles.size(); i < count; ++i)
  427. {
  428. if (strcmp(name, _styles[i]->getId()) == 0)
  429. {
  430. return _styles[i];
  431. }
  432. }
  433. return NULL;
  434. }
  435. void Theme::setProjectionMatrix(const Matrix& matrix)
  436. {
  437. _spriteBatch->setProjectionMatrix(matrix);
  438. // Set the matrix on each Font used by the style.
  439. std::set<Font*>::const_iterator it;
  440. for (it = _fonts.begin(); it != _fonts.end(); ++it)
  441. {
  442. (*it)->getSpriteBatch()->setProjectionMatrix(matrix);
  443. }
  444. }
  445. SpriteBatch* Theme::getSpriteBatch() const
  446. {
  447. return _spriteBatch;
  448. }
  449. /***************
  450. * Theme::Icon *
  451. ***************/
  452. Theme::Icon* Theme::Icon::create(const char* id, const Texture& texture, const Vector2& size,
  453. const Vector2& offPosition, const Vector2& onPosition, const Vector4& color)
  454. {
  455. Icon* icon = new Icon(texture, size, offPosition, onPosition, color);
  456. if (id)
  457. {
  458. icon->_id = id;
  459. }
  460. return icon;
  461. }
  462. Theme::Icon::Icon(const Texture& texture, const Vector2& size,
  463. const Vector2& offPosition, const Vector2& onPosition, const Vector4& color)
  464. : _size(size), _color(color)
  465. {
  466. generateUVs(texture, offPosition.x, offPosition.y, size.x, size.y, &_off);
  467. generateUVs(texture, onPosition.x, onPosition.y, size.x, size.y, &_on);
  468. }
  469. Theme::Icon::~Icon()
  470. {
  471. }
  472. const char* Theme::Icon::getId() const
  473. {
  474. return _id.c_str();
  475. }
  476. const Vector2& Theme::Icon::getSize() const
  477. {
  478. return _size;
  479. }
  480. const Vector4& Theme::Icon::getColor() const
  481. {
  482. return _color;
  483. }
  484. const Theme::UVs& Theme::Icon::getOffUVs() const
  485. {
  486. return _off;
  487. }
  488. const Theme::UVs& Theme::Icon::getOnUVs() const
  489. {
  490. return _on;
  491. }
  492. /*********************
  493. * Theme::SliderIcon *
  494. *********************/
  495. Theme::SliderIcon* Theme::SliderIcon::create(const char* id, const Texture& texture, const Vector4& minCapRegion,
  496. const Vector4& maxCapRegion, const Vector4& markerRegion, const Vector4& trackRegion, const Vector4& color)
  497. {
  498. SliderIcon* sliderIcon = new SliderIcon(texture, minCapRegion, maxCapRegion, markerRegion, trackRegion, color);
  499. if (id)
  500. {
  501. sliderIcon->_id = id;
  502. }
  503. return sliderIcon;
  504. }
  505. Theme::SliderIcon::SliderIcon(const Texture& texture, const Vector4& minCapRegion, const Vector4& maxCapRegion,
  506. const Vector4& markerRegion, const Vector4& trackRegion, const Vector4& color)
  507. : _color(color)
  508. {
  509. _minCapSize.set(minCapRegion.z, minCapRegion.w);
  510. _maxCapSize.set(maxCapRegion.z, maxCapRegion.w);
  511. _markerSize.set(markerRegion.z, markerRegion.w);
  512. _trackSize.set(trackRegion.z, trackRegion.w);
  513. generateUVs(texture, minCapRegion.x, minCapRegion.y, minCapRegion.z, minCapRegion.w, &_minCap);
  514. generateUVs(texture, maxCapRegion.x, maxCapRegion.y, maxCapRegion.z, maxCapRegion.w, &_maxCap);
  515. generateUVs(texture, markerRegion.x, markerRegion.y, markerRegion.z, markerRegion.w, &_marker);
  516. generateUVs(texture, trackRegion.x, trackRegion.y, trackRegion.z, trackRegion.w, &_track);
  517. }
  518. Theme::SliderIcon::~SliderIcon()
  519. {
  520. }
  521. const char* Theme::SliderIcon::getId() const
  522. {
  523. return _id.c_str();
  524. }
  525. const Theme::UVs& Theme::SliderIcon::getMinCapUVs() const
  526. {
  527. return _minCap;
  528. }
  529. const Theme::UVs& Theme::SliderIcon::getMaxCapUVs() const
  530. {
  531. return _maxCap;
  532. }
  533. const Theme::UVs& Theme::SliderIcon::getMarkerUVs() const
  534. {
  535. return _marker;
  536. }
  537. const Theme::UVs& Theme::SliderIcon::getTrackUVs() const
  538. {
  539. return _track;
  540. }
  541. const Vector2& Theme::SliderIcon::getMinCapSize() const
  542. {
  543. return _minCapSize;
  544. }
  545. const Vector2& Theme::SliderIcon::getMaxCapSize() const
  546. {
  547. return _maxCapSize;
  548. }
  549. const Vector2& Theme::SliderIcon::getMarkerSize() const
  550. {
  551. return _markerSize;
  552. }
  553. const Vector2& Theme::SliderIcon::getTrackSize() const
  554. {
  555. return _trackSize;
  556. }
  557. const Vector4& Theme::SliderIcon::getColor() const
  558. {
  559. return _color;
  560. }
  561. /*****************
  562. * Theme::Cursor *
  563. *****************/
  564. Theme::Cursor* Theme::Cursor::create(const char* id, const Texture& texture, const Rectangle& region, const Vector4& color)
  565. {
  566. Cursor* cursor = new Cursor(texture, region, color);
  567. if (id)
  568. {
  569. cursor->_id = id;
  570. }
  571. return cursor;
  572. }
  573. Theme::Cursor::Cursor(const Texture& texture, const Rectangle& region, const Vector4& color)
  574. : _color(color)
  575. {
  576. _size.set(region.width, region.height);
  577. generateUVs(texture, region.x, region.y, region.width, region.height, &_uvs);
  578. }
  579. Theme::Cursor::~Cursor()
  580. {
  581. }
  582. const char* Theme::Cursor::getId() const
  583. {
  584. return _id.data();
  585. }
  586. const Theme::UVs& Theme::Cursor::getUVs() const
  587. {
  588. return _uvs;
  589. }
  590. const Vector2& Theme::Cursor::getSize() const
  591. {
  592. return _size;
  593. }
  594. const Vector4& Theme::Cursor::getColor() const
  595. {
  596. return _color;
  597. }
  598. /**************************
  599. * Theme::ContainerRegion *
  600. **************************/
  601. Theme::ContainerRegion* Theme::ContainerRegion::create(const char* id, const Texture& texture, const Rectangle& region, const Theme::Border& border, const Vector4& color)
  602. {
  603. ContainerRegion* containerRegion = new ContainerRegion(texture, region, border, color);
  604. if (id)
  605. {
  606. containerRegion->_id = id;
  607. }
  608. return containerRegion;
  609. }
  610. Theme::ContainerRegion::ContainerRegion(const Texture& texture, const Rectangle& region, const Theme::Border& border, const Vector4& color)
  611. : _border(border), _color(color)
  612. {
  613. // Need to convert pixel coords to unit space by dividing by texture size.
  614. float tw = 1.0f / (float)texture.getWidth();
  615. float th = 1.0f / (float)texture.getHeight();
  616. // Can calculate all measurements in advance.
  617. float leftEdge = region.x * tw;
  618. float rightEdge = (region.x + region.width) * tw;
  619. float leftBorder = (region.x + border.left) * tw;
  620. float rightBorder = (region.x + region.width - border.right) * tw;
  621. float topEdge = 1.0f - (region.y * th);
  622. float bottomEdge = 1.0f - ((region.y + region.height) * th);
  623. float topBorder = 1.0f - ((region.y + border.top) * th);
  624. float bottomBorder = 1.0f - ((region.y + region.height - border.bottom) * th);
  625. // There are 9 sets of UVs to set.
  626. _uvs[TOP_LEFT].u1 = leftEdge;
  627. _uvs[TOP_LEFT].v1 = topEdge;
  628. _uvs[TOP_LEFT].u2 = leftBorder;
  629. _uvs[TOP_LEFT].v2 = topBorder;
  630. _uvs[TOP].u1 = leftBorder;
  631. _uvs[TOP].v1 = topEdge;
  632. _uvs[TOP].u2 = rightBorder;
  633. _uvs[TOP].v2 = topBorder;
  634. _uvs[TOP_RIGHT].u1 = rightBorder;
  635. _uvs[TOP_RIGHT].v1 = topEdge;
  636. _uvs[TOP_RIGHT].u2 = rightEdge;
  637. _uvs[TOP_RIGHT].v2 = topBorder;
  638. _uvs[LEFT].u1 = leftEdge;
  639. _uvs[LEFT].v1 = topBorder;
  640. _uvs[LEFT].u2 = leftBorder;
  641. _uvs[LEFT].v2 = bottomBorder;
  642. _uvs[CENTER].u1 = leftBorder;
  643. _uvs[CENTER].v1 = topBorder;
  644. _uvs[CENTER].u2 = rightBorder;
  645. _uvs[CENTER].v2 = bottomBorder;
  646. _uvs[RIGHT].u1 = rightBorder;
  647. _uvs[RIGHT].v1 = topBorder;
  648. _uvs[RIGHT].u2 = rightEdge;
  649. _uvs[RIGHT].v2 = bottomBorder;
  650. _uvs[BOTTOM_LEFT].u1 = leftEdge;
  651. _uvs[BOTTOM_LEFT].v1 = bottomBorder;
  652. _uvs[BOTTOM_LEFT].u2 = leftBorder;
  653. _uvs[BOTTOM_LEFT].v2 = bottomEdge;
  654. _uvs[BOTTOM].u1 = leftBorder;
  655. _uvs[BOTTOM].v1 = bottomBorder;
  656. _uvs[BOTTOM].u2 = rightBorder;
  657. _uvs[BOTTOM].v2 = bottomEdge;
  658. _uvs[BOTTOM_RIGHT].u1 = rightBorder;
  659. _uvs[BOTTOM_RIGHT].v1 = bottomBorder;
  660. _uvs[BOTTOM_RIGHT].u2 = rightEdge;
  661. _uvs[BOTTOM_RIGHT].v2 = bottomEdge;
  662. }
  663. Theme::ContainerRegion::~ContainerRegion()
  664. {
  665. }
  666. const char* Theme::ContainerRegion::getId() const
  667. {
  668. return _id.c_str();
  669. }
  670. const Theme::Border& Theme::ContainerRegion::getBorder() const
  671. {
  672. return _border;
  673. }
  674. const Theme::UVs& Theme::ContainerRegion::getUVs(ContainerArea area) const
  675. {
  676. return _uvs[area];
  677. }
  678. const Vector4& Theme::ContainerRegion::getColor() const
  679. {
  680. return _color;
  681. }
  682. /****************
  683. * Theme::Style *
  684. ****************/
  685. Theme::Style::Style(const char* id, const Theme::Margin& margin, const Theme::Padding& padding,
  686. Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active, Theme::Style::Overlay* disabled)
  687. : _id(id), _margin(margin), _padding(padding)
  688. {
  689. _overlays[OVERLAY_NORMAL] = normal;
  690. _overlays[OVERLAY_FOCUS] = focus;
  691. _overlays[OVERLAY_ACTIVE] = active;
  692. _overlays[OVERLAY_DISABLED] = disabled;
  693. }
  694. Theme::Style::~Style()
  695. {
  696. for (int i = 0; i < MAX_OVERLAYS; i++)
  697. {
  698. SAFE_RELEASE(_overlays[i]);
  699. }
  700. }
  701. const char* Theme::Style::getId() const
  702. {
  703. return _id.data();
  704. }
  705. Theme::Style::Overlay* Theme::Style::getOverlay(OverlayType overlayType) const
  706. {
  707. return _overlays[overlayType];
  708. }
  709. const Theme::Margin& Theme::Style::getMargin() const
  710. {
  711. return _margin;
  712. }
  713. const Theme::Padding& Theme::Style::getPadding() const
  714. {
  715. return _padding;
  716. }
  717. /*************************
  718. * Theme::Style::Overlay *
  719. *************************/
  720. Theme::Style::Overlay* Theme::Style::Overlay::create()
  721. {
  722. Overlay* overlay = new Overlay();
  723. return overlay;
  724. }
  725. Theme::Style::Overlay::Overlay() : _container(NULL), _textCursor(NULL), _mouseCursor(NULL), _checkBoxIcon(NULL), _radioButtonIcon(NULL), _sliderIcon(NULL), _font(NULL)
  726. {
  727. }
  728. Theme::Style::Overlay::~Overlay()
  729. {
  730. SAFE_RELEASE(_container);
  731. SAFE_RELEASE(_checkBoxIcon);
  732. SAFE_RELEASE(_radioButtonIcon);
  733. SAFE_RELEASE(_sliderIcon);
  734. SAFE_RELEASE(_mouseCursor);
  735. SAFE_RELEASE(_textCursor);
  736. SAFE_RELEASE(_font);
  737. }
  738. Font* Theme::Style::Overlay::getFont() const
  739. {
  740. return _font;
  741. }
  742. void Theme::Style::Overlay::setFont(Font* font)
  743. {
  744. if (_font != font)
  745. {
  746. SAFE_RELEASE(_font);
  747. _font = font;
  748. if (_font)
  749. {
  750. _font->addRef();
  751. }
  752. }
  753. }
  754. unsigned int Theme::Style::Overlay::getFontSize() const
  755. {
  756. return _fontSize;
  757. }
  758. void Theme::Style::Overlay::setFontSize(unsigned int fontSize)
  759. {
  760. _fontSize = fontSize;
  761. }
  762. Font::Justify Theme::Style::Overlay::getTextAlignment() const
  763. {
  764. return _alignment;
  765. }
  766. void Theme::Style::Overlay::setTextAlignment(Font::Justify alignment)
  767. {
  768. _alignment = alignment;
  769. }
  770. bool Theme::Style::Overlay::getTextRightToLeft() const
  771. {
  772. return _textRightToLeft;
  773. }
  774. void Theme::Style::Overlay::setTextRightToLeft(bool rightToLeft)
  775. {
  776. _textRightToLeft = rightToLeft;
  777. }
  778. const Vector4& Theme::Style::Overlay::getTextColor() const
  779. {
  780. return _textColor;
  781. }
  782. void Theme::Style::Overlay::setTextColor(const Vector4& color)
  783. {
  784. _textColor = color;
  785. }
  786. Theme::Cursor* Theme::Style::Overlay::getTextCursor() const
  787. {
  788. return _textCursor;
  789. }
  790. void Theme::Style::Overlay::setTextCursor(Theme::Cursor* cursor)
  791. {
  792. if (_textCursor != cursor)
  793. {
  794. SAFE_RELEASE(_textCursor);
  795. _textCursor = cursor;
  796. if (cursor)
  797. {
  798. cursor->addRef();
  799. }
  800. }
  801. }
  802. Theme::Cursor* Theme::Style::Overlay::getMouseCursor() const
  803. {
  804. return _mouseCursor;
  805. }
  806. void Theme::Style::Overlay::setMouseCursor(Theme::Cursor* cursor)
  807. {
  808. if (_mouseCursor != cursor)
  809. {
  810. SAFE_RELEASE(_mouseCursor);
  811. _mouseCursor = cursor;
  812. if (cursor)
  813. {
  814. cursor->addRef();
  815. }
  816. }
  817. }
  818. void Theme::Style::Overlay::setCheckBoxIcon(Icon* icon)
  819. {
  820. if (_checkBoxIcon != icon)
  821. {
  822. SAFE_RELEASE(_checkBoxIcon);
  823. _checkBoxIcon = icon;
  824. if (icon)
  825. {
  826. icon->addRef();
  827. }
  828. }
  829. }
  830. Theme::Icon* Theme::Style::Overlay::getCheckBoxIcon() const
  831. {
  832. return _checkBoxIcon;
  833. }
  834. void Theme::Style::Overlay::setRadioButtonIcon(Icon* icon)
  835. {
  836. if (_radioButtonIcon != icon)
  837. {
  838. SAFE_RELEASE(_radioButtonIcon);
  839. _radioButtonIcon = icon;
  840. if (icon)
  841. {
  842. icon->addRef();
  843. }
  844. }
  845. }
  846. Theme::Icon* Theme::Style::Overlay::getRadioButtonIcon() const
  847. {
  848. return _radioButtonIcon;
  849. }
  850. void Theme::Style::Overlay::setSliderIcon(SliderIcon* slider)
  851. {
  852. if (_sliderIcon != slider)
  853. {
  854. SAFE_RELEASE(_sliderIcon);
  855. _sliderIcon = slider;
  856. if (slider)
  857. {
  858. slider->addRef();
  859. }
  860. }
  861. }
  862. Theme::SliderIcon* Theme::Style::Overlay::getSliderIcon() const
  863. {
  864. return _sliderIcon;
  865. }
  866. void Theme::Style::Overlay::setContainerRegion(ContainerRegion* container)
  867. {
  868. if (_container != container)
  869. {
  870. SAFE_RELEASE(_container);
  871. _container = container;
  872. if (container)
  873. {
  874. container->addRef();
  875. }
  876. }
  877. }
  878. Theme::ContainerRegion* Theme::Style::Overlay::getContainerRegion() const
  879. {
  880. return _container;
  881. }
  882. void Theme::generateUVs(const Texture& texture, float x, float y, float width, float height, UVs* uvs)
  883. {
  884. float tw = 1.0f / texture.getWidth();
  885. float th = 1.0f / texture.getHeight();
  886. uvs->u1 = x * tw;
  887. uvs->u2 = (x + width) * tw;
  888. uvs->v1 = 1.0f - (y * th);
  889. uvs->v2 = 1.0f - ((y + height) * th);
  890. }
  891. void Theme::lookUpSprites(const Properties* overlaySpace, Icon** checkBoxIcon, Icon** radioButtonIcon, SliderIcon** sliderIcon,
  892. Cursor** textCursor, Cursor** mouseCursor, ContainerRegion** containerRegion)
  893. {
  894. const char* checkBoxString = overlaySpace->getString("checkBox");
  895. if (checkBoxString)
  896. {
  897. for (unsigned int i = 0; i < _icons.size(); i++)
  898. {
  899. if (strcmp(_icons[i]->getId(), checkBoxString) == 0)
  900. {
  901. *checkBoxIcon = _icons[i];
  902. break;
  903. }
  904. }
  905. }
  906. const char* radioButtonString = overlaySpace->getString("radioButton");
  907. if (radioButtonString)
  908. {
  909. for (unsigned int i = 0; i < _icons.size(); i++)
  910. {
  911. if (strcmp(_icons[i]->getId(), radioButtonString) == 0)
  912. {
  913. *radioButtonIcon = _icons[i];
  914. break;
  915. }
  916. }
  917. }
  918. const char* sliderString = overlaySpace->getString("slider");
  919. if (sliderString)
  920. {
  921. for (unsigned int i = 0; i < _sliders.size(); ++i)
  922. {
  923. if (strcmp(_sliders[i]->getId(), sliderString) == 0)
  924. {
  925. *sliderIcon = _sliders[i];
  926. break;
  927. }
  928. }
  929. }
  930. const char* textCursorString = overlaySpace->getString("textCursor");
  931. if (textCursorString)
  932. {
  933. for (unsigned int i = 0; i < _cursors.size(); ++i)
  934. {
  935. if (strcmp(_cursors[i]->getId(), textCursorString) == 0)
  936. {
  937. *textCursor = _cursors[i];
  938. break;
  939. }
  940. }
  941. }
  942. const char* mouseCursorString = overlaySpace->getString("mouseCursor");
  943. if (mouseCursorString)
  944. {
  945. for (unsigned int i = 0; i < _cursors.size(); ++i)
  946. {
  947. if (strcmp(_cursors[i]->getId(), mouseCursorString) == 0)
  948. {
  949. *mouseCursor = _cursors[i];
  950. break;
  951. }
  952. }
  953. }
  954. const char* containerString = overlaySpace->getString("container");
  955. if (containerString)
  956. {
  957. for (unsigned int i = 0; i < _containers.size(); ++i)
  958. {
  959. if (strcmp(_containers[i]->getId(), containerString) == 0)
  960. {
  961. *containerRegion = _containers[i];
  962. break;
  963. }
  964. }
  965. }
  966. }
  967. }