1 /*
2  * Copyright 2011-2013 Arx Libertatis Team (see the AUTHORS file)
3  *
4  * This file is part of Arx Libertatis.
5  *
6  * Arx Libertatis is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Arx Libertatis is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Arx Libertatis.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23 
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25 
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28 
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31 
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code.  If not, see
33 <http://www.gnu.org/licenses/>.
34 
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38 
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43 
44 #include "gui/TextManager.h"
45 
46 #include "gui/Text.h"
47 #include "graphics/Math.h"
48 #include "graphics/font/Font.h"
49 #include "io/log/Logger.h"
50 
51 using std::string;
52 using std::vector;
53 
54 struct TextManager::ManagedText {
55 	Font* pFont;
56 	Rect rRect;
57 	Rect rRectClipp;
58 	string lpszUText;
59 	float fDeltaY;
60 	float fSpeedScrollY;
61 	Color lCol;
62 	long lTimeScroll;
63 	long lTimeOut;
64 };
65 
TextManager()66 TextManager::TextManager() {
67 }
68 
~TextManager()69 TextManager::~TextManager() {
70 	Clear();
71 }
72 
AddText(Font * _pFont,const string & _lpszUText,const Rect & _rRect,Color _lCol,long _lTimeOut,long _lTimeScroll,float _fSpeedScroll,int iNbLigneClipp)73 bool TextManager::AddText(Font* _pFont, const string & _lpszUText, const Rect & _rRect, Color _lCol, long _lTimeOut, long _lTimeScroll, float _fSpeedScroll, int iNbLigneClipp) {
74 
75 	if(_lpszUText.empty()) {
76 		return false;
77 	}
78 
79 	if(!_pFont) {
80 		LogWarning << "Adding text with NULL font.";
81 		return false;
82 	}
83 
84 	ManagedText * pArxText = new ManagedText();
85 	if(!pArxText) {
86 		return false;
87 	}
88 
89 	pArxText->pFont = _pFont;
90 	pArxText->lpszUText = _lpszUText;
91 	pArxText->rRect = _rRect;
92 	pArxText->lCol = _lCol;
93 	pArxText->lTimeScroll = _lTimeScroll;
94 	pArxText->fDeltaY = 0.f;
95 	pArxText->fSpeedScrollY = _fSpeedScroll;
96 	pArxText->lTimeOut = _lTimeOut;
97 	pArxText->rRectClipp = pArxText->rRect;
98 
99 	if(iNbLigneClipp)
100 	{
101 		Vec2i sSize = _pFont->getTextSize(pArxText->lpszUText);
102 		sSize.y *= iNbLigneClipp;
103 
104 		pArxText->rRectClipp.bottom = pArxText->rRect.top + sSize.y;
105 	}
106 
107 	entries.push_back(pArxText);
108 
109 	return true;
110 }
111 
AddText(Font * font,const std::string & str,long x,long y,Color fgcolor)112 bool TextManager::AddText(Font * font, const std::string & str, long x, long y, Color fgcolor) {
113 	Rect r;
114 	r.left = x;
115 	r.top = y;
116 	r.right = Rect::Limits::max();
117 	r.bottom = Rect::Limits::max();
118 	return AddText(font, str, r, fgcolor);
119 }
120 
Update(float _fDiffFrame)121 void TextManager::Update(float _fDiffFrame) {
122 
123 	int _iDiffFrame = checked_range_cast<int>(_fDiffFrame);
124 
125 	// TODO-slussier: Until we fix the arxtime.get_updated() mess, it's easy to have a FrameDiff of 0...
126 	if(_iDiffFrame == 0)
127 		_iDiffFrame = 1;
128 
129 	vector<ManagedText *>::iterator itManage;
130 	for(itManage = entries.begin(); itManage != entries.end();) {
131 
132 		ManagedText * pArxText = *itManage;
133 
134 		if(pArxText->lTimeOut < 0) {
135 			delete pArxText;
136 			itManage = entries.erase(itManage);
137 			continue;
138 		}
139 
140 		pArxText->lTimeOut -= _iDiffFrame;
141 
142 		if(pArxText->lTimeScroll < 0 &&
143 		   pArxText->fDeltaY < (pArxText->rRect.bottom - pArxText->rRectClipp.bottom)) {
144 			pArxText->fDeltaY += pArxText->fSpeedScrollY * (float)_iDiffFrame;
145 
146 			if(pArxText->fDeltaY >= (pArxText->rRect.bottom - pArxText->rRectClipp.bottom)) {
147 				pArxText->fDeltaY = static_cast<float>(pArxText->rRect.bottom - pArxText->rRectClipp.bottom);
148 			}
149 		} else {
150 			pArxText->lTimeScroll -= _iDiffFrame;
151 		}
152 
153 		++itManage;
154 	}
155 
156 }
157 
Render()158 void TextManager::Render() {
159 	vector<ManagedText *>::const_iterator itManage = entries.begin();
160 	for(; itManage != entries.end(); ++itManage) {
161 
162 		ManagedText * pArxText = *itManage;
163 
164 		Rect * pRectClip = NULL;
165 		if(pArxText->rRectClipp.right != Rect::Limits::max() || pArxText->rRectClipp.bottom != Rect::Limits::max()) {
166 			pRectClip = &pArxText->rRectClipp;
167 		}
168 
169 		float maxx;
170 		if(pArxText->rRect.right == Rect::Limits::max()) {
171 			maxx = std::numeric_limits<float>::infinity();
172 		} else {
173 			maxx = static_cast<float>(pArxText->rRect.right);
174 		}
175 
176 		long height = ARX_UNICODE_DrawTextInRect(pArxText->pFont, static_cast<float>(pArxText->rRect.left),
177 		                                         pArxText->rRect.top - pArxText->fDeltaY,
178 		                                         maxx,
179 		                                         pArxText->lpszUText, pArxText->lCol, pRectClip);
180 
181 		pArxText->rRect.bottom = pArxText->rRect.top + height;
182 	}
183 }
184 
Clear()185 void TextManager::Clear() {
186 
187 	vector<ManagedText *>::iterator itManage;
188 	for(itManage = entries.begin(); itManage < entries.end(); ++itManage) {
189 		delete *itManage;
190 	}
191 
192 	entries.clear();
193 }
194 
Empty() const195 bool TextManager::Empty() const
196 {
197 	return entries.empty();
198 }
199