Theme.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  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("leftCapRegion", &minCapRegion);
  129. space->getVector4("rightCapRegion", &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. // Need to load OVERLAY_NORMAL first so that the other overlays can inherit from it.
  196. Properties* innerSpace = space->getNextNamespace();
  197. while (innerSpace != NULL)
  198. {
  199. const char* innerSpacename = innerSpace->getNamespace();
  200. if (strcmp(innerSpacename, "normal") == 0)
  201. {
  202. Vector4 textColor(0, 0, 0, 1);
  203. if (innerSpace->exists("textColor"))
  204. {
  205. innerSpace->getColor("textColor", &textColor);
  206. }
  207. const char* fontPath = innerSpace->getString("font");
  208. Font* font = NULL;
  209. if (fontPath)
  210. {
  211. font = Font::create(fontPath);
  212. }
  213. unsigned int fontSize = innerSpace->getInt("fontSize");
  214. const char* alignmentString = innerSpace->getString("alignment");
  215. Font::Justify alignment = Font::ALIGN_TOP_LEFT;
  216. if (alignmentString)
  217. {
  218. alignment = Font::getJustifyFromString(alignmentString);
  219. }
  220. bool rightToLeft = innerSpace->getBool("rightToLeft");
  221. Icon* checkBoxIcon = NULL;
  222. Icon* radioButtonIcon = NULL;
  223. SliderIcon* sliderIcon = NULL;
  224. Cursor* textCursor = NULL;
  225. Cursor* mouseCursor = NULL;
  226. ContainerRegion* containerRegion = NULL;
  227. theme->lookUpSprites(innerSpace, &checkBoxIcon, &radioButtonIcon, &sliderIcon, &textCursor, &mouseCursor, &containerRegion);
  228. normal = Theme::Style::Overlay::create();
  229. normal->setContainerRegion(containerRegion);
  230. normal->setTextCursor(textCursor);
  231. normal->setMouseCursor(mouseCursor);
  232. normal->setCheckBoxIcon(checkBoxIcon);
  233. normal->setRadioButtonIcon(radioButtonIcon);
  234. normal->setSliderIcon(sliderIcon);
  235. normal->setTextColor(textColor);
  236. normal->setFont(font);
  237. normal->setFontSize(fontSize);
  238. normal->setTextAlignment(alignment);
  239. normal->setTextRightToLeft(rightToLeft);
  240. theme->_fonts.insert(font);
  241. if (font) font->release();
  242. // Done with this pass.
  243. break;
  244. }
  245. innerSpace = space->getNextNamespace();
  246. }
  247. // At least the OVERLAY_NORMAL is required.
  248. assert(normal);
  249. space->rewind();
  250. innerSpace = space->getNextNamespace();
  251. while (innerSpace != NULL)
  252. {
  253. const char* innerSpacename = innerSpace->getNamespace();
  254. if (strcmp(innerSpacename, "margin") == 0)
  255. {
  256. margin.top = innerSpace->getFloat("top");
  257. margin.bottom = innerSpace->getFloat("bottom");
  258. margin.left = innerSpace->getFloat("left");
  259. margin.right = innerSpace->getFloat("right");
  260. }
  261. else if (strcmp(innerSpacename, "padding") == 0)
  262. {
  263. padding.top = innerSpace->getFloat("top");
  264. padding.bottom = innerSpace->getFloat("bottom");
  265. padding.left = innerSpace->getFloat("left");
  266. padding.right = innerSpace->getFloat("right");
  267. }
  268. else if (strcmp(innerSpacename, "normal") != 0)
  269. {
  270. // Either OVERLAY_FOCUS or OVERLAY_ACTIVE.
  271. // If a property isn't specified, it inherits from OVERLAY_NORMAL.
  272. Vector4 textColor;
  273. if (!innerSpace->getColor("textColor", &textColor))
  274. {
  275. textColor.set(normal->getTextColor());
  276. }
  277. const char* fontPath = innerSpace->getString("font");
  278. Font* font = NULL;
  279. if (fontPath)
  280. {
  281. font = Font::create(fontPath);
  282. }
  283. if (!font)
  284. {
  285. font = normal->getFont();
  286. }
  287. unsigned int fontSize;
  288. if (innerSpace->exists("fontSize"))
  289. {
  290. fontSize = innerSpace->getInt("fontSize");
  291. }
  292. else
  293. {
  294. fontSize = normal->getFontSize();
  295. }
  296. const char* alignmentString = innerSpace->getString("alignment");
  297. Font::Justify alignment;
  298. if (alignmentString)
  299. {
  300. alignment = Font::getJustifyFromString(alignmentString);
  301. }
  302. else
  303. {
  304. alignment = normal->getTextAlignment();
  305. }
  306. bool rightToLeft;
  307. if (innerSpace->exists("rightToLeft"))
  308. {
  309. rightToLeft = innerSpace->getBool("rightToLeft");
  310. }
  311. else
  312. {
  313. rightToLeft = normal->getTextRightToLeft();
  314. }
  315. Icon* checkBoxIcon = NULL;
  316. Icon* radioButtonIcon = NULL;
  317. SliderIcon* sliderIcon = NULL;
  318. Cursor* textCursor = NULL;
  319. Cursor* mouseCursor = NULL;
  320. ContainerRegion* containerRegion = NULL;
  321. theme->lookUpSprites(innerSpace, &checkBoxIcon, &radioButtonIcon, &sliderIcon, &textCursor, &mouseCursor, &containerRegion);
  322. if (!checkBoxIcon)
  323. {
  324. checkBoxIcon = normal->getCheckBoxIcon();
  325. }
  326. if (!radioButtonIcon)
  327. {
  328. radioButtonIcon = normal->getRadioButtonIcon();
  329. }
  330. if (!sliderIcon)
  331. {
  332. sliderIcon = normal->getSliderIcon();
  333. }
  334. if (!textCursor)
  335. {
  336. textCursor = normal->getTextCursor();
  337. }
  338. if (!mouseCursor)
  339. {
  340. mouseCursor = normal->getMouseCursor();
  341. }
  342. if (!containerRegion)
  343. {
  344. containerRegion = normal->getContainerRegion();
  345. }
  346. if (strcmp(innerSpacename, "focus") == 0)
  347. {
  348. focus = Theme::Style::Overlay::create();
  349. focus->setContainerRegion(containerRegion);
  350. focus->setCheckBoxIcon(checkBoxIcon);
  351. focus->setTextCursor(textCursor);
  352. focus->setMouseCursor(mouseCursor);
  353. focus->setCheckBoxIcon(checkBoxIcon);
  354. focus->setRadioButtonIcon(radioButtonIcon);
  355. focus->setSliderIcon(sliderIcon);
  356. focus->setTextColor(textColor);
  357. focus->setFont(font);
  358. focus->setFontSize(fontSize);
  359. focus->setTextAlignment(alignment);
  360. focus->setTextRightToLeft(rightToLeft);
  361. theme->_fonts.insert(font);
  362. }
  363. else if (strcmp(innerSpacename, "active") == 0)
  364. {
  365. active = Theme::Style::Overlay::create();
  366. active->setContainerRegion(containerRegion);
  367. active->setTextCursor(textCursor);
  368. active->setMouseCursor(mouseCursor);
  369. active->setCheckBoxIcon(checkBoxIcon);
  370. active->setRadioButtonIcon(radioButtonIcon);
  371. active->setSliderIcon(sliderIcon);
  372. active->setTextColor(textColor);
  373. active->setFont(font);
  374. active->setFontSize(fontSize);
  375. active->setTextAlignment(alignment);
  376. active->setTextRightToLeft(rightToLeft);
  377. theme->_fonts.insert(font);
  378. }
  379. }
  380. innerSpace = space->getNextNamespace();
  381. }
  382. if (!focus)
  383. {
  384. focus = normal;
  385. focus->addRef();
  386. }
  387. if (!active)
  388. {
  389. active = normal;
  390. active->addRef();
  391. }
  392. Theme::Style* s = new Theme::Style(space->getId(), margin, padding, normal, focus, active);
  393. theme->_styles.push_back(s);
  394. }
  395. space = themeProperties->getNextNamespace();
  396. }
  397. // Add this theme to the cache.
  398. __themeCache.push_back(theme);
  399. SAFE_DELETE(properties);
  400. return theme;
  401. }
  402. Theme::Style* Theme::getStyle(const char* name) const
  403. {
  404. for (unsigned int i = 0, count = _styles.size(); i < count; ++i)
  405. {
  406. if (strcmp(name, _styles[i]->getId()) == 0)
  407. {
  408. return _styles[i];
  409. }
  410. }
  411. return NULL;
  412. }
  413. void Theme::setProjectionMatrix(const Matrix& matrix)
  414. {
  415. _spriteBatch->setProjectionMatrix(matrix);
  416. // Set the matrix on each Font used by the style.
  417. std::set<Font*>::const_iterator it;
  418. for (it = _fonts.begin(); it != _fonts.end(); ++it)
  419. {
  420. (*it)->getSpriteBatch()->setProjectionMatrix(matrix);
  421. }
  422. }
  423. SpriteBatch* Theme::getSpriteBatch() const
  424. {
  425. return _spriteBatch;
  426. }
  427. /***************
  428. * Theme::Icon *
  429. ***************/
  430. Theme::Icon* Theme::Icon::create(const char* id, const Texture& texture, const Vector2& size,
  431. const Vector2& offPosition, const Vector2& onPosition, const Vector4& color)
  432. {
  433. Icon* icon = new Icon(texture, size, offPosition, onPosition, color);
  434. if (id)
  435. {
  436. icon->_id = id;
  437. }
  438. return icon;
  439. }
  440. Theme::Icon::Icon(const Texture& texture, const Vector2& size,
  441. const Vector2& offPosition, const Vector2& onPosition, const Vector4& color)
  442. : _size(size), _color(color)
  443. {
  444. generateUVs(texture, offPosition.x, offPosition.y, size.x, size.y, &_off);
  445. generateUVs(texture, onPosition.x, onPosition.y, size.x, size.y, &_on);
  446. }
  447. Theme::Icon::~Icon()
  448. {
  449. }
  450. const char* Theme::Icon::getId() const
  451. {
  452. return _id.c_str();
  453. }
  454. const Vector2& Theme::Icon::getSize() const
  455. {
  456. return _size;
  457. }
  458. const Vector4& Theme::Icon::getColor() const
  459. {
  460. return _color;
  461. }
  462. const Theme::UVs& Theme::Icon::getOffUVs() const
  463. {
  464. return _off;
  465. }
  466. const Theme::UVs& Theme::Icon::getOnUVs() const
  467. {
  468. return _on;
  469. }
  470. /*********************
  471. * Theme::SliderIcon *
  472. *********************/
  473. Theme::SliderIcon* Theme::SliderIcon::create(const char* id, const Texture& texture, const Vector4& minCapRegion,
  474. const Vector4& maxCapRegion, const Vector4& markerRegion, const Vector4& trackRegion, const Vector4& color)
  475. {
  476. SliderIcon* sliderIcon = new SliderIcon(texture, minCapRegion, maxCapRegion, markerRegion, trackRegion, color);
  477. if (id)
  478. {
  479. sliderIcon->_id = id;
  480. }
  481. return sliderIcon;
  482. }
  483. Theme::SliderIcon::SliderIcon(const Texture& texture, const Vector4& minCapRegion, const Vector4& maxCapRegion,
  484. const Vector4& markerRegion, const Vector4& trackRegion, const Vector4& color)
  485. : _color(color)
  486. {
  487. _minCapSize.set(minCapRegion.z, minCapRegion.w);
  488. _maxCapSize.set(maxCapRegion.z, maxCapRegion.w);
  489. _markerSize.set(markerRegion.z, markerRegion.w);
  490. _trackSize.set(trackRegion.z, trackRegion.w);
  491. generateUVs(texture, minCapRegion.x, minCapRegion.y, minCapRegion.z, minCapRegion.w, &_minCap);
  492. generateUVs(texture, maxCapRegion.x, maxCapRegion.y, maxCapRegion.z, maxCapRegion.w, &_maxCap);
  493. generateUVs(texture, markerRegion.x, markerRegion.y, markerRegion.z, markerRegion.w, &_marker);
  494. generateUVs(texture, trackRegion.x, trackRegion.y, trackRegion.z, trackRegion.w, &_track);
  495. }
  496. Theme::SliderIcon::~SliderIcon()
  497. {
  498. }
  499. const char* Theme::SliderIcon::getId() const
  500. {
  501. return _id.c_str();
  502. }
  503. const Theme::UVs& Theme::SliderIcon::getMinCapUVs() const
  504. {
  505. return _minCap;
  506. }
  507. const Theme::UVs& Theme::SliderIcon::getMaxCapUVs() const
  508. {
  509. return _maxCap;
  510. }
  511. const Theme::UVs& Theme::SliderIcon::getMarkerUVs() const
  512. {
  513. return _marker;
  514. }
  515. const Theme::UVs& Theme::SliderIcon::getTrackUVs() const
  516. {
  517. return _track;
  518. }
  519. const Vector2& Theme::SliderIcon::getMinCapSize() const
  520. {
  521. return _minCapSize;
  522. }
  523. const Vector2& Theme::SliderIcon::getMaxCapSize() const
  524. {
  525. return _maxCapSize;
  526. }
  527. const Vector2& Theme::SliderIcon::getMarkerSize() const
  528. {
  529. return _markerSize;
  530. }
  531. const Vector2& Theme::SliderIcon::getTrackSize() const
  532. {
  533. return _trackSize;
  534. }
  535. const Vector4& Theme::SliderIcon::getColor() const
  536. {
  537. return _color;
  538. }
  539. /*****************
  540. * Theme::Cursor *
  541. *****************/
  542. Theme::Cursor* Theme::Cursor::create(const char* id, const Texture& texture, const Rectangle& region, const Vector4& color)
  543. {
  544. Cursor* cursor = new Cursor(texture, region, color);
  545. if (id)
  546. {
  547. cursor->_id = id;
  548. }
  549. return cursor;
  550. }
  551. Theme::Cursor::Cursor(const Texture& texture, const Rectangle& region, const Vector4& color)
  552. : _color(color)
  553. {
  554. _size.set(region.width, region.height);
  555. generateUVs(texture, region.x, region.y, region.width, region.height, &_uvs);
  556. }
  557. Theme::Cursor::~Cursor()
  558. {
  559. }
  560. const char* Theme::Cursor::getId() const
  561. {
  562. return _id.data();
  563. }
  564. const Theme::UVs& Theme::Cursor::getUVs() const
  565. {
  566. return _uvs;
  567. }
  568. const Vector2& Theme::Cursor::getSize() const
  569. {
  570. return _size;
  571. }
  572. const Vector4& Theme::Cursor::getColor() const
  573. {
  574. return _color;
  575. }
  576. /**************************
  577. * Theme::ContainerRegion *
  578. **************************/
  579. Theme::ContainerRegion* Theme::ContainerRegion::create(const char* id, const Texture& texture, const Rectangle& region, const Theme::Border& border, const Vector4& color)
  580. {
  581. ContainerRegion* containerRegion = new ContainerRegion(texture, region, border, color);
  582. if (id)
  583. {
  584. containerRegion->_id = id;
  585. }
  586. return containerRegion;
  587. }
  588. Theme::ContainerRegion::ContainerRegion(const Texture& texture, const Rectangle& region, const Theme::Border& border, const Vector4& color)
  589. : _border(border), _color(color)
  590. {
  591. // Need to convert pixel coords to unit space by dividing by texture size.
  592. float tw = 1.0f / (float)texture.getWidth();
  593. float th = 1.0f / (float)texture.getHeight();
  594. // Can calculate all measurements in advance.
  595. float leftEdge = region.x * tw;
  596. float rightEdge = (region.x + region.width) * tw;
  597. float leftBorder = (region.x + border.left) * tw;
  598. float rightBorder = (region.x + region.width - border.right) * tw;
  599. float topEdge = 1.0f - (region.y * th);
  600. float bottomEdge = 1.0f - ((region.y + region.height) * th);
  601. float topBorder = 1.0f - ((region.y + border.top) * th);
  602. float bottomBorder = 1.0f - ((region.y + region.height - border.bottom) * th);
  603. // There are 9 sets of UVs to set.
  604. _uvs[TOP_LEFT].u1 = leftEdge;
  605. _uvs[TOP_LEFT].v1 = topEdge;
  606. _uvs[TOP_LEFT].u2 = leftBorder;
  607. _uvs[TOP_LEFT].v2 = topBorder;
  608. _uvs[TOP].u1 = leftBorder;
  609. _uvs[TOP].v1 = topEdge;
  610. _uvs[TOP].u2 = rightBorder;
  611. _uvs[TOP].v2 = topBorder;
  612. _uvs[TOP_RIGHT].u1 = rightBorder;
  613. _uvs[TOP_RIGHT].v1 = topEdge;
  614. _uvs[TOP_RIGHT].u2 = rightEdge;
  615. _uvs[TOP_RIGHT].v2 = topBorder;
  616. _uvs[LEFT].u1 = leftEdge;
  617. _uvs[LEFT].v1 = topBorder;
  618. _uvs[LEFT].u2 = leftBorder;
  619. _uvs[LEFT].v2 = bottomBorder;
  620. _uvs[CENTER].u1 = leftBorder;
  621. _uvs[CENTER].v1 = topBorder;
  622. _uvs[CENTER].u2 = rightBorder;
  623. _uvs[CENTER].v2 = bottomBorder;
  624. _uvs[RIGHT].u1 = rightBorder;
  625. _uvs[RIGHT].v1 = topBorder;
  626. _uvs[RIGHT].u2 = rightEdge;
  627. _uvs[RIGHT].v2 = bottomBorder;
  628. _uvs[BOTTOM_LEFT].u1 = leftEdge;
  629. _uvs[BOTTOM_LEFT].v1 = bottomBorder;
  630. _uvs[BOTTOM_LEFT].u2 = leftBorder;
  631. _uvs[BOTTOM_LEFT].v2 = bottomEdge;
  632. _uvs[BOTTOM].u1 = leftBorder;
  633. _uvs[BOTTOM].v1 = bottomBorder;
  634. _uvs[BOTTOM].u2 = rightBorder;
  635. _uvs[BOTTOM].v2 = bottomEdge;
  636. _uvs[BOTTOM_RIGHT].u1 = rightBorder;
  637. _uvs[BOTTOM_RIGHT].v1 = bottomBorder;
  638. _uvs[BOTTOM_RIGHT].u2 = rightEdge;
  639. _uvs[BOTTOM_RIGHT].v2 = bottomEdge;
  640. }
  641. Theme::ContainerRegion::~ContainerRegion()
  642. {
  643. }
  644. const char* Theme::ContainerRegion::getId() const
  645. {
  646. return _id.c_str();
  647. }
  648. const Theme::Border& Theme::ContainerRegion::getBorder() const
  649. {
  650. return _border;
  651. }
  652. const Theme::UVs& Theme::ContainerRegion::getUVs(ContainerArea area) const
  653. {
  654. return _uvs[area];
  655. }
  656. const Vector4& Theme::ContainerRegion::getColor() const
  657. {
  658. return _color;
  659. }
  660. /****************
  661. * Theme::Style *
  662. ****************/
  663. Theme::Style::Style(const char* id, const Theme::Margin& margin, const Theme::Padding& padding,
  664. Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active)
  665. : _id(id), _margin(margin), _padding(padding)
  666. {
  667. _overlays[OVERLAY_NORMAL] = normal;
  668. _overlays[OVERLAY_FOCUS] = focus;
  669. _overlays[OVERLAY_ACTIVE] = active;
  670. }
  671. Theme::Style::~Style()
  672. {
  673. for (int i = 0; i < MAX_OVERLAYS; i++)
  674. {
  675. SAFE_RELEASE(_overlays[i]);
  676. }
  677. }
  678. const char* Theme::Style::getId() const
  679. {
  680. return _id.data();
  681. }
  682. Theme::Style::Overlay* Theme::Style::getOverlay(OverlayType overlayType) const
  683. {
  684. return _overlays[overlayType];
  685. }
  686. const Theme::Margin& Theme::Style::getMargin() const
  687. {
  688. return _margin;
  689. }
  690. const Theme::Padding& Theme::Style::getPadding() const
  691. {
  692. return _padding;
  693. }
  694. /*************************
  695. * Theme::Style::Overlay *
  696. *************************/
  697. Theme::Style::Overlay* Theme::Style::Overlay::create()
  698. {
  699. Overlay* overlay = new Overlay();
  700. return overlay;
  701. }
  702. Theme::Style::Overlay::Overlay() : _container(NULL), _textCursor(NULL), _mouseCursor(NULL), _checkBoxIcon(NULL), _radioButtonIcon(NULL), _sliderIcon(NULL), _font(NULL)
  703. {
  704. }
  705. Theme::Style::Overlay::~Overlay()
  706. {
  707. SAFE_RELEASE(_container);
  708. SAFE_RELEASE(_checkBoxIcon);
  709. SAFE_RELEASE(_radioButtonIcon);
  710. SAFE_RELEASE(_sliderIcon);
  711. SAFE_RELEASE(_mouseCursor);
  712. SAFE_RELEASE(_textCursor);
  713. SAFE_RELEASE(_font);
  714. }
  715. Font* Theme::Style::Overlay::getFont() const
  716. {
  717. return _font;
  718. }
  719. void Theme::Style::Overlay::setFont(Font* font)
  720. {
  721. if (_font != font)
  722. {
  723. SAFE_RELEASE(_font);
  724. _font = font;
  725. if (_font)
  726. {
  727. _font->addRef();
  728. }
  729. }
  730. }
  731. unsigned int Theme::Style::Overlay::getFontSize() const
  732. {
  733. return _fontSize;
  734. }
  735. void Theme::Style::Overlay::setFontSize(unsigned int fontSize)
  736. {
  737. _fontSize = fontSize;
  738. }
  739. Font::Justify Theme::Style::Overlay::getTextAlignment() const
  740. {
  741. return _alignment;
  742. }
  743. void Theme::Style::Overlay::setTextAlignment(Font::Justify alignment)
  744. {
  745. _alignment = alignment;
  746. }
  747. bool Theme::Style::Overlay::getTextRightToLeft() const
  748. {
  749. return _textRightToLeft;
  750. }
  751. void Theme::Style::Overlay::setTextRightToLeft(bool rightToLeft)
  752. {
  753. _textRightToLeft = rightToLeft;
  754. }
  755. const Vector4& Theme::Style::Overlay::getTextColor() const
  756. {
  757. return _textColor;
  758. }
  759. void Theme::Style::Overlay::setTextColor(const Vector4& color)
  760. {
  761. _textColor = color;
  762. }
  763. Theme::Cursor* Theme::Style::Overlay::getTextCursor() const
  764. {
  765. return _textCursor;
  766. }
  767. void Theme::Style::Overlay::setTextCursor(Theme::Cursor* cursor)
  768. {
  769. if (_textCursor != cursor)
  770. {
  771. SAFE_RELEASE(_textCursor);
  772. _textCursor = cursor;
  773. if (cursor)
  774. {
  775. cursor->addRef();
  776. }
  777. }
  778. }
  779. Theme::Cursor* Theme::Style::Overlay::getMouseCursor() const
  780. {
  781. return _mouseCursor;
  782. }
  783. void Theme::Style::Overlay::setMouseCursor(Theme::Cursor* cursor)
  784. {
  785. if (_mouseCursor != cursor)
  786. {
  787. SAFE_RELEASE(_mouseCursor);
  788. _mouseCursor = cursor;
  789. if (cursor)
  790. {
  791. cursor->addRef();
  792. }
  793. }
  794. }
  795. void Theme::Style::Overlay::setCheckBoxIcon(Icon* icon)
  796. {
  797. if (_checkBoxIcon != icon)
  798. {
  799. SAFE_RELEASE(_checkBoxIcon);
  800. _checkBoxIcon = icon;
  801. if (icon)
  802. {
  803. icon->addRef();
  804. }
  805. }
  806. }
  807. Theme::Icon* Theme::Style::Overlay::getCheckBoxIcon() const
  808. {
  809. return _checkBoxIcon;
  810. }
  811. void Theme::Style::Overlay::setRadioButtonIcon(Icon* icon)
  812. {
  813. if (_radioButtonIcon != icon)
  814. {
  815. SAFE_RELEASE(_radioButtonIcon);
  816. _radioButtonIcon = icon;
  817. if (icon)
  818. {
  819. icon->addRef();
  820. }
  821. }
  822. }
  823. Theme::Icon* Theme::Style::Overlay::getRadioButtonIcon() const
  824. {
  825. return _radioButtonIcon;
  826. }
  827. void Theme::Style::Overlay::setSliderIcon(SliderIcon* slider)
  828. {
  829. if (_sliderIcon != slider)
  830. {
  831. SAFE_RELEASE(_sliderIcon);
  832. _sliderIcon = slider;
  833. if (slider)
  834. {
  835. slider->addRef();
  836. }
  837. }
  838. }
  839. Theme::SliderIcon* Theme::Style::Overlay::getSliderIcon() const
  840. {
  841. return _sliderIcon;
  842. }
  843. void Theme::Style::Overlay::setContainerRegion(ContainerRegion* container)
  844. {
  845. if (_container != container)
  846. {
  847. SAFE_RELEASE(_container);
  848. _container = container;
  849. if (container)
  850. {
  851. container->addRef();
  852. }
  853. }
  854. }
  855. Theme::ContainerRegion* Theme::Style::Overlay::getContainerRegion() const
  856. {
  857. return _container;
  858. }
  859. void Theme::generateUVs(const Texture& texture, float x, float y, float width, float height, UVs* uvs)
  860. {
  861. float tw = 1.0f / texture.getWidth();
  862. float th = 1.0f / texture.getHeight();
  863. uvs->u1 = x * tw;
  864. uvs->u2 = (x + width) * tw;
  865. uvs->v1 = 1.0f - (y * th);
  866. uvs->v2 = 1.0f - ((y + height) * th);
  867. }
  868. void Theme::lookUpSprites(const Properties* overlaySpace, Icon** checkBoxIcon, Icon** radioButtonIcon, SliderIcon** sliderIcon,
  869. Cursor** textCursor, Cursor** mouseCursor, ContainerRegion** containerRegion)
  870. {
  871. const char* checkBoxString = overlaySpace->getString("checkBox");
  872. if (checkBoxString)
  873. {
  874. for (unsigned int i = 0; i < _icons.size(); i++)
  875. {
  876. if (strcmp(_icons[i]->getId(), checkBoxString) == 0)
  877. {
  878. *checkBoxIcon = _icons[i];
  879. break;
  880. }
  881. }
  882. }
  883. const char* radioButtonString = overlaySpace->getString("radioButton");
  884. if (radioButtonString)
  885. {
  886. for (unsigned int i = 0; i < _icons.size(); i++)
  887. {
  888. if (strcmp(_icons[i]->getId(), radioButtonString) == 0)
  889. {
  890. *radioButtonIcon = _icons[i];
  891. break;
  892. }
  893. }
  894. }
  895. const char* sliderString = overlaySpace->getString("slider");
  896. if (sliderString)
  897. {
  898. for (unsigned int i = 0; i < _sliders.size(); ++i)
  899. {
  900. if (strcmp(_sliders[i]->getId(), sliderString) == 0)
  901. {
  902. *sliderIcon = _sliders[i];
  903. break;
  904. }
  905. }
  906. }
  907. const char* textCursorString = overlaySpace->getString("textCursor");
  908. if (textCursorString)
  909. {
  910. for (unsigned int i = 0; i < _cursors.size(); ++i)
  911. {
  912. if (strcmp(_cursors[i]->getId(), textCursorString) == 0)
  913. {
  914. *textCursor = _cursors[i];
  915. break;
  916. }
  917. }
  918. }
  919. const char* mouseCursorString = overlaySpace->getString("mouseCursor");
  920. if (mouseCursorString)
  921. {
  922. for (unsigned int i = 0; i < _cursors.size(); ++i)
  923. {
  924. if (strcmp(_cursors[i]->getId(), mouseCursorString) == 0)
  925. {
  926. *mouseCursor = _cursors[i];
  927. break;
  928. }
  929. }
  930. }
  931. const char* containerString = overlaySpace->getString("container");
  932. if (containerString)
  933. {
  934. for (unsigned int i = 0; i < _containers.size(); ++i)
  935. {
  936. if (strcmp(_containers[i]->getId(), containerString) == 0)
  937. {
  938. *containerRegion = _containers[i];
  939. break;
  940. }
  941. }
  942. }
  943. }
  944. }