1 /***************************************************************************
2              textscroller.cpp  -  "Scrolling text lines" widget
3                              -------------------
4     begin                : Sat Apr 14 2007
5     copyright            : (C) 2003 by Gabor Torok
6     email                : cctorok@yahoo.com
7 ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #include "common/constants.h"
18 #include "textscroller.h"
19 #include "scourge.h"
20 #include "sdlhandler.h"
21 #include "render/map.h"
22 #include "shapepalette.h"
23 
24 // ###### MS Visual C++ specific ######
25 #if defined(_MSC_VER) && defined(_DEBUG)
26 # define new DEBUG_NEW
27 # undef THIS_FILE
28 static char THIS_FILE[] = __FILE__;
29 #endif
30 
31 using namespace std;
32 
33 #define LINE_HEIGHT 15
34 #define LINES_SHOWN 7
35 #define SCROLL_SPEED 100
36 #define OFFSET_DELTA 1
37 #define MAX_QUEUE_SIZE 200
38 #define SCROLL_WIDTH 500
39 
TextScroller(Scourge * scourge)40 TextScroller::TextScroller( Scourge *scourge ) {
41 	this->scourge = scourge;
42 	this->xp = 300;
43 	this->yp = 0;
44 	startOffset = lineOffset = 0;
45 	offset = 0;
46 	lastCheck = SDL_GetTicks();
47 	inside = false;
48 	visible = false;
49 	scrollTexture = 0;
50 }
51 
~TextScroller()52 TextScroller::~TextScroller() {
53 	for ( size_t i = 0; i < color.size(); ++i ) {
54 		delete color[i];
55 	}
56 }
57 
addDescription(char const * description,float r,float g,float b,int logLevel)58 void TextScroller::addDescription( char const* description, float r, float g, float b, int logLevel ) {
59 	if ( scourge->getUserConfiguration()->getLogLevel() < logLevel ) return;
60 
61 	string s = description;
62 	color.insert( color.begin(), new Color( r, g, b, 1 ) );
63 	text.insert( text.begin(), s );
64 	if ( text.size() == MAX_QUEUE_SIZE ) {
65 		text.erase( text.end() - 1 );
66 		Color *c = color[ color.size() - 1 ];
67 		delete( c );
68 		color.erase( color.end() - 1 );
69 	}
70 }
71 
writeLogMessage(char const * message,int messageType,int logLevel)72 void TextScroller::writeLogMessage( char const* message, int messageType, int logLevel ) {
73 
74 	if ( messageType == Constants::MSGTYPE_NORMAL ) {
75 		addDescription( message, 1, 1, 0, logLevel );
76 	} else if ( messageType == Constants::MSGTYPE_MISSION ) {
77 		addDescription( message, 1, 1, 1, logLevel );
78 	} else if ( messageType == Constants::MSGTYPE_PLAYERDAMAGE ) {
79 		addDescription( message, 1, 0, 0, logLevel );
80 	} else if ( messageType == Constants::MSGTYPE_NPCDAMAGE ) {
81 		addDescription( message, 0, 1, 0, logLevel );
82 	} else if ( messageType == Constants::MSGTYPE_PLAYERMAGIC ) {
83 		addDescription( message, 1, 0, 1, logLevel );
84 	} else if ( messageType == Constants::MSGTYPE_NPCMAGIC ) {
85 		addDescription( message, 0.7f, 0, 1, logLevel );
86 	} else if ( messageType == Constants::MSGTYPE_PLAYERITEM ) {
87 		addDescription( message, 0, 0, 1, logLevel );
88 	} else if ( messageType == Constants::MSGTYPE_NPCITEM ) {
89 		addDescription( message, 0, 0.5f, 1, logLevel );
90 	} else if ( messageType == Constants::MSGTYPE_PLAYERBATTLE ) {
91 		addDescription( message, 1, 0.8f, 0.8f, logLevel );
92 	} else if ( messageType == Constants::MSGTYPE_NPCBATTLE ) {
93 		addDescription( message, 1, 0.5f, 0.5f, logLevel );
94 	} else if ( messageType == Constants::MSGTYPE_PLAYERDEATH ) {
95 		addDescription( message, 0.7f, 0.7f, 0, logLevel );
96 	} else if ( messageType == Constants::MSGTYPE_NPCDEATH ) {
97 		addDescription( message, 0, 0.7f, 0, logLevel );
98 	} else if ( messageType == Constants::MSGTYPE_FAILURE ) {
99 		addDescription( message, 0.7f, 0.7f, 0.7f, logLevel );
100 	} else if ( messageType == Constants::MSGTYPE_STATS ) {
101 		addDescription( message, 1, 0.5f, 0, logLevel );
102 	} else if ( messageType == Constants::MSGTYPE_SYSTEM ) {
103 		addDescription( message, 0, 0.8f, 0.8f, logLevel );
104 	} else if ( messageType == Constants::MSGTYPE_SKILL ) {
105 		addDescription( message, 0, 1, 1, logLevel );
106 	}
107 }
108 
draw()109 void TextScroller::draw() {
110 
111 	if ( !visible ) {
112 		lineOffset = 0;
113 	}
114 
115 	if ( scourge->getParty()->isRealTimeMode() && !visible ) {
116 		Uint32 now = SDL_GetTicks();
117 		if ( now - lastCheck > SCROLL_SPEED ) {
118 			lastCheck = now;
119 			offset += OFFSET_DELTA;
120 			if ( offset >= LINE_HEIGHT ) {
121 				offset = 0;
122 				text.insert( text.begin(), "" );
123 				color.insert( color.begin(), new Color( 0, 0, 0, 0 ) );
124 				for ( unsigned int i = LINES_SHOWN; i < text.size(); i++ ) {
125 					if ( text[i] == "" ) {
126 						text.erase( text.begin() + i );
127 						Color *c = color[ i ];
128 						delete( c );
129 						color.erase( color.begin() + i );
130 						i--;
131 					}
132 				}
133 			}
134 		}
135 	}
136 
137 	int height = LINES_SHOWN * LINE_HEIGHT;
138 
139 	glPushMatrix();
140 	glLoadIdentity();
141 	int ytop = ( scourge->inTurnBasedCombat() ? yp + 50 : yp );
142 	glTranslatef( xp, ytop, 0 );
143 	glDisable( GL_DEPTH_TEST );
144 
145 	if ( visible ) {
146 		int margin = 10;
147 		glEnable( GL_BLEND );
148 		glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
149 		glDisable( GL_TEXTURE_2D );
150 		// glColor4f( 1, 1, 1, 0.25f );
151 		glColor4f( 0, 0, 0, 0.5f );
152 		glBegin( GL_TRIANGLE_STRIP );
153 		glVertex2d( -margin, 0 );
154 		glVertex2d( SCROLL_WIDTH + margin, 0 );
155 		glVertex2d( -margin, height + margin );
156 		glVertex2d( SCROLL_WIDTH + margin, height + margin );
157 		glEnd();
158 		glColor4f( 0.5f, 0.5f, 0.5f, 1 );
159 		glBegin( GL_LINE_LOOP );
160 		glVertex2d( -margin, height + margin );
161 		glVertex2d( -margin, 0 );
162 		glVertex2d( SCROLL_WIDTH + margin, 0 );
163 		glVertex2d( SCROLL_WIDTH + margin, height + margin );
164 		glEnd();
165 
166 		glBegin( GL_LINE_LOOP );
167 		glVertex2d( SCROLL_WIDTH + margin - 10, height );
168 		glVertex2d( SCROLL_WIDTH + margin - 10, 10 );
169 		glVertex2d( SCROLL_WIDTH + margin - 7, 10 );
170 		glVertex2d( SCROLL_WIDTH + margin - 7, height );
171 		glEnd();
172 		int ypos = static_cast<int>( ( lineOffset * ( height - 10 ) ) / static_cast<float>( text.size() - 1 ) );
173 		glBegin( GL_TRIANGLE_STRIP );
174 		glVertex2d( SCROLL_WIDTH + margin - 10, height - ( ypos + 10 ) );
175 		glVertex2d( SCROLL_WIDTH + margin - 7, height - ( ypos + 10 ) );
176 		glVertex2d( SCROLL_WIDTH + margin - 10, height - ypos );
177 		glVertex2d( SCROLL_WIDTH + margin - 7, height - ypos );
178 		glEnd();
179 
180 		glEnable( GL_TEXTURE_2D );
181 		glDisable( GL_BLEND );
182 	}
183 
184 	glScissor( xp, scourge->getScreenHeight() - ( ytop + height ), SCROLL_WIDTH, height );
185 	glEnable( GL_SCISSOR_TEST );
186 
187 	int currentOffset = ( visible ? 0 : offset );
188 	int x = 0;
189 	int y = height - currentOffset;
190 	// cerr << "text.size=" << text.size() << endl;
191 	for ( unsigned int i = lineOffset; static_cast<int>( i ) < lineOffset + LINES_SHOWN && i < text.size(); i++ ) {
192 		if ( text[ i ] != "" ) {
193 			Color *c = color[ i ];
194 			float a;
195 			if ( visible ) a = 1;
196 			else a = c->a * ( ( LINES_SHOWN - ( ( i - lineOffset ) + ( currentOffset / static_cast<float>( LINE_HEIGHT ) ) ) ) / static_cast<float>( LINES_SHOWN ) );
197 			glColor4f( c->r, c->g, c->b, a  );
198 			scourge->getSDLHandler()->texPrint( x, y, text[ i ].c_str() );
199 		}
200 		y -= LINE_HEIGHT;
201 	}
202 	glDisable( GL_SCISSOR_TEST );
203 	glEnable( GL_DEPTH_TEST );
204 	glPopMatrix();
205 	glColor4f( 1, 1, 1, 1 );
206 }
207 
scrollUp()208 void TextScroller::scrollUp() {
209 }
210 
scrollDown()211 void TextScroller::scrollDown() {
212 }
213 
handleEvent(SDL_Event * event)214 bool TextScroller::handleEvent( SDL_Event *event ) {
215 	int mx = scourge->getSDLHandler()->mouseX;
216 	int my = scourge->getSDLHandler()->mouseY;
217 	int ytop = ( scourge->inTurnBasedCombat() ? yp + 50 : yp );
218 	bool before = visible;
219 	inside = ( mx >= xp && mx < xp + SCROLL_WIDTH &&
220 	           my >= ytop && my < ytop + LINES_SHOWN * LINE_HEIGHT &&
221 	           !( scourge->getSession()->getMap()->isMouseRotating() ||
222 	              scourge->getSession()->getMap()->isMouseZooming() ||
223 	              scourge->getSession()->getMap()->isMapMoving() ) );
224 	if ( inside && !before && my >= ytop && my <= ytop + 15 ) {
225 		visible = true;
226 		startOffset = lineOffset = 0;
227 		for ( unsigned int i = 0; i < text.size(); i++ ) {
228 			if ( text[i] != "" ) {
229 				startOffset = lineOffset = i;
230 				break;
231 			}
232 		}
233 	}
234 
235 	if ( !inside && before ) visible = false;
236 
237 	if ( event->type == SDL_MOUSEBUTTONDOWN ) {
238 		if ( inside && visible ) {
239 			if ( event->button.button == SDL_BUTTON_WHEELUP ) {
240 				lineOffset++;
241 				if ( lineOffset + LINES_SHOWN >= static_cast<int>( text.size() ) ) {
242 					lineOffset = text.size() - LINES_SHOWN + 1;
243 				}
244 			} else if ( event->button.button == SDL_BUTTON_WHEELDOWN ) {
245 				lineOffset--;
246 				if ( lineOffset < startOffset ) lineOffset = startOffset;
247 			}
248 		}
249 	}
250 	return visible;
251 }
252 
253