BaseGUIText.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. #include "BaseGUIText.h"
  2. #include "../utils/InterfaceUtils.h"
  3. const int icon_max_count = 16;
  4. const dword buffer_size = 1024;
  5. static char buffer[buffer_size*2];
  6. static float __aspect;
  7. static float __asp;
  8. static float font_hk;
  9. static IVBuffer *_VB = null;
  10. static IIBuffer *_IB = null;
  11. static IVariable *Texture = null;
  12. static IBaseTexture *Image;
  13. static IRender *__render = null;
  14. static IControlsService *__controls = null;
  15. static ShaderId Circular_shadow_id;
  16. static ShaderId Circular_id;
  17. static int _refCount = 0;
  18. struct Vertex
  19. {
  20. Vector p;
  21. float tu;
  22. float tv;
  23. float al;
  24. };
  25. /////////////////////////////////
  26. class GUIText : public IGUIText
  27. {
  28. struct Params
  29. {
  30. string defaultString;
  31. Align horizAlign;
  32. Align vertAlign;
  33. bool useSafeFrame;
  34. Color color;
  35. Params()
  36. {
  37. horizAlign = Left;
  38. vertAlign = Top;
  39. useSafeFrame = true;
  40. color = (dword)-1;
  41. }
  42. };
  43. Params m_params;
  44. struct Info
  45. {
  46. ImagePlace p;
  47. float x; float w;
  48. float y; float h;
  49. float k;
  50. bool anim;
  51. };
  52. array<Info> table;
  53. array<long> hash;
  54. private:
  55. float SC2UIRC(float t)
  56. {
  57. return m_params.useSafeFrame ? InterfaceUtils::ScreenCoord2UIRectCoord(t) : t;
  58. }
  59. float SS2UIRS(float size)
  60. {
  61. return m_params.useSafeFrame ? InterfaceUtils::ScreenSize2UIRectSize(size) : size;
  62. }
  63. void UpdateTable(string &s);
  64. void UpdateHash (string &s);
  65. public:
  66. GUIText() : table(_FL_),
  67. hash (_FL_)
  68. {
  69. m_font = null;
  70. m_time = 0.0f;
  71. m_alpha = 1.0f;
  72. m_fontScale = 1.0f;
  73. }
  74. virtual bool Prepare(IFont *font, float w, float h, const char *text,
  75. Align hor,
  76. Align ver, bool useSafeFrame);
  77. virtual void Draw (IFont *font, float x, float y,
  78. bool animate,
  79. Effect *eff);
  80. virtual void Update(float time)
  81. {
  82. m_time = time;
  83. }
  84. virtual void SetScale(float k)
  85. {
  86. m_fontScale = k;
  87. }
  88. virtual void SetColor(const Color &c)
  89. {
  90. m_params.color = c;
  91. }
  92. virtual void SetAlpha(float a)
  93. {
  94. m_alpha = a;
  95. }
  96. virtual void GetPos(float &x, float &y)
  97. {
  98. x = m_strOffX;
  99. y = m_strOffY;
  100. }
  101. virtual void Release()
  102. {
  103. Assert(_refCount > 0)
  104. if( !--_refCount )
  105. {
  106. RELEASE(_VB)
  107. RELEASE(_IB)
  108. Texture = NULL;
  109. }
  110. delete this;
  111. }
  112. private:
  113. IFont *m_font;
  114. dword m_linesCount;
  115. float m_fontScale;
  116. float m_w;
  117. float m_h;
  118. float m_strOffX;
  119. float m_strOffY;
  120. float m_time;
  121. float m_alpha;
  122. };
  123. void GUIText::Draw(IFont *font, float x, float y, bool animate, Effect *eff)
  124. {
  125. m_font = font;
  126. if( !m_font )
  127. return;
  128. float fh = m_font->GetHeight();
  129. m_font->SetHeight(fh*m_fontScale);
  130. dword cx = __render->GetViewport().Width;
  131. dword cy = __render->GetViewport().Height;
  132. float width = m_w*__aspect;
  133. float height = m_h;
  134. float textX = cx*SC2UIRC(x/100.0f);
  135. float textY = cy*SC2UIRC(y/100.0f);
  136. float outputWidth = cx*SS2UIRS(width /100.0f);
  137. float outputHeight = cy*SS2UIRS(height/100.0f);
  138. float textHeight = m_font->GetHeight()*m_linesCount;
  139. switch( m_params.vertAlign )
  140. {
  141. case Center:
  142. textY += (outputHeight - textHeight)/2;
  143. break;
  144. case Bottom:
  145. textY += (outputHeight - textHeight);
  146. break;
  147. }
  148. dword strBegin = 0;
  149. dword lineNumber = 0;
  150. Vertex *p = (Vertex *)_VB->Lock(0,0,LOCK_DISCARD);
  151. Vertex *q = p + icon_max_count/2*4;
  152. int n = 0;
  153. for( dword i = 0; i < m_params.defaultString.Len(); i++ )
  154. {
  155. if( m_params.defaultString[i] == '\n' )
  156. {
  157. m_params.defaultString[i] = 0;
  158. char *line = (char *)m_params.defaultString.GetBuffer() + strBegin;
  159. float lineWidth = m_font->GetLength(line);
  160. textX = cx*SC2UIRC(x/100.0f);
  161. switch( m_params.horizAlign )
  162. {
  163. case Center:
  164. textX += (outputWidth - lineWidth)/2;
  165. break;
  166. case Right:
  167. textX += (outputWidth - lineWidth);
  168. break;
  169. }
  170. Color c = m_params.color;
  171. // c.a *= m_fadeAlpha*GetAlpha();
  172. c.a *= m_alpha;
  173. m_font->SetColor(c);
  174. if( eff )
  175. {
  176. float y = textY + lineNumber*m_font->GetHeight();
  177. if( eff->Beg > 0 )
  178. {
  179. char d = line[eff->Beg];
  180. line[eff->Beg] = 0;
  181. m_font->Print(textX,y,line);
  182. line[eff->Beg] = d;
  183. }
  184. if( eff->Beg + eff->Len < strlen(line))
  185. {
  186. m_font->Print(textX + eff->Width,y,line + eff->Beg + eff->Len);
  187. }
  188. }
  189. else
  190. {
  191. m_font->Print(textX,textY + lineNumber*m_font->GetHeight(),line);
  192. }
  193. m_strOffX = textX;
  194. m_strOffY = textY + m_font->GetHeight()/2;
  195. if( table )
  196. {
  197. for( int j = 0 ; j < hash[lineNumber] ; j++ )
  198. {
  199. if( n > icon_max_count/2 )
  200. break;
  201. Info &info = table[n++];
  202. float xx = (textX + info.x)/cx;
  203. float yy = (textY + info.y)/cy;
  204. xx = xx*2.0f - 1.0f;
  205. yy = 1.0f - yy*2.0f;
  206. // float sy = info.h/cy*2*m_hk;
  207. float sy = info.h/cy*2;
  208. // float sx = info.w/cx*2*m_hk;
  209. float sx = sy*info.k;
  210. float dx = 0.0f;
  211. float dy = 0.0f;
  212. float ak = 1.0f;
  213. // if( animate )
  214. if( animate && info.anim )
  215. /* {
  216. float k = 1.0f + (1.0f - cosf(m_time))*0.5f*0.2f;
  217. float tx = sx*k;
  218. float ty = sy*k;
  219. xx -= (tx - sx)*0.5f;
  220. yy += (ty - sy)*0.5f;
  221. sx = tx;
  222. sy = ty;
  223. }*/
  224. {
  225. float k = (1.0f - cosf(m_time))*0.5f*0.1f;
  226. // ak = 1.0f - k*10.0f;
  227. ak = 0.6f - k*10.0f*0.4f;
  228. float tx = sx*(1.0f + k);
  229. float ty = sy*(1.0f + k);
  230. // xx -= (tx - sx)*0.5f + k*sx;
  231. // yy += (ty - sy)*0.5f + k*sy;
  232. dx = (tx - sx)*0.5f + k*sx;
  233. dy = (ty - sy)*0.5f + k*sy;
  234. sx = tx;
  235. sy = ty;
  236. }
  237. ImagePlace &pl = info.p;
  238. float _l = pl.u; float _r = _l + pl.w;
  239. float _t = pl.v; float _b = _t + pl.h;
  240. q[0].p = Vector(xx ,yy - sy,0.0f);
  241. q[1].p = Vector(xx ,yy ,0.0f);
  242. q[2].p = Vector(xx + sx,yy ,0.0f);
  243. q[3].p = Vector(xx + sx,yy - sy,0.0f);
  244. q[0].tu = _l; q[0].tv = _b;
  245. q[1].tu = _l; q[1].tv = _t;
  246. q[2].tu = _r; q[2].tv = _t;
  247. q[3].tu = _r; q[3].tv = _b;
  248. q[0].al = c.a*ak;//m_fadeAlpha;
  249. q[1].al = c.a*ak;//m_fadeAlpha;
  250. q[2].al = c.a*ak;//m_fadeAlpha;
  251. q[3].al = c.a*ak;//m_fadeAlpha;
  252. q += 4;
  253. xx -= dx;
  254. yy += dy;
  255. p[0].p = Vector(xx ,yy - sy,0.0f);
  256. p[1].p = Vector(xx ,yy ,0.0f);
  257. p[2].p = Vector(xx + sx,yy ,0.0f);
  258. p[3].p = Vector(xx + sx,yy - sy,0.0f);
  259. p[0].tu = _l; p[0].tv = _b;
  260. p[1].tu = _l; p[1].tv = _t;
  261. p[2].tu = _r; p[2].tv = _t;
  262. p[3].tu = _r; p[3].tv = _b;
  263. p[0].al = c.a;//m_fadeAlpha;
  264. p[1].al = c.a;//m_fadeAlpha;
  265. p[2].al = c.a;//m_fadeAlpha;
  266. p[3].al = c.a;//m_fadeAlpha;
  267. p += 4;
  268. }
  269. }
  270. m_params.defaultString[i] = '\n';
  271. strBegin = i + 1;
  272. lineNumber++;
  273. }
  274. }
  275. _VB->Unlock();
  276. if( n )
  277. {
  278. __render->SetStreamSource(0,_VB);
  279. __render->SetIndices(_IB,0);
  280. if( Image )
  281. Texture->SetTexture(Image);
  282. __render->DrawIndexedPrimitive(Circular_shadow_id,
  283. PT_TRIANGLELIST,icon_max_count/2*4,n*4,icon_max_count/2*6,n*2);
  284. __render->DrawIndexedPrimitive(Circular_id,
  285. PT_TRIANGLELIST,0,n*4,0,n*2);
  286. }
  287. m_font->SetHeight(fh);
  288. }
  289. bool GUIText::Prepare(IFont *font, float w, float h, const char *text, Align hor, Align ver, bool useSafeFrame)
  290. {
  291. if( !font )
  292. return false;
  293. m_params.defaultString = text;
  294. m_params.horizAlign = hor;
  295. m_params. vertAlign = ver;
  296. m_params.useSafeFrame = useSafeFrame;
  297. m_w = w;
  298. m_h = h;
  299. m_font = font;
  300. UpdateTable(m_params.defaultString);
  301. m_linesCount = InterfaceUtils::WordWrapString(
  302. buffer,font,w/100.0f*__render->GetViewport().Width*__aspect,buffer_size);
  303. UpdateHash (m_params.defaultString);
  304. return m_params.defaultString != text;
  305. }
  306. void GUIText::UpdateTable(string &s)
  307. {
  308. if( !m_font )
  309. return;
  310. float fh = m_font->GetHeight()*font_hk;
  311. table.DelAll();
  312. char name[40];
  313. char *line = (char *)s.GetBuffer();
  314. char *p = line;
  315. // IBaseTexture *image = Controls().GetControlsImage();
  316. // Assert(image)
  317. // dword imageW = image->GetWidth ();
  318. // dword imageH = image->GetHeight();
  319. // Assert(Image)
  320. Image = __controls->GetControlsImage();
  321. /*
  322. // lastImage = Image;
  323. m_updated = Controls().GetImagesUpdated();
  324. */
  325. dword imageW = Image ? Image->GetWidth () : 0;
  326. dword imageH = Image ? Image->GetHeight() : 0;
  327. dword cx = __render->GetViewport().Width;
  328. dword cy = __render->GetViewport().Height;
  329. // string t;
  330. buffer[0] = 0;
  331. while( 1 )
  332. {
  333. p = strchr(line,'[');
  334. if( !p )
  335. break;
  336. if( p > line )
  337. {
  338. *p = 0;
  339. // t += line;
  340. strcat_s(buffer,buffer_size,line);
  341. *p = '[';
  342. line = p;
  343. }
  344. p++;
  345. if( *p == '[' )
  346. {
  347. strcat_s(buffer,buffer_size,"[");
  348. line = p = p + 1;
  349. continue;
  350. }
  351. bool anim = false;
  352. if( *p == '#' )
  353. {
  354. anim = true; p++;
  355. }
  356. for( int j = 0 ; *p && *p != ']' ; )
  357. name[j++] = *p++;
  358. if( !*p )
  359. break;
  360. name[j] = 0;
  361. Info &info = table[table.Add()];
  362. info.p = __controls->GetControlImagePlace(name);
  363. if( info.p.h )
  364. {
  365. info.anim = anim;
  366. info.w = imageW*info.p.w;//*0.4f;
  367. info.h = imageH*info.p.h;//*0.4f;
  368. info.w *= fh/info.h;
  369. info.h = fh;
  370. info.k = info.w/info.h/__asp;
  371. int n;
  372. float width = m_font->GetLength("`");
  373. if( fabs(width) < 1e-30f ) // символ не найден
  374. n = info.w ? 1 : 0;
  375. else
  376. {
  377. // n = info.w ? (int)ceilf(info.w*m_hk/width) : 0;
  378. // float sx = info.h/cy*m_hk*info.k;
  379. float sx = info.h/cy*info.k;
  380. n = info.w ? (int)ceilf(sx*cx/width) : 0;
  381. }
  382. while( n-- > 0 )
  383. // t += '@';
  384. strcat_s(buffer,buffer_size,"`");
  385. }
  386. else
  387. {
  388. info.w = 0.0f;
  389. info.h = 0.0f;
  390. info.k = 0.0f;
  391. // strcat_s(buffer,buffer_size,"[");
  392. strcat_s(buffer,buffer_size,name);
  393. // strcat_s(buffer,buffer_size,"]");
  394. }
  395. p++; line = p;
  396. }
  397. // t += line;
  398. strcat_s(buffer,buffer_size,line);
  399. // s = t;
  400. // s = buffer;
  401. }
  402. static float round(float x)
  403. {
  404. float f = floorf(x);
  405. if( x - f > 0.5f )
  406. return f + 1.0f;
  407. else
  408. return f;
  409. }
  410. void GUIText::UpdateHash(string &s)
  411. {
  412. if( !m_font )
  413. return;
  414. dword cx = __render->GetViewport().Width;
  415. dword cy = __render->GetViewport().Height;
  416. // float aspect = InterfaceUtils::AspectRatio(Render());
  417. hash.DelAll();
  418. dword i = 0; // текущая позиция в исходной строке
  419. dword j = 0; // текущая позиция в строке результата
  420. dword n = 0; // индекс первого символа в строке
  421. dword t = 0; // индекс в таблице
  422. dword d = 0; // номер текущей строки
  423. // string z;
  424. // buffer[0] = 0;
  425. hash.Add();
  426. hash[d] = 0;
  427. char *dst = buffer + buffer_size;
  428. while( 1 )
  429. {
  430. // while( s [i] != '`' && s [i] != '\n' )
  431. while( buffer[i] != '`' && buffer[i] != '\n' )
  432. // dst[j++] = s [i++];
  433. dst[j++] = buffer[i++];
  434. // if( s [i] == '\n' )
  435. if( buffer[i] == '\n' )
  436. {
  437. // dst[j++] = s [i];
  438. dst[j++] = buffer[i];
  439. // if( i >= s.Len() - 1 )
  440. if( !buffer[i + 1] )
  441. break;
  442. else
  443. {
  444. i++; n = j; d++;
  445. hash.Add();
  446. hash[d] = 0; continue;
  447. }
  448. }
  449. hash[d]++;
  450. Info &info = table[t++];
  451. info.x = m_font->GetLength(j - n,dst + n);
  452. info.y = m_font->GetHeight()*d;
  453. // info.y += (m_font->GetHeight() - info.h*m_hk)*0.5f;
  454. info.y += (m_font->GetHeight() - info.h)*0.5f;
  455. // while( s [i] == '`' )
  456. while( buffer[i] == '`' )
  457. i++;
  458. int n;
  459. float width = m_font->GetLength(" ");
  460. if( width == 0.0f ) // символ не найден
  461. // n = 1;
  462. n = 0;
  463. else
  464. {
  465. // n = (int)round(info.w*m_hk/width);
  466. // float sx = info.h/cy*m_hk*info.k;
  467. float sx = info.h/cy*info.k;
  468. n = (int)round(sx*cx/width);
  469. // n = (int)ceilf(sx*cx/width);
  470. }
  471. while( n-- )
  472. dst[j++] = ' ';
  473. // if( s [i] == '\n' )
  474. if( buffer[i] == '\n' )
  475. {
  476. // dst[j++] = s [i];
  477. dst[j++] = buffer[i];
  478. // if( i >= s.Len() - 1 )
  479. if( !buffer[i + 1] )
  480. break;
  481. else
  482. {
  483. i++; n = j; d++;
  484. hash.Add();
  485. hash[d] = 0; continue;
  486. }
  487. }
  488. }
  489. dst[j] = 0;
  490. // s = z;
  491. s = dst;
  492. }
  493. /////////////////////////////////
  494. GUITextManager:: GUITextManager()
  495. {
  496. //
  497. }
  498. GUITextManager::~GUITextManager()
  499. {
  500. // Assert(!_refCount)
  501. }
  502. IGUIText *GUITextManager::CreateText()
  503. {
  504. if( !_refCount++ )
  505. {
  506. InitParams();
  507. CreateBuffers();
  508. }
  509. return NEW GUIText();
  510. }
  511. bool GUITextManager::Create(MOPReader &reader)
  512. {
  513. // CreateBuffers();
  514. return true;
  515. }
  516. void GUITextManager::Activate(bool isActive)
  517. {
  518. //
  519. }
  520. void GUITextManager::Show(bool isShow)
  521. {
  522. //
  523. }
  524. void GUITextManager::Command(const char *id, dword numParams, const char **params)
  525. {
  526. //
  527. }
  528. void GUITextManager::InitParams()
  529. {
  530. if( __render )
  531. return;
  532. __render = (IRender *) api->GetService("DX9Render");
  533. __controls = (IControlsService *)api->GetService("ControlsService");
  534. // все элементы создаются из расчета этого аспекта
  535. const float def_aspect = 16.0f/9.0f;
  536. float cx;
  537. float cy;
  538. if( EditMode_IsOn())
  539. {
  540. cx = (float)__render->GetFullScreenViewPort_2D().Width;
  541. cy = (float)__render->GetFullScreenViewPort_2D().Height;
  542. }
  543. else
  544. {
  545. cx = (float)__render->GetFullScreenViewPort_2D().Width;
  546. cy = (float)__render->GetFullScreenViewPort_2D().Height;
  547. }
  548. // аспект разрешения экрана
  549. float scr_aspect = cx/cy;
  550. // аспект пикселя
  551. float dot_aspect = InterfaceUtils::AspectRatio(*__render);
  552. // реальный аспект
  553. float cur_aspect = scr_aspect/dot_aspect;
  554. __aspect = def_aspect/cur_aspect;
  555. __asp = cur_aspect;
  556. /////////////////////////////////
  557. IFileService *storage = (IFileService *)api->GetService("FileService");
  558. Assert(storage)
  559. IIniFile *ini = storage->SystemIni();
  560. if( ini )
  561. {
  562. font_hk = ini->GetFloat("Controls","IconMult",1.0f);
  563. }
  564. else
  565. font_hk = 1.0f;
  566. //////////////////////////////////
  567. __render->GetShaderId("Circular_shadow", Circular_shadow_id);
  568. __render->GetShaderId("Circular", Circular_id);
  569. }
  570. void GUITextManager::CreateBuffers()
  571. {
  572. _VB = __render->CreateVertexBuffer(
  573. sizeof(Vertex)*icon_max_count*4,
  574. sizeof(Vertex),
  575. _FL_,USAGE_WRITEONLY|USAGE_DYNAMIC,POOL_DEFAULT);
  576. Assert(_VB)
  577. _IB = __render->CreateIndexBuffer(
  578. sizeof(WORD) *icon_max_count*6,
  579. _FL_,USAGE_WRITEONLY|USAGE_DYNAMIC);
  580. Assert(_IB)
  581. WORD *p = (WORD *)_IB->Lock();
  582. Assert(p)
  583. for( long i = 0 ; i < icon_max_count ; i++ )
  584. {
  585. p[i*6 + 0] = WORD(i*4 + 0);
  586. p[i*6 + 1] = WORD(i*4 + 1);
  587. p[i*6 + 2] = WORD(i*4 + 2);
  588. p[i*6 + 3] = WORD(i*4 + 0);
  589. p[i*6 + 4] = WORD(i*4 + 2);
  590. p[i*6 + 5] = WORD(i*4 + 3);
  591. }
  592. _IB->Unlock();
  593. Texture = __render->GetTechniqueGlobalVariable("CircularTexture",_FL_);
  594. }
  595. MOP_BEGINLIST(GUITextManager, "", '1.00', 100)
  596. MOP_ENDLIST(GUITextManager)