1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2011
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D 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 2 of the License, or
9 // (at your option) any later version.
10 //
11 // Scorched3D 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 along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20
21 #include <console/ConsoleImpl.h>
22 #include <common/Keyboard.h>
23 #include <common/Defines.h>
24 #include <common/Logger.h>
25 #include <GLEXT/GLState.h>
26 #include <GLEXT/GLViewPort.h>
27 #include <GLW/GLWFont.h>
28 #include <GLW/GLWToolTip.h>
29 #include <limits.h>
30
ConsoleImpl()31 ConsoleImpl::ConsoleImpl() :
32 GameStateI("Console"),
33 height_(0.0f), opening_(false),
34 lines_(1000), historyPosition_(-1), font_(0),
35 showCursor_(true)
36 {
37 Logger::addLogger(this);
38 }
39
~ConsoleImpl()40 ConsoleImpl::~ConsoleImpl()
41 {
42
43 }
44
init()45 void ConsoleImpl::init()
46 {
47 methods_.init();
48 }
49
logMessage(LoggerInfo & info)50 void ConsoleImpl::logMessage(LoggerInfo &info)
51 {
52 addLine(false, info.getMessage());
53 }
54
keyboardCheck(const unsigned state,float frameTime,char * buffer,unsigned int keyState,KeyboardHistory::HistoryElement * history,int hisCount,bool & skipRest)55 void ConsoleImpl::keyboardCheck(const unsigned state, float frameTime,
56 char *buffer, unsigned int keyState,
57 KeyboardHistory::HistoryElement *history, int hisCount,
58 bool &skipRest)
59 {
60 // Use the history to ensure that no keystrokes are missed
61 // regardless of the framerate.
62 KEYBOARDKEY("CONSOLE", consoleKey);
63 for (int i=0; i<hisCount; i++)
64 {
65 unsigned int dik = history[i].sdlKey;
66 if (consoleKey->keyMatch(dik))
67 {
68 resetPositions();
69 if (currentLine_.empty()) opening_ = !opening_;
70 else currentLine_ = "";
71 skipRest = true;
72 }
73 }
74
75 if (height_ > 0.0f)
76 {
77 // Use the history to ensure that no keystrokes are missed
78 // regardless of the framerate.
79 if (!skipRest)
80 for (int i=0; i<hisCount; i++)
81 {
82 char unicodeKey = history[i].representedUnicode;
83 unsigned int dik = history[i].sdlKey;
84
85 if (unicodeKey >= ' ')
86 {
87 resetPositions();
88 if (unicodeKey < 127) currentLine_ += (char) unicodeKey;
89 }
90 else
91 {
92 switch (dik)
93 {
94 case SDLK_ESCAPE:
95 resetPositions();
96 if (currentLine_.empty()) opening_ = false;
97 else currentLine_ = "";
98 break;
99 case SDLK_TAB:
100 resetPositions();
101 {
102 std::vector<ConsoleRule *> matches;
103 std::string result =
104 rules_.matchRule(currentLine_.c_str(), matches);
105 if (result.length() > 0) currentLine_ = result;
106
107 addLine(false, "-------------------");
108 std::vector<ConsoleRule *>::iterator itor;
109 for (itor = matches.begin();
110 itor != matches.end();
111 ++itor)
112 {
113 std::string text = (*itor)->toString();
114 addLine(false, text.c_str());
115 }
116 }
117 break;
118 case SDLK_BACKSPACE:
119 case SDLK_DELETE:
120 resetPositions();
121 currentLine_ = currentLine_.substr(0, currentLine_.length() - 1);
122 break;
123 case SDLK_RETURN:
124 if (!currentLine_.empty())
125 {
126 resetPositions();
127 addLine(true, currentLine_.c_str());
128 history_.push_front(currentLine_.c_str());
129 currentLine_.erase();
130 }
131 break;
132 case SDLK_UP:
133 historyPosition_++;
134 if (historyPosition_ >= int(history_.size()))
135 historyPosition_ = int(history_.size()) - 1;
136 if (historyPosition_ >= 0)
137 currentLine_ = history_[historyPosition_];
138 break;
139 case SDLK_DOWN:
140 historyPosition_--;
141 if (historyPosition_ <= 0)
142 historyPosition_ = (history_.empty()?-1:0);
143 if (historyPosition_ >= 0)
144 currentLine_ = history_[historyPosition_];
145 break;
146 case SDLK_PAGEUP:
147 lines_.scroll(-5);
148 break;
149 case SDLK_PAGEDOWN:
150 lines_.scroll(+5);
151 break;
152 case SDLK_HOME:
153 lines_.scroll(INT_MIN);
154 break;
155 case SDLK_END:
156 lines_.scroll(INT_MAX);
157 break;
158 }
159 }
160 }
161 skipRest = true;
162 }
163 else
164 {
165 std::list<KeyboardKey *> &keys = Keyboard::instance()->getCommandKeys();
166 std::list<KeyboardKey *>::iterator keyItor = keys.begin();
167 std::list<KeyboardKey *>::iterator keyEndItor = keys.end();
168 for (; keyItor != keyEndItor; ++keyItor)
169 {
170 KeyboardKey *key = (*keyItor);
171 if (key->keyDown(buffer, keyState, false))
172 {
173 resetPositions();
174 addLine(true, key->getName());
175 }
176 }
177 }
178 }
179
resetPositions()180 void ConsoleImpl::resetPositions()
181 {
182 historyPosition_ = -1;
183 lines_.resetScroll();
184 }
185
simulate(const unsigned state,float frameTime)186 void ConsoleImpl::simulate(const unsigned state, float frameTime)
187 {
188 const GLfloat dropSpeed = 1200.0f;
189 if (opening_)
190 {
191 height_ += frameTime * dropSpeed;
192 }
193 else
194 {
195 height_ -= frameTime * dropSpeed;
196 if (height_ < 0.0f) height_ = 0.0f;
197 }
198
199 static float ctime = 0;
200 ctime += frameTime;
201 if (ctime > 0.5f)
202 {
203 ctime = 0.0f;
204 showCursor_ = !showCursor_;
205 }
206 }
207
draw(const unsigned state)208 void ConsoleImpl::draw(const unsigned state)
209 {
210 if (height_ <= 0.0f) return;
211
212 GLState currentState(GLState::DEPTH_OFF | GLState::TEXTURE_OFF | GLState::BLEND_ON);
213
214 GLfloat width = (GLfloat) GLViewPort::getWidth();
215 GLfloat top = (GLfloat) GLViewPort::getHeight();
216
217 drawBackdrop(width, top);
218 drawText(width, top);
219 }
220
drawBackdrop(float width,float top)221 void ConsoleImpl::drawBackdrop(float width, float top)
222 {
223 if (height_ > top * .85f) height_ = top * .85f;
224
225 GLWToolTip::instance()->clearToolTip(
226 0.0f, top - height_ + 10.0f,
227 width, height_);
228
229 glColor4f(0.0f, 0.0f, 0.0f, 0.9f);
230 glBegin(GL_QUADS);
231 glVertex2f(0.0f, top - height_ + 10.0f);
232 glVertex2f(width, top - height_ + 10.0f);
233 glVertex2f(width, top);
234 glVertex2f(0.0f, top);
235
236 glVertex2f(10.0f, top - height_);
237 glVertex2f(width - 10.0f, top - height_);
238 glVertex2f(width, top - height_ + 10.0f);
239 glVertex2f(0.0f, top - height_ + 10.0f);
240 glEnd();
241
242 glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
243 glBegin(GL_LINE_STRIP);
244 glVertex2f(0.0f, top - height_ + 10.0f);
245 glVertex2f(10.0f, top - height_);
246 glVertex2f(width - 10.0f, top - height_);
247 glVertex2f(width, top - height_ + 10.0f);
248 glEnd();
249 }
250
drawText(float width,float top)251 void ConsoleImpl::drawText(float width, float top)
252 {
253 static Vector color(1.0f, 1.0f, 1.0f);
254 if (!font_) font_ = GLWFont::instance()->getCourierFont();
255 font_->draw(color, 14,
256 10.0f, top - (height_ - 14.0f), 0.0f,
257 S3D::formatStringBuffer("> %s%c",
258 currentLine_.c_str(),
259 (showCursor_?'_':' ')));
260
261 lines_.drawLines(font_, top - (height_ - 14.0f), top, width);
262 }
263
addLine(bool parse,const std::string & text)264 void ConsoleImpl::addLine(bool parse, const std::string &text)
265 {
266 lines_.addLine(text, parse);
267 if (parse)
268 {
269 rules_.addLine(this, text.c_str());
270 }
271 }
272
help()273 void ConsoleImpl::help()
274 {
275 std::vector<std::string>::iterator itor;
276 std::vector<std::string> result;
277 rules_.dump(result);
278
279 for (itor = result.begin();
280 itor != result.end();
281 ++itor)
282 {
283 addLine(false, *itor);
284 }
285 }
286