1 #include "Font.h"
2 #include "HImage.h"
3 #include "Types.h"
4 #include "Animated_ProgressBar.h"
5 #include "MemMan.h"
6 #include "Debug.h"
7 #include "Font_Control.h"
8 #include "VObject.h"
9 #include "VSurface.h"
10 #include "Video.h"
11 #include "Render_Dirty.h"
12 #include "Music_Control.h"
13 #include "ContentMusic.h"
14 #include "Timer_Control.h"
15 #include "SysUtil.h"
16 #include "UILayout.h"
17 
18 #include <string_theory/string>
19 
20 
21 #define MAX_PROGRESSBARS 4
22 
23 enum ProgressBarFlags
24 {
25 	PROGRESS_NONE           = 0,
26 	PROGRESS_PANEL          = 1 << 0,
27 	PROGRESS_DISPLAY_TEXT   = 1 << 1,
28 	PROGRESS_USE_SAVEBUFFER = 1 << 2, // use the save buffer when display the text
29 	PROGRESS_LOAD_BAR       = 1 << 3
30 };
31 ENUM_BITSET(ProgressBarFlags)
32 
33 struct PROGRESSBAR
34 {
35 	ProgressBarFlags flags;
36 	SGPBox           pos;
37 	UINT16 usPanelLeft, usPanelTop, usPanelRight, usPanelBottom;
38 	UINT16 usColor, usLtColor, usDkColor;
39 	ST::string title;
40 	SGPFont usTitleFont;
41 	UINT8 ubTitleFontForeColor, ubTitleFontShadowColor;
42 	SGPFont usMsgFont;
43 	UINT8 ubMsgFontForeColor, ubMsgFontShadowColor;
44 	UINT32 fill_colour;
45 	double rStart, rEnd;
46 	double rLastActual;
47 };
48 
49 static PROGRESSBAR* pBar[MAX_PROGRESSBARS];
50 
51 
CreateLoadingScreenProgressBar()52 void CreateLoadingScreenProgressBar()
53 {
54 	CreateProgressBar(0, STD_SCREEN_X + 162, STD_SCREEN_Y + 427, 318, 16);
55 	pBar[0]->flags |= PROGRESS_LOAD_BAR;
56 }
57 
RemoveLoadingScreenProgressBar()58 void RemoveLoadingScreenProgressBar()
59 {
60 	RemoveProgressBar( 0 );
61 	SetFontShadow(DEFAULT_SHADOW);
62 }
63 
64 
CreateProgressBar(const UINT8 ubProgressBarID,const UINT16 x,const UINT16 y,const UINT16 w,const UINT16 h)65 void CreateProgressBar(const UINT8 ubProgressBarID, const UINT16 x, const UINT16 y, const UINT16 w, const UINT16 h)
66 {
67 	PROGRESSBAR* const pNew = new PROGRESSBAR{};
68 
69 	if( pBar[ ubProgressBarID ] )
70 		RemoveProgressBar( ubProgressBarID );
71 
72 	pBar[ ubProgressBarID ] = pNew;
73 	//Assign coordinates
74 	pNew->flags                = PROGRESS_NONE;
75 	pNew->pos.x                = x;
76 	pNew->pos.y                = y;
77 	pNew->pos.w                = w;
78 	pNew->pos.h                = h;
79 	//Init default data
80 	pNew->usMsgFont            = FONT12POINT1;
81 	pNew->ubMsgFontForeColor   = FONT_BLACK;
82 	pNew->ubMsgFontShadowColor = 0;
83 	SetRelativeStartAndEndPercentage(ubProgressBarID, 0, 100, ST::null);
84 	pNew->title = ST::null;
85 
86 	//Default the progress bar's color to be red
87 	pNew->fill_colour = FROMRGB(150, 0, 0);
88 }
89 
90 
91 //You may also define a panel to go in behind the progress bar.  You can now assign a title to go with
92 //the panel.
DefineProgressBarPanel(UINT32 ubID,UINT8 r,UINT8 g,UINT8 b,UINT16 usLeft,UINT16 usTop,UINT16 usRight,UINT16 usBottom)93 void DefineProgressBarPanel( UINT32 ubID, UINT8 r, UINT8 g, UINT8 b,
94 				UINT16 usLeft, UINT16 usTop, UINT16 usRight, UINT16 usBottom )
95 {
96 	PROGRESSBAR *pCurr;
97 	Assert( ubID < MAX_PROGRESSBARS );
98 	pCurr = pBar[ ubID ];
99 	if( !pCurr )
100 		return;
101 
102 	pCurr->flags |= PROGRESS_PANEL;
103 	pCurr->usPanelLeft = usLeft;
104 	pCurr->usPanelTop = usTop;
105 	pCurr->usPanelRight = usRight;
106 	pCurr->usPanelBottom = usBottom;
107 	pCurr->usColor = Get16BPPColor( FROMRGB( r, g, b ) );
108 	//Calculate the slightly lighter and darker versions of the same rgb color
109 	pCurr->usLtColor = Get16BPPColor( FROMRGB( (UINT8)MIN( 255, (UINT16)(r*1.33)),
110 						(UINT8)MIN( 255, (UINT16)(g*1.33)),
111 						(UINT8)MIN( 255, (UINT16)(b*1.33)) ));
112 	pCurr->usDkColor = Get16BPPColor( FROMRGB( (UINT8)(r*0.75), (UINT8)(g*0.75), (UINT8)(b*0.75) ) );
113 }
114 
115 //Assigning a title for the panel will automatically position the text horizontally centered on the
116 //panel and vertically centered from the top of the panel, to the top of the progress bar.
SetProgressBarTitle(UINT32 ubID,const ST::string & str,SGPFont font,UINT8 ubForeColor,UINT8 ubShadowColor)117 void SetProgressBarTitle(UINT32 ubID, const ST::string& str, SGPFont font, UINT8 ubForeColor, UINT8 ubShadowColor)
118 {
119 	PROGRESSBAR *pCurr;
120 	Assert( ubID < MAX_PROGRESSBARS );
121 	pCurr = pBar[ ubID ];
122 	if( !pCurr )
123 		return;
124 	pCurr->title = str;
125 	pCurr->usTitleFont = font;
126 	pCurr->ubTitleFontForeColor = ubForeColor;
127 	pCurr->ubTitleFontShadowColor = ubShadowColor;
128 }
129 
130 //Unless you set up the attributes, any text you pass to SetRelativeStartAndEndPercentage will
131 //default to FONT12POINT1 in a black color.
SetProgressBarMsgAttributes(UINT32 ubID,SGPFont const font,UINT8 ubForeColor,UINT8 ubShadowColor)132 void SetProgressBarMsgAttributes(UINT32 ubID, SGPFont const font, UINT8 ubForeColor, UINT8 ubShadowColor)
133 {
134 	PROGRESSBAR *pCurr;
135 	Assert( ubID < MAX_PROGRESSBARS );
136 	pCurr = pBar[ ubID ];
137 	if( !pCurr )
138 		return;
139 	pCurr->usMsgFont            = font;
140 	pCurr->ubMsgFontForeColor = ubForeColor;
141 	pCurr->ubMsgFontShadowColor = ubShadowColor;
142 }
143 
144 
145 //When finished, the progress bar needs to be removed.
RemoveProgressBar(UINT8 ubID)146 void RemoveProgressBar( UINT8 ubID )
147 {
148 	Assert( ubID < MAX_PROGRESSBARS );
149 	if( pBar[ubID] )
150 	{
151 		delete pBar[ubID];
152 		pBar[ubID] = NULL;
153 		return;
154 	}
155 }
156 
157 /* An important setup function.  The best explanation is through example.  The
158  * example being the loading of a file -- there are many stages of the map
159  * loading.  In JA2, the first step is to load the tileset.  Because it is a
160  * large chunk of the total loading of the map, we may gauge that it takes up
161  * 30% of the total load.  Because it is also at the beginning, we would pass in
162  * the arguments (0, 30, "text").  As the process animates using
163  * UpdateProgressBar(0 to 100), the total progress bar will only reach 30% at
164  * the 100% mark within UpdateProgressBar.  At that time, you would go onto the
165  * next step, resetting the relative start and end percentage from 30 to
166  * whatever, until your done. */
SetRelativeStartAndEndPercentage(UINT8 id,UINT32 uiRelStartPerc,UINT32 uiRelEndPerc,const ST::string & str)167 void SetRelativeStartAndEndPercentage(UINT8 id, UINT32 uiRelStartPerc, UINT32 uiRelEndPerc, const ST::string& str)
168 {
169 	Assert(id < MAX_PROGRESSBARS);
170 	PROGRESSBAR* const bar = pBar[id];
171 	if (!bar) return;
172 
173 	bar->rStart = uiRelStartPerc * 0.01;
174 	bar->rEnd   = uiRelEndPerc   * 0.01;
175 
176 	//Render the entire panel now, as it doesn't need update during the normal rendering
177 	if (bar->flags & PROGRESS_PANEL)
178 	{ // Draw panel
179 		UINT16 const l = bar->usPanelLeft;
180 		UINT16 const t = bar->usPanelTop;
181 		UINT16 const r = bar->usPanelRight;
182 		UINT16 const b = bar->usPanelBottom;
183 		ColorFillVideoSurfaceArea(FRAME_BUFFER, l,     t,     r,     b,     bar->usLtColor);
184 		ColorFillVideoSurfaceArea(FRAME_BUFFER, l + 1, t + 1, r,     b,     bar->usDkColor);
185 		ColorFillVideoSurfaceArea(FRAME_BUFFER, l + 1, t + 1, r - 1, b - 1, bar->usColor);
186 		InvalidateRegion(l, t, r, b);
187 		if (!bar->title.empty())
188 		{ // Draw title
189 			SGPFont  const font = bar->usTitleFont;
190 			INT32 const x    = (r + l - StringPixLength(bar->title, font)) / 2; // Center
191 			SetFontAttributes(font, bar->ubTitleFontForeColor, bar->ubTitleFontShadowColor);
192 			MPrint(x, t + 3, bar->title);
193 		}
194 	}
195 
196 	if (bar->flags & PROGRESS_DISPLAY_TEXT && !str.empty())
197 	{ // Draw message
198 		INT32 const x    = bar->pos.x;
199 		INT32 const y    = bar->pos.y + bar->pos.h;
200 		SGPFont  const font = bar->usMsgFont;
201 		if (bar->flags & PROGRESS_USE_SAVEBUFFER)
202 		{
203 			UINT16 const h = GetFontHeight(font);
204 			RestoreExternBackgroundRect(x, y, bar->pos.w, h + 3);
205 		}
206 
207 		SetFontAttributes(font, bar->ubMsgFontForeColor, bar->ubMsgFontShadowColor);
208 		MPrint(x, y + 3, str);
209 	}
210 }
211 
212 
213 //This part renders the progress bar at the percentage level that you specify.  If you have set relative
214 //percentage values in the above function, then the uiPercentage will be reflected based off of the relative
215 //percentages.
RenderProgressBar(UINT8 ubID,UINT32 uiPercentage)216 void RenderProgressBar( UINT8 ubID, UINT32 uiPercentage )
217 {
218 	static UINT32 uiLastTime = 0;
219 	UINT32 uiCurTime = GetJA2Clock();
220 	double rActual;
221 	PROGRESSBAR *pCurr=NULL;
222 	//UINT32 r, g;
223 
224 	Assert( ubID < MAX_PROGRESSBARS );
225 	pCurr = pBar[ubID];
226 
227 	if( pCurr == NULL )
228 		return;
229 
230 	if( pCurr )
231 	{
232 		rActual = pCurr->rStart+(pCurr->rEnd-pCurr->rStart)*uiPercentage*0.01;
233 
234 		if( rActual - pCurr->rLastActual < 0.01 )
235 		{
236 			return;
237 		}
238 
239 		pCurr->rLastActual = ( DOUBLE )( ( INT32)( rActual * 100 ) * 0.01 );
240 
241 		INT32 const x   = pCurr->pos.x;
242 		INT32 const y   = pCurr->pos.y;
243 		INT32 const w   = pCurr->pos.w;
244 		INT32 const h   = pCurr->pos.h;
245 		INT32 const end = (INT32)(x + 2.0 + rActual * (w - 4));
246 		if (end < x + 2 || x + w - 2 < end) return;
247 		if (pCurr->flags & PROGRESS_LOAD_BAR)
248 		{
249 			ColorFillVideoSurfaceArea(FRAME_BUFFER, x, y, end, y + h, Get16BPPColor(pCurr->fill_colour));
250 		}
251 		else
252 		{
253 			//Border edge of the progress bar itself in gray
254 			ColorFillVideoSurfaceArea( FRAME_BUFFER,
255 				x, y, x + w, y + h,
256 				Get16BPPColor(FROMRGB(160, 160, 160)) );
257 			//Interior of progress bar in black
258 			ColorFillVideoSurfaceArea( FRAME_BUFFER,
259 				x + 2, y + 2, x + w - 2, y + h - 2,
260 				Get16BPPColor(FROMRGB(  0,   0,   0)) );
261 			ColorFillVideoSurfaceArea(FRAME_BUFFER,	x + 2, y + 2, end, y + h - 2, Get16BPPColor(FROMRGB(72 , 155, 24)));
262 		}
263 		InvalidateRegion(x, y, x + w, y + h);
264 		ExecuteBaseDirtyRectQueue();
265 		EndFrameBufferRender();
266 		RefreshScreen();
267 	}
268 
269 	// update music here
270 	if( uiCurTime > ( uiLastTime + 200 ) )
271 	{
272 		MusicPoll();
273 		uiLastTime = GetJA2Clock();
274 	}
275 }
276 
SetProgressBarColor(UINT8 ubID,UINT8 ubColorFillRed,UINT8 ubColorFillGreen,UINT8 ubColorFillBlue)277 void SetProgressBarColor( UINT8 ubID, UINT8 ubColorFillRed, UINT8 ubColorFillGreen, UINT8 ubColorFillBlue )
278 {
279 	PROGRESSBAR *pCurr=NULL;
280 
281 	Assert( ubID < MAX_PROGRESSBARS );
282 
283 	pCurr = pBar[ubID];
284 	if( pCurr == NULL )
285 		return;
286 
287 	pCurr->fill_colour = FROMRGB(ubColorFillRed, ubColorFillGreen, ubColorFillBlue);
288 }
289 
290 
SetProgressBarTextDisplayFlag(UINT8 ubID,BOOLEAN fDisplayText,BOOLEAN fUseSaveBuffer,BOOLEAN fSaveScreenToFrameBuffer)291 void SetProgressBarTextDisplayFlag( UINT8 ubID, BOOLEAN fDisplayText, BOOLEAN fUseSaveBuffer, BOOLEAN fSaveScreenToFrameBuffer )
292 {
293 	PROGRESSBAR *pCurr=NULL;
294 
295 
296 	Assert( ubID < MAX_PROGRESSBARS );
297 
298 	pCurr = pBar[ubID];
299 	if( pCurr == NULL )
300 		return;
301 
302 	ProgressBarFlags flags = pCurr->flags & ~(PROGRESS_DISPLAY_TEXT | PROGRESS_USE_SAVEBUFFER);
303 	if (fDisplayText)   flags |= PROGRESS_DISPLAY_TEXT;
304 	if (fUseSaveBuffer) flags |= PROGRESS_USE_SAVEBUFFER;
305 	pCurr->flags = flags;
306 
307 	//if we are to use the save buffer, blit the portion of the screen to the save buffer
308 	if( fSaveScreenToFrameBuffer )
309 	{
310 		UINT16 usFontHeight = GetFontHeight( pCurr->usMsgFont )+3;
311 
312 		//blit everything to the save buffer ( cause the save buffer can bleed through )
313 		BlitBufferToBuffer(FRAME_BUFFER, guiSAVEBUFFER, pCurr->pos.x, pCurr->pos.y + pCurr->pos.h, pCurr->pos.w, usFontHeight);
314 	}
315 }
316