Text.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #include "Base.h"
  2. #include "Text.h"
  3. #include "Matrix.h"
  4. #include "Scene.h"
  5. namespace gameplay
  6. {
  7. Text::Text() :
  8. _font(NULL), _text(""), _size(0), _width(0), _height(0), _wrap(true), _rightToLeft(false),
  9. _align(Font::ALIGN_TOP_LEFT), _clip(Rectangle(0, 0, 0, 0)),
  10. _opacity(1.0f), _color(Vector4::one())
  11. {
  12. }
  13. Text::~Text()
  14. {
  15. SAFE_RELEASE(_font);
  16. }
  17. Text& Text::operator=(const Text& text)
  18. {
  19. return *this;
  20. }
  21. Text* Text::create(const char* fontPath, const char* str, const Vector4& color, unsigned int size)
  22. {
  23. GP_ASSERT(fontPath);
  24. GP_ASSERT(str);
  25. Font* font = Font::create(fontPath);
  26. if (size == 0)
  27. {
  28. size = font->_size;
  29. }
  30. else
  31. {
  32. // Delegate to closest sized font
  33. font = font->findClosestSize(size);
  34. size = font->_size;
  35. }
  36. unsigned int widthOut, heightOut;
  37. font->measureText(str, size, &widthOut, &heightOut);
  38. Text* text = new Text();
  39. text->_font = font;
  40. text->_text = str;
  41. text->_size = size;
  42. text->_width = (float)widthOut + 1;
  43. text->_height = (float)heightOut + 1;
  44. text->_color = color;
  45. return text;
  46. }
  47. Text* Text::create(Properties* properties)
  48. {
  49. // Check if the Properties is valid and has a valid namespace.
  50. if (!properties || strcmp(properties->getNamespace(), "text") != 0)
  51. {
  52. GP_ERROR("Properties object must be non-null and have namespace equal to 'text'.");
  53. return NULL;
  54. }
  55. // Get font path.
  56. const char* fontPath = properties->getString("font");
  57. if (fontPath == NULL || strlen(fontPath) == 0)
  58. {
  59. GP_ERROR("Text is missing required font file path.");
  60. return NULL;
  61. }
  62. // Get text
  63. const char* text = properties->getString("text");
  64. if (text == NULL || strlen(text) == 0)
  65. {
  66. GP_ERROR("Text is missing required 'text' value.");
  67. return NULL;
  68. }
  69. // Get size
  70. int size = properties->getInt("size"); // Default return is 0 if a value doesn't exist
  71. if (size < 0)
  72. {
  73. GP_WARN("Text size must be a positive value, with zero being default font size. Using default font size.");
  74. size = 0;
  75. }
  76. // Get text color
  77. Vector4 color = Vector4::one();
  78. if (properties->exists("color"))
  79. {
  80. switch (properties->getType("color"))
  81. {
  82. case Properties::VECTOR3:
  83. color.w = 1.0f;
  84. properties->getVector3("color", (Vector3*)&color);
  85. break;
  86. case Properties::VECTOR4:
  87. properties->getVector4("color", &color);
  88. break;
  89. case Properties::STRING:
  90. default:
  91. properties->getColor("color", &color);
  92. break;
  93. }
  94. }
  95. // Create
  96. return Text::create(fontPath, text, color, size);
  97. }
  98. void Text::setText(const char* str)
  99. {
  100. _text = str;
  101. }
  102. const char* Text::getText() const
  103. {
  104. return _text.c_str();
  105. }
  106. unsigned int Text::getSize() const
  107. {
  108. return _size;
  109. }
  110. void Text::setWidth(float width)
  111. {
  112. _width = width;
  113. }
  114. float Text::getWidth() const
  115. {
  116. return _width;
  117. }
  118. void Text::setHeight(float height)
  119. {
  120. _height = height;
  121. }
  122. float Text::getHeight() const
  123. {
  124. return _height;
  125. }
  126. void Text::setWrap(bool wrap)
  127. {
  128. _wrap = wrap;
  129. }
  130. bool Text::getWrap() const
  131. {
  132. return _wrap;
  133. }
  134. void Text::setRightToLeft(bool rightToLeft)
  135. {
  136. _rightToLeft = rightToLeft;
  137. }
  138. bool Text::getRightToLeft() const
  139. {
  140. return _rightToLeft;
  141. }
  142. void Text::setJustify(Font::Justify align)
  143. {
  144. _align = align;
  145. }
  146. Font::Justify Text::getJustify() const
  147. {
  148. return _align;
  149. }
  150. void Text::setClip(const Rectangle& clip)
  151. {
  152. _clip = clip;
  153. }
  154. const Rectangle& Text::getClip() const
  155. {
  156. return _clip;
  157. }
  158. void Text::setOpacity(float opacity)
  159. {
  160. _opacity = opacity;
  161. }
  162. float Text::getOpacity() const
  163. {
  164. return _opacity;
  165. }
  166. void Text::setColor(const Vector4& color)
  167. {
  168. _color = color;
  169. }
  170. const Vector4& Text::getColor() const
  171. {
  172. return _color;
  173. }
  174. Drawable* Text::clone(NodeCloneContext& context)
  175. {
  176. Text* textClone = new Text();
  177. textClone->_font = _font;
  178. _font->addRef();
  179. textClone->_text = _text;
  180. textClone->_size = _size;
  181. textClone->_width = _width;
  182. textClone->_height = _height;
  183. textClone->_wrap = _wrap;
  184. textClone->_rightToLeft = _rightToLeft;
  185. textClone->_align = _align;
  186. textClone->_clip = _clip;
  187. textClone->_opacity = _opacity;
  188. textClone->_color = _color;
  189. return textClone;
  190. }
  191. unsigned int Text::draw(bool wireframe)
  192. {
  193. // Apply scene camera projection and translation offsets
  194. Rectangle viewport = Game::getInstance()->getViewport();
  195. Vector3 position = Vector3::zero();
  196. // Font is always using a offset projection matrix to top-left. So we need to adjust it back to cartesian
  197. position.x += viewport.width / 2;
  198. position.y += viewport.height / 2;
  199. Rectangle clipViewport = _clip;
  200. if (_node && _node->getScene())
  201. {
  202. Camera* activeCamera = _node->getScene()->getActiveCamera();
  203. if (activeCamera)
  204. {
  205. Node* cameraNode = _node->getScene()->getActiveCamera()->getNode();
  206. if (cameraNode)
  207. {
  208. // Camera translation offsets
  209. position.x -= cameraNode->getTranslationWorld().x;
  210. position.y += cameraNode->getTranslationWorld().y - getHeight();
  211. }
  212. }
  213. // Apply node translation offsets
  214. Vector3 translation = _node->getTranslationWorld();
  215. position.x += translation.x;
  216. position.y -= translation.y;
  217. if (!clipViewport.isEmpty())
  218. {
  219. clipViewport.x += position.x;
  220. clipViewport.y += position.y;
  221. }
  222. }
  223. _font->start();
  224. _font->drawText(_text.c_str(), Rectangle(position.x, position.y, _width, _height),
  225. Vector4(_color.x, _color.y, _color.z, _color.w * _opacity), _size,
  226. _align, _wrap, _rightToLeft, clipViewport);
  227. _font->finish();
  228. return 1;
  229. }
  230. int Text::getPropertyId(TargetType type, const char* propertyIdStr)
  231. {
  232. GP_ASSERT(propertyIdStr);
  233. if (type == AnimationTarget::TRANSFORM)
  234. {
  235. if (strcmp(propertyIdStr, "ANIMATE_OPACITY") == 0)
  236. {
  237. return Text::ANIMATE_OPACITY;
  238. }
  239. else if (strcmp(propertyIdStr, "ANIMATE_COLOR") == 0)
  240. {
  241. return Text::ANIMATE_COLOR;
  242. }
  243. }
  244. return AnimationTarget::getPropertyId(type, propertyIdStr);
  245. }
  246. unsigned int Text::getAnimationPropertyComponentCount(int propertyId) const
  247. {
  248. switch (propertyId)
  249. {
  250. case ANIMATE_OPACITY:
  251. return 1;
  252. case ANIMATE_COLOR:
  253. return 4;
  254. default:
  255. return -1;
  256. }
  257. }
  258. void Text::getAnimationPropertyValue(int propertyId, AnimationValue* value)
  259. {
  260. GP_ASSERT(value);
  261. switch (propertyId)
  262. {
  263. case ANIMATE_OPACITY:
  264. value->setFloat(0, _opacity);
  265. break;
  266. case ANIMATE_COLOR:
  267. value->setFloat(0, _color.x);
  268. value->setFloat(1, _color.y);
  269. value->setFloat(2, _color.z);
  270. value->setFloat(3, _color.w);
  271. break;
  272. default:
  273. break;
  274. }
  275. }
  276. void Text::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
  277. {
  278. GP_ASSERT(value);
  279. switch(propertyId)
  280. {
  281. case ANIMATE_OPACITY:
  282. setOpacity(Curve::lerp(blendWeight, _opacity, value->getFloat(0)));
  283. break;
  284. case ANIMATE_COLOR:
  285. setColor(Vector4(Curve::lerp(blendWeight, _color.x, value->getFloat(0)),
  286. Curve::lerp(blendWeight, _color.x, value->getFloat(1)),
  287. Curve::lerp(blendWeight, _color.x, value->getFloat(2)),
  288. Curve::lerp(blendWeight, _color.x, value->getFloat(3))));
  289. break;
  290. default:
  291. break;
  292. }
  293. }
  294. }