ProgressBar.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #include "ProgressBar.h"
  2. #include "RenderState.h"
  3. #include <sstream>
  4. #include "Serialize.h"
  5. #include "STDRenderer.h"
  6. namespace oxygine
  7. {
  8. void fill_tex_coord(vertexPCT2& vt, unsigned int rgba, const Vector2& pnt, float nu, float nv)
  9. {
  10. vt.color = rgba;
  11. vt.z = 0;
  12. vt.x = pnt.x;
  13. vt.y = pnt.y;
  14. vt.u = nu;
  15. vt.v = nv;
  16. }
  17. void rotateVector(Vector2& v, float rad)
  18. {
  19. Vector2 vh;
  20. vh.x = v.x * cosf(rad) - v.y * sinf(rad);
  21. vh.y = v.x * sinf(rad) + v.y * cosf(rad);
  22. v = vh;
  23. }
  24. float Angle(const Vector2& current, const Vector2* pRelative)
  25. {
  26. if (pRelative)
  27. {
  28. Vector2 s = current, t = *pRelative;
  29. s.normalize(); t.normalize();
  30. return acosf(s.dot(t));
  31. }
  32. else return atan2f(current.y, current.x);
  33. }
  34. ProgressBar::ProgressBar(): _progress(1.0f), _direction(dir_0)
  35. {
  36. }
  37. ProgressBar::~ProgressBar()
  38. {
  39. }
  40. void ProgressBar::copyFrom(const ProgressBar& src, cloneOptions opt)
  41. {
  42. _Sprite::copyFrom(src, opt);
  43. _progress = src._progress;
  44. _direction = src._direction;
  45. _originalFrame = src._originalFrame;
  46. }
  47. void ProgressBar::animFrameChanged(const AnimationFrame& f)
  48. {
  49. _originalFrame = f;
  50. _update();
  51. }
  52. void ProgressBar::_update()
  53. {
  54. if (!_frame.getDiffuse().base)
  55. return;
  56. RectF newSrc = _originalFrame.getSrcRect();
  57. RectF newDest = _originalFrame.getDestRect();
  58. float inv_progress = 1.0f - _progress;
  59. switch (_direction)
  60. {
  61. case dir_180:
  62. newSrc.pos.x += newSrc.size.x * inv_progress;
  63. newDest.pos.x += newDest.size.x * inv_progress;
  64. //break; do not break
  65. case dir_0:
  66. newSrc.size.x = newSrc.size.x * _progress;
  67. newDest.size.x = newDest.size.x * _progress;
  68. break;
  69. case dir_90:
  70. newSrc.pos.y += newSrc.size.y * inv_progress;
  71. newDest.pos.y += newDest.size.y * inv_progress;
  72. //break; do not break
  73. case dir_270:
  74. newSrc.size.y = newSrc.size.y * _progress;
  75. newDest.size.y = newDest.size.y * _progress;
  76. break;
  77. }
  78. Vector2 newSize = _originalFrame.getSize() * _progress;
  79. _frame.init(_frame.getResAnim(), _frame.getDiffuse(), newSrc, newDest, newSize);
  80. //_vstyle._material.srcRect = newSrc;
  81. }
  82. void ProgressBar::doRender(const RenderState& rs)
  83. {
  84. if (_progress == 0)
  85. return;
  86. if (((_direction != __dir_radial_ccw) && (_direction != dir_radial_cw)) || (_progress == 1.0f))
  87. {
  88. _Sprite::doRender(rs);
  89. return;
  90. }
  91. STDRenderer* renderer = safeCast<STDRenderer*>(rs.renderer);
  92. _vstyle._apply(rs);
  93. const Diffuse& df = _frame.getDiffuse();
  94. if (df.base)
  95. {
  96. renderer->setTexture(df.base, df.alpha, df.premultiplied);
  97. RectF destRect = _Sprite::getDestRect();
  98. RectF srcRect = _frame.getSrcRect();
  99. float u = srcRect.pos.x;
  100. float v = srcRect.pos.y;
  101. float du = srcRect.size.x;
  102. float dv = srcRect.size.y;
  103. u += du / 2.f;
  104. v += dv / 2.f;
  105. Vector2 pos = destRect.pos;
  106. const Vector2& size = destRect.size;
  107. pos += size / 2.f;
  108. Vector2 vecCenter(pos.x, pos.y);
  109. Vector2 vdiag = Vector2(pos.x + size.x / 2.f, pos.y - size.y / 2.f) - vecCenter;
  110. Vector2 vdiag2 = Vector2(pos.x + size.x / 2.f, pos.y + size.y / 2.f) - vecCenter;
  111. float lenDiag = vdiag.length();
  112. Vector2 vecCircle(pos.x, pos.y - lenDiag);
  113. Vector2 vecRad = vecCircle - vecCenter;
  114. float progress = _progress;
  115. float fP = MATH_PI * 2.f * progress;
  116. rotateVector(vecRad, fP);
  117. Vector2 p1(0.f, 0.f);
  118. Vector2 p2(0.f, 0.f);
  119. Vector2 p3(0.f, 0.f);
  120. Vector2 vert(0.f, -1.f);
  121. float fA1 = Angle(vdiag, &vert);
  122. float fA2 = Angle(vdiag2, &vdiag);
  123. const int MAX_TRI = 6;
  124. float u1, v1, u2, v2, u3, v3;
  125. float result = 0.f;
  126. float angles[ 6 ];
  127. angles[ 0 ] = fA1;
  128. angles[ 1 ] = fA2;
  129. angles[ 2 ] = fA1;
  130. angles[ 3 ] = fA1;
  131. angles[ 4 ] = fA2;
  132. angles[ 5 ] = fA1;
  133. for (int i = 0; i < MAX_TRI; i++)
  134. {
  135. float limitLo = 0.f;
  136. float limitHi = 0.f;
  137. for (int j = 0; j < i; j++)
  138. limitLo += angles[ j ];
  139. limitHi = limitLo + angles[ i ];
  140. bool bOverHi = fP > limitHi;
  141. bool bOverLo = fP < limitLo;
  142. if (i && bOverLo)
  143. continue;
  144. vertexPCT2 vertices[4];
  145. vertexPCT2* pv = vertices;
  146. switch (i)
  147. {
  148. case 0:
  149. {
  150. result = bOverHi ? size.x / 2.f : vecRad.x;
  151. p1 = Vector2(pos.x, pos.y);
  152. p2 = Vector2(pos.x, pos.y - size.y / 2.f);
  153. p3 = Vector2(pos.x + result, pos.y - size.y / 2.f);
  154. float fPercent = result / size.x;
  155. float fDU = du * fPercent;
  156. u1 = u;
  157. v1 = v;
  158. u2 = u;
  159. v2 = (v - dv / 2.f);
  160. u3 = (u + fDU);
  161. v3 = (v - dv / 2.f);
  162. }
  163. break;
  164. case 1:
  165. {
  166. result = bOverHi ? size.y / 2.f : (vecRad.y) ;
  167. p1 = Vector2(pos.x, pos.y);
  168. p2 = Vector2(pos.x + size.x / 2.f, pos.y - size.y / 2.f);
  169. p3 = Vector2(pos.x + size.x / 2.f, pos.y + result);
  170. float fPercent = result / size.y;
  171. float fDV = dv * fPercent;
  172. u2 = u + du / 2.f;
  173. v2 = (v - dv / 2.f);
  174. u3 = u + du / 2.f;
  175. v3 = (v + fDV);
  176. }
  177. break;
  178. case 2:
  179. {
  180. result = bOverHi ? 0.f : vecRad.x ;
  181. p1 = Vector2(pos.x, pos.y);
  182. p2 = Vector2(pos.x + size.x / 2.f, pos.y + size.y / 2.f);
  183. p3 = Vector2(pos.x + result, pos.y + size.y / 2.f);
  184. float fPercent = result / size.x;
  185. float fDU = du * fPercent;
  186. u2 = u + du / 2.f;
  187. v2 = (v + dv / 2.f);
  188. u3 = u + fDU;
  189. v3 = (v + dv / 2.f);
  190. }
  191. break;
  192. case 3:
  193. {
  194. result = bOverHi ? (-size.x / 2.f) : vecRad.x ;
  195. p1 = Vector2(pos.x, pos.y);
  196. p2 = Vector2(pos.x , pos.y + size.y / 2.f);
  197. p3 = Vector2(pos.x + result, pos.y + size.y / 2.f);
  198. float fPercent = result / size.x;
  199. float fDU = du * fPercent;
  200. u2 = u;
  201. v2 = (v + dv / 2.f);
  202. u3 = u + fDU;
  203. v3 = (v + dv / 2.f);
  204. }
  205. break;
  206. case 4:
  207. {
  208. result = bOverHi ? (-size.y / 2.f) : vecRad.y ;
  209. p1 = Vector2(pos.x, pos.y);
  210. p2 = Vector2(pos.x - (size.x / 2.f) , pos.y + size.y / 2.f);
  211. p3 = Vector2(pos.x - (size.x / 2.f), pos.y + result);
  212. float fPercent = result / size.y;
  213. float fDV = dv * fPercent;
  214. u2 = u - du / 2.f;
  215. v2 = (v + dv / 2.f);
  216. u3 = u - du / 2.f;
  217. v3 = (v + fDV);
  218. }
  219. break;
  220. case 5:
  221. {
  222. result = bOverHi ? (0.f) : vecRad.x ;
  223. p1 = Vector2(pos.x, pos.y);
  224. p2 = Vector2(pos.x - (size.x / 2.f), pos.y - (size.y / 2.f));
  225. p3 = Vector2(pos.x + result, pos.y - (size.y / 2.f));
  226. float fPercent = result / size.x;
  227. float fDU = du * fPercent;
  228. u2 = u - du / 2.f;
  229. v2 = (v - dv / 2.f);
  230. u3 = u + fDU;
  231. v3 = (v - dv / 2.f);
  232. }
  233. break;
  234. default:
  235. continue;
  236. }
  237. u1 = u;
  238. v1 = v;
  239. p1 = rs.transform.transform(p1);
  240. p2 = rs.transform.transform(p2);
  241. p3 = rs.transform.transform(p3);
  242. unsigned int rgba = getColor().rgba();
  243. fill_tex_coord(*pv, rgba, p1, u1, v1);
  244. pv++;
  245. fill_tex_coord(*pv, rgba, p2, u2, v2);
  246. pv++;
  247. fill_tex_coord(*pv, rgba, p3, u3, v3);
  248. pv++;
  249. fill_tex_coord(*pv, rgba, p2, u2, v2);
  250. pv++;
  251. rs.renderer->addVertices(vertices, sizeof(vertices));
  252. }
  253. }
  254. }
  255. std::string ProgressBar::dump(const dumpOptions& options) const
  256. {
  257. std::stringstream stream;
  258. stream << "{ProgressBar}\n";
  259. const char* dir = "dir_0";
  260. switch (_direction)
  261. {
  262. case dir_90:
  263. dir = "dir_90";
  264. break;
  265. case dir_180:
  266. dir = "dir_180";
  267. break;
  268. case dir_270:
  269. dir = "dir_270";
  270. break;
  271. case dir_radial_cw:
  272. dir = "dir_radial_cw";
  273. break;
  274. case __dir_radial_ccw:
  275. dir = "dir_radial_ccw";
  276. break;
  277. }
  278. stream << " direction=" << dir << "";
  279. stream << "\n" << _Sprite::dump(options);
  280. return stream.str();
  281. }
  282. RectF ProgressBar::getDestRect() const
  283. {
  284. return calcDestRectF(_frame.getDestRect(), _frame.getSize());
  285. }
  286. void ProgressBar::setProgress(float f)
  287. {
  288. _progress = scalar::clamp(f, 0.0f, 1.0f);
  289. Event ev(PROGRESS_CHANGED);
  290. dispatchEvent(&ev);
  291. if (_direction == __dir_radial_ccw || _direction == dir_radial_cw)
  292. return;
  293. _update();
  294. }
  295. void ProgressBar::setDirection(direction dir)
  296. {
  297. _direction = dir;
  298. if (_direction == __dir_radial_ccw || _direction == dir_radial_cw)
  299. {
  300. _frame = _originalFrame;
  301. return;
  302. }
  303. _update();
  304. }
  305. float ProgressBar::getProgress() const
  306. {
  307. return _progress;
  308. }
  309. ProgressBar::direction ProgressBar::getDirection() const
  310. {
  311. return _direction;
  312. }
  313. void ProgressBar::serialize(serializedata* data)
  314. {
  315. _Sprite::serialize(data);
  316. pugi::xml_node node = data->node;
  317. data->node.set_name("ProgressBar");
  318. data->node.append_attribute("progress").set_value(_progress);
  319. data->node.append_attribute("direction").set_value((int)_direction);
  320. }
  321. void ProgressBar::deserialize(const deserializedata* data)
  322. {
  323. _Sprite::deserialize(data);
  324. _direction = (direction)data->node.attribute("direction").as_int();
  325. _progress = data->node.attribute("progress").as_float(1.0f);
  326. }
  327. }