UiTextArea.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. #include <OgreFontManager.h>
  2. #include <OgreHardwareBufferManager.h>
  3. #include <OgreMaterialManager.h>
  4. #include "core/Logger.h"
  5. #include "core/UiManager.h"
  6. #include "core/UiTextArea.h"
  7. #include "core/TextManager.h"
  8. #include "core/Timer.h"
  9. #include "core/UiSprite.h"
  10. #include "core/Utilites.h"
  11. UiTextArea::UiTextArea(const Ogre::String& name):
  12. UiWidget(name)
  13. {
  14. Initialise();
  15. }
  16. UiTextArea::UiTextArea(const Ogre::String& name, const Ogre::String& path_name, UiWidget* parent):
  17. UiWidget(name, path_name, parent)
  18. {
  19. Initialise();
  20. }
  21. UiTextArea::~UiTextArea()
  22. {
  23. DestroyVertexBuffer();
  24. }
  25. void
  26. UiTextArea::Initialise()
  27. {
  28. m_Font = nullptr;
  29. m_MaxLetters = 0;
  30. m_TextAlign = UiTextArea::LEFT;
  31. m_TextLimit = 0;
  32. m_TextPrintSpeed = -1; // -1 instant
  33. m_TextPrintSpeedMod = 1;
  34. m_TextState = TS_DONE;
  35. m_TextYOffset = 0;
  36. m_TextYOffsetTarget = 0;
  37. m_PauseTime = 0;
  38. m_NextPageStart = 0;
  39. m_PaddingTop = 0;
  40. m_PaddingRight = 0;
  41. m_PaddingBottom = 0;
  42. m_PaddingLeft = 0;
  43. m_NextPressed = false;
  44. m_NextRepeated = false;
  45. m_Timer = false;
  46. m_TimerTime = 0;
  47. TextVariable var;
  48. var.name = "UITextAreaTimer";
  49. var.value = "00:00";
  50. m_TextVariable.push_back( var );
  51. m_SceneManager = Ogre::Root::getSingleton().getSceneManager("Scene");
  52. m_RenderSystem = Ogre::Root::getSingletonPtr()->getRenderSystem();
  53. CreateVertexBuffer();
  54. }
  55. void
  56. UiTextArea::Update()
  57. {
  58. if( m_Visible == true )
  59. {
  60. if( m_Timer == true )
  61. {
  62. int time = Timer::getSingleton().GetGameTimer();
  63. if( time > 5999 ) // 99:59
  64. {
  65. time = 5999;
  66. }
  67. if( time != m_TimerTime )
  68. {
  69. m_TimerTime = time;
  70. Ogre::String time_string = "";
  71. time_string += Ogre::StringConverter::toString( m_TimerTime / 60, 2, '0' );
  72. time_string += ( m_TimerTime & 1 ) ? ":" : ";";
  73. time_string += Ogre::StringConverter::toString( m_TimerTime % 60, 2, '0' );
  74. SetVariable( "UITextAreaTimer", time_string );
  75. }
  76. }
  77. switch( m_TextState )
  78. {
  79. case TS_SHOW_TEXT:
  80. {
  81. if( m_TextPrintSpeed == -1 )
  82. {
  83. m_TextLimit = m_MaxLetters;
  84. }
  85. else
  86. {
  87. float time = Timer::getSingleton().GetGameTimeDelta() * 30;
  88. float addition, limit;
  89. if( m_NextPressed == true || m_NextRepeated == true )
  90. {
  91. m_TextPrintSpeedMod += ( m_TextPrintSpeedMod >= 128 ) ? 0 : 1.0f * time;
  92. }
  93. else
  94. {
  95. m_TextPrintSpeedMod -= ( m_TextPrintSpeedMod <= 1) ? 0 : 1.0f * time;
  96. }
  97. if( m_TextPrintSpeed < 128 )
  98. {
  99. addition = ( ( 128 - m_TextPrintSpeed ) / 32 ) + 2;
  100. limit = 1;
  101. }
  102. else
  103. {
  104. addition = 2;
  105. limit = ( ( m_TextPrintSpeed - 128 ) / 32 ) + 1;
  106. }
  107. float char_to_add = ( limit * m_TextPrintSpeedMod / 16 + addition ) / limit;
  108. m_TextLimit += time * char_to_add;
  109. }
  110. m_UpdateTransformation = true;
  111. }
  112. break;
  113. case TS_SCROLL_TEXT:
  114. {
  115. m_TextYOffset -= m_Font->GetHeight() * Timer::getSingleton().GetGameTimeDelta() / m_TextScrollTime;
  116. if( m_TextYOffset <= m_TextYOffsetTarget )
  117. {
  118. m_TextYOffset = m_TextYOffsetTarget;
  119. m_TextPrintSpeedMod = 1;
  120. m_TextState = TS_SHOW_TEXT;
  121. }
  122. m_UpdateTransformation = true;
  123. }
  124. break;
  125. case TS_PAUSE_OK:
  126. {
  127. if( m_NextPressed == true )
  128. {
  129. m_TextPrintSpeedMod = 1;
  130. m_TextState = TS_SHOW_TEXT;
  131. }
  132. }
  133. break;
  134. case TS_PAUSE_TIME:
  135. {
  136. m_PauseTime -= Timer::getSingleton().GetGameTimeDelta();
  137. if( m_PauseTime <= 0 )
  138. {
  139. m_TextPrintSpeedMod = 1;
  140. m_TextState = TS_SHOW_TEXT;
  141. }
  142. }
  143. break;
  144. case TS_OVERFLOW:
  145. {
  146. if( m_NextPressed == true )
  147. {
  148. m_TextYOffsetTarget = m_TextYOffset - m_Font->GetHeight();
  149. m_TextState = TS_SCROLL_TEXT;
  150. }
  151. }
  152. break;
  153. case TS_NEXT_PAGE:
  154. {
  155. if( m_NextPressed == true )
  156. {
  157. RemoveSpritesFromText( m_NextPageStart );
  158. m_Text.erase( m_Text.begin(), m_Text.begin() + m_NextPageStart );
  159. m_TextLimit = 0;
  160. m_TextPrintSpeedMod = 1;
  161. m_TextYOffset = 0;
  162. m_TextYOffsetTarget = 0;
  163. m_TextState = TS_SHOW_TEXT;
  164. }
  165. }
  166. break;
  167. }
  168. }
  169. m_NextPressed = false;
  170. m_NextRepeated = false;
  171. UiWidget::Update();
  172. }
  173. void
  174. UiTextArea::Render()
  175. {
  176. if( m_UpdateTransformation == false && m_Visible == true )
  177. {
  178. if(m_RenderOp.vertexData->vertexCount != 0)
  179. {
  180. m_RenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
  181. m_RenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY);
  182. m_RenderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY);
  183. m_SceneManager->_setPass(m_Material->getTechnique(0)->getPass(0), true, false);
  184. m_RenderSystem->setScissorTest(true, m_ScissorLeft, m_ScissorTop, m_ScissorRight, m_ScissorBottom);
  185. m_RenderSystem->_render(m_RenderOp);
  186. m_RenderSystem->setScissorTest(false);
  187. }
  188. }
  189. UiWidget::Render();
  190. }
  191. void
  192. UiTextArea::UpdateTransformation()
  193. {
  194. UiWidget::UpdateTransformation();
  195. UpdateGeometry();
  196. }
  197. void
  198. UiTextArea::InputPressed()
  199. {
  200. m_NextPressed = true;
  201. }
  202. void
  203. UiTextArea::InputRepeated()
  204. {
  205. m_NextRepeated = true;
  206. }
  207. void
  208. UiTextArea::SetTextAlign( const TextAlign align )
  209. {
  210. m_TextAlign = align;
  211. m_UpdateTransformation = true;
  212. }
  213. void
  214. UiTextArea::SetPadding( const float top, const float right, const float bottom, const float left )
  215. {
  216. m_PaddingTop = top;
  217. m_PaddingRight = right;
  218. m_PaddingBottom = bottom;
  219. m_PaddingLeft = left;
  220. }
  221. void
  222. UiTextArea::SetText( const Ogre::UTFString& text )
  223. {
  224. TiXmlDocument doc;
  225. Ogre::UTFString xml_text = "<container>" + text + "</container>";
  226. doc.Parse( xml_text.asUTF8_c_str(), 0, TIXML_ENCODING_UTF8 );
  227. if( doc.Error() == true )
  228. {
  229. LOG_ERROR( "Can't parse text \"" + text + "\". TinyXml Error: " + doc.ErrorDesc() );
  230. return;
  231. }
  232. SetText( doc.RootElement() );
  233. }
  234. void
  235. UiTextArea::SetText( TiXmlNode* text )
  236. {
  237. if( text == NULL )
  238. {
  239. LOG_ERROR( "Text pointer is NULL." );
  240. return;
  241. }
  242. // reload font if language was changed
  243. if( m_Font != NULL )
  244. {
  245. Ogre::String language = m_Font->GetLanguage();
  246. if( language != "" )
  247. {
  248. if( TextManager::getSingleton().GetLanguage() != language )
  249. {
  250. SetFont( m_Font->GetName() );
  251. }
  252. }
  253. }
  254. TextClear();
  255. PrepareTextFromNode( text, m_Colour1 );
  256. m_TextState = TS_SHOW_TEXT;
  257. m_UpdateTransformation = true;
  258. if( m_Text.size() > m_MaxLetters )
  259. {
  260. m_Text.clear();
  261. LOG_ERROR( "Max number of text reached in \"" + m_PathName + "\". Can't render text from node. Max number of letters is " + Ogre::StringConverter::toString( m_MaxLetters ) + "." );
  262. }
  263. }
  264. void
  265. UiTextArea::TextClear()
  266. {
  267. RemoveSpritesFromText( m_Text.size() );
  268. m_Text.clear();
  269. m_TextLimit = 0;
  270. m_TextPrintSpeedMod = 1;
  271. m_TextYOffset = 0;
  272. m_TextYOffsetTarget = 0;
  273. }
  274. void
  275. UiTextArea::RemoveSpritesFromText( const unsigned int end )
  276. {
  277. for( unsigned int i = 0; i < end; ++i )
  278. {
  279. if( m_Text[ i ].sprite != NULL )
  280. {
  281. for( unsigned int j = 0; j < m_Children.size(); ++j )
  282. {
  283. if( m_Text[ i ].sprite == m_Children[ j ] )
  284. {
  285. delete m_Children[ j ];
  286. m_Children.erase( m_Children.begin() + j, m_Children.begin() + j + 1 );
  287. break;
  288. }
  289. }
  290. }
  291. }
  292. }
  293. void
  294. UiTextArea::SetFont(const Ogre::String& font)
  295. {
  296. m_Font = UiManager::getSingleton().GetFont(font);
  297. if(m_Font == nullptr)
  298. {
  299. LOG_ERROR("Could not find font \"" + font + "\" for \"" + m_PathName + "\".");
  300. return;
  301. }
  302. m_Material = Ogre::MaterialManager::getSingleton().create("UiMaterials." + m_PathName, "General");
  303. Ogre::Pass* pass = m_Material->getTechnique(0)->getPass(0);
  304. pass->setVertexColourTracking(Ogre::TVC_AMBIENT);
  305. pass->setCullingMode(Ogre::CULL_NONE);
  306. pass->setDepthCheckEnabled(false);
  307. pass->setDepthWriteEnabled(false);
  308. pass->setLightingEnabled(false);
  309. pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
  310. pass->setAlphaRejectFunction(Ogre::CMPF_GREATER);
  311. pass->setAlphaRejectValue(0);
  312. Ogre::TextureUnitState* tex = pass->createTextureUnitState();
  313. tex->setTextureName(m_Font->GetImageName());
  314. tex->setNumMipmaps(-1);
  315. tex->setTextureFiltering(Ogre::TFO_NONE);
  316. m_UpdateTransformation = true;
  317. }
  318. const UiFont*
  319. UiTextArea::GetFont() const
  320. {
  321. return m_Font;
  322. }
  323. void
  324. UiTextArea::SetTextPrintSpeed( const float speed )
  325. {
  326. m_TextPrintSpeed = speed;
  327. }
  328. void
  329. UiTextArea::SetTextScrollTime( const float time )
  330. {
  331. m_TextScrollTime = time;
  332. }
  333. void
  334. UiTextArea::SetVariable( const Ogre::String& name, const Ogre::UTFString& value )
  335. {
  336. if( name == "" )
  337. {
  338. return;
  339. }
  340. bool update = false;
  341. for( unsigned int i = 0; i < m_TextVariable.size(); ++i )
  342. {
  343. if( m_TextVariable[ i ].name == name )
  344. {
  345. m_TextVariable[ i ].value = value;
  346. update = true;
  347. for( unsigned int j = 0; j < m_Text.size(); ++j )
  348. {
  349. if( m_Text[ j ].variable == name )
  350. {
  351. m_Text.erase( m_Text.begin() + j + 1, m_Text.begin() + j + 1 + m_Text[ j ].variable_len );
  352. }
  353. }
  354. }
  355. }
  356. if( update == false )
  357. {
  358. TextVariable var;
  359. var.name = name;
  360. var.value = value;
  361. m_TextVariable.push_back( var );
  362. }
  363. for( unsigned int i = 0; i < m_Text.size(); ++i )
  364. {
  365. if( m_Text[ i ].variable == name )
  366. {
  367. m_Text[ i ].variable_len = value.size();
  368. unsigned int j = 0;
  369. for( ; j < m_Text[ i ].variable_len; ++j )
  370. {
  371. TextChar text_char;
  372. text_char.char_code = value[ j ];
  373. text_char.colour = m_Text[ i ].colour;
  374. m_Text.insert( m_Text.begin() + i + 1 + j, text_char );
  375. }
  376. i += j;
  377. }
  378. }
  379. m_UpdateTransformation = true;
  380. }
  381. Ogre::UTFString
  382. UiTextArea::GetVariable( const Ogre::String& name ) const
  383. {
  384. for( unsigned int i = 0; i < m_TextVariable.size(); ++i )
  385. {
  386. if( m_TextVariable[ i ].name == name )
  387. {
  388. return m_TextVariable[ i ].value;
  389. }
  390. }
  391. return "";
  392. }
  393. TextState
  394. UiTextArea::GetTextState() const
  395. {
  396. return m_TextState;
  397. }
  398. float
  399. UiTextArea::GetTextLimit() const
  400. {
  401. return m_TextLimit;
  402. }
  403. unsigned int
  404. UiTextArea::GetTextSize() const
  405. {
  406. return m_Text.size();
  407. }
  408. float
  409. UiTextArea::GetPauseTime() const
  410. {
  411. return m_PauseTime;
  412. }
  413. void
  414. UiTextArea::UpdateGeometry()
  415. {
  416. if( m_Font == NULL )
  417. {
  418. LOG_ERROR( "Font for \"" + m_PathName + "\" if not set." );
  419. return;
  420. }
  421. float width = 0;
  422. if( m_TextAlign != LEFT )
  423. {
  424. width = GetTextWidth();
  425. if( m_TextAlign == CENTER )
  426. {
  427. width /= 2;
  428. }
  429. }
  430. //LOG_ERROR( "1) m_FinalOrigin.y = " + Ogre::StringConverter::toString( m_FinalOrigin.y ) + ", m_TextYOffset = " + Ogre::StringConverter::toString( m_TextYOffset ) );
  431. float* writeIterator = ( float* ) m_VertexBuffer->lock( Ogre::HardwareBuffer::HBL_NORMAL );
  432. m_RenderOp.vertexData->vertexCount = 0;
  433. float local_x_start = -m_FinalOrigin.x - ( width - m_PaddingLeft ) * m_FinalScale.x * m_ScreenHeight / 720.0f;
  434. float local_x1 = local_x_start;
  435. float local_y1 = -m_FinalOrigin.y + ( ( m_TextYOffset + m_PaddingTop ) * m_FinalScale.y * m_ScreenHeight / 720.0f );
  436. float local_x2;
  437. float local_y2;
  438. float x = m_FinalTranslate.x;
  439. float y = m_FinalTranslate.y;
  440. unsigned int i = 0;
  441. for( ; ( i < m_TextLimit ) && ( i < m_Text.size() ); ++i )
  442. {
  443. if( m_Text[ i ].skip == true )
  444. {
  445. continue;
  446. }
  447. else if( m_Text[ i ].pause_ok == true )
  448. {
  449. m_Text[ i ].skip = true;
  450. m_TextState = TS_PAUSE_OK;
  451. break;
  452. }
  453. else if( m_Text[ i ].pause_time != 0 )
  454. {
  455. m_Text[ i ].skip = true;
  456. m_PauseTime = m_Text[ i ].pause_time;
  457. m_TextState = TS_PAUSE_TIME;
  458. break;
  459. }
  460. else if( m_Text[ i ].next_page == true )
  461. {
  462. m_Text[ i ].skip = true;
  463. m_NextPageStart = i + 1;
  464. m_TextState = TS_NEXT_PAGE;
  465. break;
  466. }
  467. else if( m_Text[ i ].sprite != NULL )
  468. {
  469. float width_percent = 0;
  470. float width = 0;
  471. m_Text[ i ].sprite->GetWidth( width_percent, width );
  472. m_Text[ i ].sprite->SetX( 0, local_x1 / ( m_FinalScale.x * m_ScreenHeight / 720.0f ) );
  473. local_x1 += width * m_FinalScale.x * m_ScreenHeight / 720.0f;
  474. float height_percent = 0;
  475. float height = 0;
  476. m_Text[ i ].sprite->GetHeight( height_percent, height );
  477. m_Text[ i ].sprite->SetY( 0, m_Text[ i ].sprite_y + ( local_y1 / ( m_FinalScale.y * m_ScreenHeight / 720.0f ) ) );
  478. m_Text[ i ].sprite->SetVisible( true );
  479. m_Text[ i ].sprite->UpdateGeometry();
  480. continue;
  481. }
  482. UiCharData char_data = m_Font->GetCharData( m_Text[ i ].char_code );
  483. Ogre::ColourValue colour = m_Text[ i ].colour;
  484. if( char_data.char_code == 10 )
  485. {
  486. local_x1 = local_x_start;
  487. local_y1 += m_Font->GetHeight() * m_FinalScale.y * m_ScreenHeight / 720.0f;
  488. continue;
  489. }
  490. local_x1 += char_data.pre * m_FinalScale.x * m_ScreenHeight / 720.0f;
  491. local_x2 = local_x1 + char_data.width * m_FinalScale.x * m_ScreenHeight / 720.0f;
  492. local_y2 = local_y1 + char_data.height * m_FinalScale.y * m_ScreenHeight / 720.0f;
  493. if( local_x2 + char_data.post * m_FinalScale.x * m_ScreenHeight / 720.0f > m_FinalSize.x - m_PaddingRight * m_FinalScale.x * m_ScreenHeight / 720.0f )
  494. {
  495. local_x1 = local_x_start;
  496. local_x2 = local_x1 + char_data.width * m_FinalScale.x * m_ScreenHeight / 720.0f;
  497. local_y1 += m_Font->GetHeight() * m_FinalScale.y * m_ScreenHeight / 720.0f;
  498. local_y2 = local_y1 + char_data.height * m_FinalScale.y * m_ScreenHeight / 720.0f;
  499. }
  500. // if we cross lower border of textarea - generate event and stop rendering
  501. if( local_y2 > m_FinalSize.y - m_PaddingBottom * m_FinalScale.y * m_ScreenHeight / 720.0f )
  502. {
  503. if( m_TextState != TS_SCROLL_TEXT )
  504. {
  505. m_TextState = TS_OVERFLOW;
  506. }
  507. break;
  508. }
  509. int x1, y1, x2, y2, x3, y3, x4, y4;
  510. //LOG_ERROR( m_Name );
  511. //LOG_ERROR( "local_x1 = " + Ogre::StringConverter::toString( local_x1 ) + ", local_y1 = " + Ogre::StringConverter::toString( local_y1 ) );
  512. //LOG_ERROR( "local_x2 = " + Ogre::StringConverter::toString( local_x2 ) + ", local_y2 = " + Ogre::StringConverter::toString( local_y2 ) );
  513. if( m_FinalRotation != 0 )
  514. {
  515. float cos = Ogre::Math::Cos( Ogre::Radian( Ogre::Degree( m_FinalRotation ) ) );
  516. float sin = Ogre::Math::Sin( Ogre::Radian( Ogre::Degree( m_FinalRotation ) ) );
  517. x1 = local_x1 * cos - local_y1 * sin + x;
  518. y1 = local_x1 * sin + local_y1 * cos + y;
  519. x2 = local_x2 * cos - local_y1 * sin + x;
  520. y2 = local_x2 * sin + local_y1 * cos + y;
  521. x3 = local_x2 * cos - local_y2 * sin + x;
  522. y3 = local_x2 * sin + local_y2 * cos + y;
  523. x4 = local_x1 * cos - local_y2 * sin + x;
  524. y4 = local_x1 * sin + local_y2 * cos + y;
  525. }
  526. else
  527. {
  528. x1 = local_x1 + x;
  529. y1 = local_y1 + y;
  530. x2 = local_x2 + x;
  531. y2 = local_y1 + y;
  532. x3 = local_x2 + x;
  533. y3 = local_y2 + y;
  534. x4 = local_x1 + x;
  535. y4 = local_y2 + y;
  536. }
  537. //LOG_ERROR( "x1 = " + Ogre::StringConverter::toString( x1 ) + ", y1 = " + Ogre::StringConverter::toString( y1 ) );
  538. //LOG_ERROR( "x2 = " + Ogre::StringConverter::toString( x2 ) + ", y2 = " + Ogre::StringConverter::toString( y2 ) );
  539. //LOG_ERROR( "x3 = " + Ogre::StringConverter::toString( x3 ) + ", y3 = " + Ogre::StringConverter::toString( y3 ) );
  540. //LOG_ERROR( "x4 = " + Ogre::StringConverter::toString( x4 ) + ", y4 = " + Ogre::StringConverter::toString( y4 ) );
  541. float new_x1 = ( x1 / m_ScreenWidth ) * 2 - 1;
  542. float new_y1 = -( ( y1 / m_ScreenHeight ) * 2 - 1 );
  543. float new_x2 = ( x2 / m_ScreenWidth ) * 2 - 1;
  544. float new_y2 = -( ( y2 / m_ScreenHeight ) * 2 - 1 );
  545. float new_x3 = ( x3 / m_ScreenWidth ) * 2 - 1;
  546. float new_y3 = -( ( y3 / m_ScreenHeight ) * 2 - 1 );
  547. float new_x4 = ( x4 / m_ScreenWidth ) * 2 - 1;
  548. float new_y4 = -( ( y4 / m_ScreenHeight ) * 2 - 1 );
  549. local_x1 += ( char_data.width + char_data.post ) * m_FinalScale.x * m_ScreenHeight / 720.0f;
  550. float width = m_Font->GetImageWidth();
  551. float height = m_Font->GetImageHeight();
  552. float left = ( float )char_data.x / width;
  553. float right = ( float )( char_data.x + char_data.width ) / width;
  554. float top = ( float )char_data.y / height;
  555. float bottom = ( float )( char_data.y + char_data.height ) / height;
  556. //LOG_ERROR( "width = " + Ogre::StringConverter::toString( width ) + "." );
  557. //LOG_ERROR( "height = " + Ogre::StringConverter::toString( height ) + "." );
  558. //LOG_ERROR( "char_data.x = " + Ogre::StringConverter::toString( char_data.x ) + "." );
  559. //LOG_ERROR( "char_data.y = " + Ogre::StringConverter::toString( char_data.y ) + "." );
  560. //LOG_ERROR( "char_data.width = " + Ogre::StringConverter::toString( char_data.width ) + "." );
  561. //LOG_ERROR( "char_data.height = " + Ogre::StringConverter::toString( char_data.height ) + "." );
  562. //LOG_ERROR( "left = " + Ogre::StringConverter::toString( left ) + "." );
  563. //LOG_ERROR( "right = " + Ogre::StringConverter::toString( right ) + "." );
  564. //LOG_ERROR( "top = " + Ogre::StringConverter::toString( top ) + "." );
  565. //LOG_ERROR( "bottom = " + Ogre::StringConverter::toString( bottom ) + "." );
  566. *writeIterator++ = new_x1;
  567. *writeIterator++ = new_y1;
  568. *writeIterator++ = m_FinalZ;
  569. *writeIterator++ = colour.r;
  570. *writeIterator++ = colour.g;
  571. *writeIterator++ = colour.b;
  572. *writeIterator++ = colour.a;
  573. *writeIterator++ = left;
  574. *writeIterator++ = top;
  575. *writeIterator++ = new_x2;
  576. *writeIterator++ = new_y2;
  577. *writeIterator++ = m_FinalZ;
  578. *writeIterator++ = colour.r;
  579. *writeIterator++ = colour.g;
  580. *writeIterator++ = colour.b;
  581. *writeIterator++ = colour.a;
  582. *writeIterator++ = right;
  583. *writeIterator++ = top;
  584. *writeIterator++ = new_x3;
  585. *writeIterator++ = new_y3;
  586. *writeIterator++ = m_FinalZ;
  587. *writeIterator++ = colour.r;
  588. *writeIterator++ = colour.g;
  589. *writeIterator++ = colour.b;
  590. *writeIterator++ = colour.a;
  591. *writeIterator++ = right;
  592. *writeIterator++ = bottom;
  593. *writeIterator++ = new_x1;
  594. *writeIterator++ = new_y1;
  595. *writeIterator++ = m_FinalZ;
  596. *writeIterator++ = colour.r;
  597. *writeIterator++ = colour.g;
  598. *writeIterator++ = colour.b;
  599. *writeIterator++ = colour.a;
  600. *writeIterator++ = left;
  601. *writeIterator++ = top;
  602. *writeIterator++ = new_x3;
  603. *writeIterator++ = new_y3;
  604. *writeIterator++ = m_FinalZ;
  605. *writeIterator++ = colour.r;
  606. *writeIterator++ = colour.g;
  607. *writeIterator++ = colour.b;
  608. *writeIterator++ = colour.a;
  609. *writeIterator++ = right;
  610. *writeIterator++ = bottom;
  611. *writeIterator++ = new_x4;
  612. *writeIterator++ = new_y4;
  613. *writeIterator++ = m_FinalZ;
  614. *writeIterator++ = colour.r;
  615. *writeIterator++ = colour.g;
  616. *writeIterator++ = colour.b;
  617. *writeIterator++ = colour.a;
  618. *writeIterator++ = left;
  619. *writeIterator++ = bottom;
  620. m_RenderOp.vertexData->vertexCount += 6;
  621. }
  622. m_VertexBuffer->unlock();
  623. if( i == m_Text.size() )
  624. {
  625. m_TextState = TS_DONE;
  626. }
  627. }
  628. float
  629. UiTextArea::GetTextWidth() const
  630. {
  631. float width = 0;
  632. float width_max = 0;
  633. for( unsigned int i = 0; i < m_Text.size(); ++i )
  634. {
  635. UiCharData char_data = m_Font->GetCharData( m_Text[ i ].char_code );
  636. // if we go to next row store max previous row width
  637. if( char_data.char_code == 10 )
  638. {
  639. width_max = ( width > width_max ) ? width : width_max;
  640. width = 0;
  641. }
  642. else
  643. {
  644. width += char_data.pre + char_data.width + char_data.post;
  645. }
  646. }
  647. return ( width > width_max ) ? width : width_max;
  648. }
  649. void
  650. UiTextArea::PrepareTextFromNode( TiXmlNode* node, const Ogre::ColourValue& colour )
  651. {
  652. while( node != NULL )
  653. {
  654. switch( node->Type() )
  655. {
  656. case TiXmlNode::TINYXML_TEXT:
  657. {
  658. TiXmlText* childText = node->ToText();
  659. if( childText )
  660. {
  661. PrepareTextFromText( childText->Value(), colour );
  662. }
  663. }
  664. break;
  665. case TiXmlNode::TINYXML_ELEMENT:
  666. {
  667. Ogre::ColourValue colour_child = colour;
  668. Ogre::String name = node->ValueStr();
  669. if( name == "colour" )
  670. {
  671. colour_child = Ogre::StringConverter::parseColourValue( node->ToElement()->Attribute( "value" ) );
  672. }
  673. else if( name == "pause_ok" )
  674. {
  675. TextChar new_char;
  676. new_char.pause_ok = true;
  677. m_Text.push_back( new_char );
  678. }
  679. else if( name == "pause" )
  680. {
  681. const std::string* string = node->ToElement()->Attribute( Ogre::String( "time" ) );
  682. if( string != NULL )
  683. {
  684. TextChar new_char;
  685. new_char.pause_time = Ogre::StringConverter::parseReal( *string );
  686. m_Text.push_back( new_char );
  687. }
  688. }
  689. else if( name == "next_page" )
  690. {
  691. TextChar new_char;
  692. new_char.next_page = true;
  693. m_Text.push_back( new_char );
  694. }
  695. else if( name == "timer" )
  696. {
  697. m_Timer = true;
  698. TextChar new_char;
  699. new_char.skip = true;
  700. new_char.variable = "UITextAreaTimer";
  701. new_char.colour = colour;
  702. Ogre::UTFString var = GetVariable( "UITextAreaTimer" );
  703. new_char.variable_len = var.size();
  704. m_Text.push_back( new_char );
  705. for( unsigned int i = 0; i < var.size(); ++i )
  706. {
  707. TextChar text_char;
  708. text_char.char_code = var[ i ];
  709. text_char.colour = colour;
  710. m_Text.push_back( text_char );
  711. }
  712. }
  713. else if( name == "variable" )
  714. {
  715. const std::string* string = node->ToElement()->Attribute( Ogre::String( "name" ) );
  716. if( string != NULL )
  717. {
  718. TextChar new_char;
  719. new_char.skip = true;
  720. new_char.variable = *string;
  721. new_char.colour = colour;
  722. Ogre::UTFString var = GetVariable( *string );
  723. new_char.variable_len = var.size();
  724. m_Text.push_back( new_char );
  725. for( unsigned int i = 0; i < var.size(); ++i )
  726. {
  727. TextChar text_char;
  728. text_char.char_code = var[ i ];
  729. text_char.colour = colour;
  730. m_Text.push_back( text_char );
  731. }
  732. }
  733. }
  734. else if( name == "include" )
  735. {
  736. const std::string* text_name = node->ToElement()->Attribute( Ogre::String( "name" ) );
  737. if( text_name != NULL )
  738. {
  739. TiXmlNode* text = TextManager::getSingleton().GetText( *text_name );
  740. if( text != NULL )
  741. {
  742. PrepareTextFromNode( text, colour_child );
  743. }
  744. }
  745. }
  746. else if( name == "image" )
  747. {
  748. Ogre::String name1 = GetString( node, "sprite" );
  749. if( name1 != "" )
  750. {
  751. TiXmlNode* sprites = UiManager::getSingleton().GetPrototype( "TextAreaSprite" );
  752. if( sprites != NULL )
  753. {
  754. sprites = sprites->FirstChild();
  755. while( sprites != NULL )
  756. {
  757. if( sprites->Type() == TiXmlNode::TINYXML_ELEMENT && sprites->ValueStr() == "sprite" )
  758. {
  759. Ogre::String name2 = GetString( sprites, "name" );
  760. if( name1 == name2 )
  761. {
  762. TextChar new_char;
  763. UiSprite* sprite = new UiSprite( name1, m_Name + "." + name1, this );
  764. Ogre::String image = GetString( sprites, "image" );
  765. if( image != "" )
  766. {
  767. sprite->SetImage( image );
  768. }
  769. Ogre::String y_str = GetString( sprites, "y" );
  770. if( y_str != "" )
  771. {
  772. float y_percent = 0;
  773. float y = 0;
  774. ParsePersent( y_percent, y, y_str );
  775. new_char.sprite_y = y;
  776. }
  777. Ogre::String width_str = GetString( sprites, "width" );
  778. if( width_str != "" )
  779. {
  780. float width_percent = 0;
  781. float width = 0;
  782. ParsePersent( width_percent, width, width_str );
  783. sprite->SetWidth( 0, width );
  784. }
  785. Ogre::String height_str = GetString( sprites, "height" );
  786. if( height_str != "" )
  787. {
  788. float height_percent = 0;
  789. float height = 0;
  790. ParsePersent( height_percent, height, height_str );
  791. sprite->SetHeight( height_percent, height );
  792. }
  793. sprite->SetVisible( false );
  794. AddChild( sprite );
  795. new_char.sprite = sprite;
  796. m_Text.push_back( new_char );
  797. break;
  798. }
  799. }
  800. sprites = sprites->NextSibling();
  801. }
  802. }
  803. }
  804. }
  805. TiXmlNode* node_child = node->FirstChild();
  806. PrepareTextFromNode( node_child, colour_child );
  807. }
  808. break;
  809. }
  810. node = node->NextSibling();
  811. }
  812. }
  813. void
  814. UiTextArea::PrepareTextFromText( const Ogre::UTFString& text, const Ogre::ColourValue& colour_child )
  815. {
  816. for( unsigned int i = 0; i < text.size(); ++i )
  817. {
  818. TextChar new_char;
  819. new_char.char_code = text[ i ];
  820. new_char.colour = colour_child;
  821. m_Text.push_back( new_char );
  822. };
  823. }
  824. void
  825. UiTextArea::CreateVertexBuffer()
  826. {
  827. m_MaxLetters = 1024;
  828. m_RenderOp.vertexData = new Ogre::VertexData;
  829. m_RenderOp.vertexData->vertexStart = 0;
  830. Ogre::VertexDeclaration* vDecl = m_RenderOp.vertexData->vertexDeclaration;
  831. size_t offset = 0;
  832. vDecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
  833. offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
  834. vDecl->addElement(0, offset, Ogre::VET_FLOAT4, Ogre::VES_DIFFUSE);
  835. offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT4);
  836. vDecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
  837. m_VertexBuffer = Ogre::HardwareBufferManager::getSingletonPtr()->createVertexBuffer(vDecl->getVertexSize(0), m_MaxLetters * 6, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
  838. m_RenderOp.vertexData->vertexBufferBinding->setBinding(0, m_VertexBuffer);
  839. m_RenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
  840. m_RenderOp.useIndexes = false;
  841. }
  842. void
  843. UiTextArea::DestroyVertexBuffer()
  844. {
  845. delete m_RenderOp.vertexData;
  846. m_RenderOp.vertexData = 0;
  847. m_VertexBuffer.setNull();
  848. m_MaxLetters = 0;
  849. }