zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Console_State.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <zeni_rest.h>
19 
20 #if defined(_DEBUG) && defined(_WINDOWS)
21 #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
22 #define new DEBUG_NEW
23 #endif
24 
25 namespace Zeni {
26 
27  Console_State::Console_State()
28  : m_virtual_screen(Point2f(0.0f, 0.0f), Point2f(float(get_Window().get_width() * 600.0f / get_Window().get_height()), 600.0f)),
29  m_projector(m_virtual_screen),
30  m_bg(Vertex2f_Color(Point2f(0.0f, 0.0f), get_Colors()["console_border"]),
31  Vertex2f_Color(Point2f(0.0f, 54.0f + 7.0f * get_Fonts()["system_36_x600"].get_text_height()), get_Colors()["console_border"]),
32  Vertex2f_Color(Point2f(m_virtual_screen.second.x, 54.0f + 7.0f * get_Fonts()["system_36_x600"].get_text_height()), get_Colors()["console_border"]),
33  Vertex2f_Color(Point2f(m_virtual_screen.second.x, 0.0f), get_Colors()["console_border"])),
34  m_log(Point2f(18.0f, 18.0f),
35  Point2f(m_virtual_screen.second.x - 18.0f,
36  18.0f + 6.0f * get_Fonts()["system_36_x600"].get_text_height()),
37  "system_36_x600",
38  "",
39  get_Colors()["console_foreground"],
40  false),
41  m_prompt(Point2f(18.0f, 36.0f + 6.0f * get_Fonts()["system_36_x600"].get_text_height()),
42  Point2f(m_virtual_screen.second.x - 18.0f,
43  36.0f + 7.0f * get_Fonts()["system_36_x600"].get_text_height()),
44  "system_36_x600",
45  "",
46  get_Colors()["console_foreground"],
47  true),
48  m_log_dirty(false),
49  m_child(0)
50  {
51  m_functions["args"] = new Console_Function;
52 
53  m_log.give_BG_Renderer(new Widget_Renderer_Color(get_Colors()["console_background"]));
54  m_prompt.give_BG_Renderer(new Widget_Renderer_Color(get_Colors()["console_background"]));
55  }
56 
57  Console_State::~Console_State() {
58  for(std::map<String, Console_Function *>::iterator it = m_functions.begin(); it != m_functions.end(); ++it)
59  delete it->second;
60  }
61 
62  Gamestate & Console_State::get_child() {
63  assert(m_child);
64  return *m_child;
65  }
66 
67  void Console_State::set_child(Gamestate child) {
68  delete m_child;
69  m_child = 0;
70  m_child = new Gamestate(child);
71  }
72 
73  void Console_State::clear_child() {
74  delete m_child;
75  m_child = 0;
76  }
77 
78  void Console_State::write_to_log(const String &text) {
79  if(!m_text.empty())
80  m_text += '\n';
81  m_text += text;
82 
83  const unsigned int max_lines = static_cast<unsigned int>(m_log.get_max_lines());
84  for(unsigned int endl_count = 0u, pos = static_cast<unsigned int>(m_text.size() - 1u); pos != static_cast<unsigned int>(-1); --pos)
85  if(m_text[pos] == '\n' && ++endl_count == max_lines) {
86  m_text = m_text.substr(pos + 1);
87  break;
88  }
89 
90  m_log_dirty = true;
91  }
92 
94  m_text.clear();
95  m_log_dirty = true;
96  }
97 
98  void Console_State::give_function(const String &name, Console_Function * const &function) {
99  assert(function);
100 
101  if(m_functions[name])
102  delete m_functions[name];
103  m_functions[name] = function;
104  }
105 
106  void Console_State::fire_command(const String &text) {
107  if(text.empty())
108  return;
109 
110  String command;
111  std::vector<String> args;
112 
113  String token;
114  bool in_quotes = false;
115  bool escaped = false;
116  for(String::const_iterator it = text.begin(); it != text.end(); ++it) {
117  if(escaped) {
118  token += *it;
119  escaped = false;
120  }
121  else {
122  switch(*it) {
123  case '"':
124  if(in_quotes || !token.empty()) {
125  if(command.empty())
126  command = token;
127  else
128  args.push_back(token);
129  token.clear();
130  }
131  in_quotes = !in_quotes;
132  break;
133 
134  case ' ':
135  case '\t':
136  if(in_quotes)
137  token += *it;
138  else if(!token.empty()) {
139  if(command.empty())
140  command = token;
141  else
142  args.push_back(token);
143  token.clear();
144  }
145  break;
146 
147  case '\\':
148  escaped = true;
149  break;
150 
151  default:
152  token += *it;
153  break;
154  }
155  }
156  }
157 
158  if(!token.empty())
159  if(command.empty())
160  command = token;
161  else
162  args.push_back(token);
163  else if(command.empty())
164  return;
165 
166  std::map<String, Console_Function *>::iterator func = m_functions.find(command);
167  if(func != m_functions.end())
168  (*(func->second))(*this, command, args);
169  else
170  write_to_log("Unrecognized command: " + command);
171  }
172 
173  void Console_State::on_event(const SDL_Event &event) {
174  m_handled_event = false;
176  if(!m_handled_event && m_child) {
177  assert(m_child);
178  m_child->on_event(event);
179  }
180  }
181 
182  void Console_State::on_key(const SDL_KeyboardEvent &event) {
183  Game &gr = get_Game();
184  const bool mod_nonshift = gr.get_key_state(SDLK_LALT) || gr.get_key_state(SDLK_RALT) ||
185  gr.get_key_state(SDLK_LCTRL) || gr.get_key_state(SDLK_RCTRL) ||
186 #if SDL_VERSION_ATLEAST(1,3,0)
187  gr.get_key_state(SDLK_LGUI) || gr.get_key_state(SDLK_LGUI);
188 #else
189  gr.get_key_state(SDLK_LMETA) || gr.get_key_state(SDLK_RMETA) ||
190  gr.get_key_state(SDLK_LSUPER) || gr.get_key_state(SDLK_RSUPER);
191 #endif
192 
193  if(event.type == SDL_KEYDOWN &&
194  !mod_nonshift)
195  {
196  switch(event.keysym.sym) {
197  case SDLK_RETURN:
198  if(m_prompt.get_edit_pos() != -1) {
199  fire_command(m_prompt.get_text());
200  m_prompt.set_text("");
201  }
202  break;
203 
204  default:
205  if(m_prompt.get_edit_pos() != -1) {
206  const String backup_text = m_prompt.get_text();
207  const int backup_pos = m_prompt.get_edit_pos();
208  const bool restore = m_prompt.get_num_lines() == 1;
209 
210  m_prompt.on_event(event);
211 
212  if(m_prompt.get_num_lines() > 1 && restore) {
213  m_prompt.set_text(backup_text);
214  m_prompt.seek(backup_pos);
215  }
216  }
217  break;
218  }
219  }
220 
221  m_handled_event = m_prompt.get_edit_pos() != -1;
222  }
223 
224  void Console_State::on_mouse_button(const SDL_MouseButtonEvent &event) {
225  m_prompt.on_event(event, m_virtual_screen);
226  m_handled_event = (float(event.y) / get_Window().get_height()) < (m_bg.c.position.y / 600.0f);
227  }
228 
229  void Console_State::on_mouse_motion(const SDL_MouseMotionEvent &event) {
230  m_prompt.on_event(event, m_virtual_screen);
231  m_handled_event = (float(event.y) / get_Window().get_height()) < (m_bg.c.position.y / 600.0f);
232  }
233 
234  void Console_State::perform_logic() {
235  m_virtual_screen = std::make_pair(Point2f(0.0f, 0.0f), Point2f(float(get_Window().get_width() * 600.0f / get_Window().get_height()), 600.0f));
236  m_projector = Projector2D(m_virtual_screen);
237 
238  if(m_bg.c.position.x != m_virtual_screen.second.x) {
239  m_bg.c.position.x = m_virtual_screen.second.x;
240  m_bg.d.position.x = m_virtual_screen.second.x;
241 
242  const float right = m_virtual_screen.second.x - 18.0f;
243  m_log.set_lower_right(Point2f(right, m_log.get_lower_right().y));
244  m_prompt.set_lower_right(Point2f(right, m_prompt.get_lower_right().y));
245  }
246 
247  m_child->perform_logic();
248  }
249 
250  void Console_State::prerender() {
251  assert(m_child);
252 
253  m_child->prerender();
254 
255  if(m_log_dirty) {
256  m_log.set_text(m_text);
257 
258  const size_t num_lines = m_log.get_num_lines();
259  const size_t max_lines = m_log.get_max_lines();
260  if(num_lines > max_lines)
261  m_log.erase_lines(0, static_cast<unsigned int>(num_lines - max_lines));
262 
263  m_text = m_log.get_text();
264  m_log_dirty = false;
265  }
266  }
267 
268  void Console_State::render() {
269  assert(m_child);
270 
271  m_child->render();
272 
273  Video &vr = get_Video();
274  vr.clear_depth_buffer();
275  vr.set_2d(m_virtual_screen);
276 
277  vr.render(m_bg);
278  m_log.render();
279  m_prompt.render();
280  }
281 
283  const String &name,
284  const std::vector<String> &args)
285  {
286  String fargs;
287 
288  if(!args.empty()) {
289  std::vector<String>::const_iterator it = args.begin();
290  fargs += *it;
291  for(++it; it != args.end(); ++it)
292  fargs += ", " + *it;
293  }
294 
295  console.write_to_log(name + '(' + fargs + ')');
296  }
297 
298 }
void on_event(const SDL_Event &event)
Definition: Gamestate.hxx:80
void clear()
Definition: String.cpp:323
friend class Game
Definition: Console_State.h:52
Colors & get_Colors()
Get access to the singleton.
Definition: Colors.cpp:51
GLclampf f
Definition: glew.h:3390
void give_function(const String &name, Console_Function *const &function)
void render() const
Definition: Widget.hxx:111
bool empty() const
Definition: String.cpp:325
EGLSurface EGLint x
Definition: eglext.h:293
EGLImageKHR EGLint * name
Definition: eglext.h:284
#define assert(x)
Definition: SDL_malloc.c:1234
GLenum func
Definition: SDL_opengl.h:5654
Game & get_Game()
Get access to the singleton.
Definition: Game.cpp:58
String substr(size_t pos=0, size_t n=npos) const
Definition: String.cpp:510
size_t get_max_lines() const
Definition: Widget.hxx:560
void erase_lines(const unsigned int &begin, const unsigned int &end)
Definition: Widget.hxx:584
Keyboard button event structure (event.key.*)
Definition: SDL_events.h:176
ALuint u
Definition: alMain.h:58
virtual void set_lower_right(const Point2f &lower_right_)
Definition: Widget.cpp:1242
iterator end()
Definition: String.cpp:301
#define true
Definition: ftrandom.c:49
void on_event(const SDL_KeyboardEvent &event)
Definition: Widget.hxx:69
virtual void on_event(const SDL_Event &event)
First check for events. Called by Game as part of the main gameloop.
Definition: Gamestate.cpp:36
iterator begin()
Definition: String.cpp:298
size_t get_num_lines() const
Definition: Widget.hxx:556
SDL_Keysym keysym
Definition: SDL_events.h:185
const Point2f & get_lower_right() const
Definition: Widget.hxx:156
Window & get_Window()
Get access to the singleton.
Definition: Window.cpp:392
Mouse motion event structure (event.motion.*)
Definition: SDL_events.h:218
Mouse button event structure (event.button.*)
Definition: SDL_events.h:234
static const int & get_height()
Get the height of the window.
Definition: Window.hxx:37
const int & get_edit_pos() const
Definition: Widget.cpp:1248
void set_text(const String &text_)
Definition: Widget.hxx:570
size_t size() const
Definition: String.cpp:310
SDL_Keycode sym
Definition: SDL_keyboard.h:50
const String & get_text() const
Definition: Widget.hxx:544
void write_to_log(const String &text)
void perform_logic()
Definition: Gamestate.hxx:85
General event structure.
Definition: SDL_events.h:495
Provide a text console to process commands.
Definition: Console_State.h:48
Fonts & get_Fonts()
Get access to the singleton.
Definition: Fonts.cpp:60
virtual void operator()(Console_State &console, const String &name, const std::vector< String > &args)
Video & get_Video()
Get access to the singleton.
Definition: Video.cpp:149
void seek(const int &edit_pos)
Definition: Widget.cpp:1274
void prerender()
Definition: Gamestate.hxx:89
GLfloat right
Definition: glew.h:13816
friend class Gamestate
Definition: Gamestate.h:83
#define false
Definition: ftrandom.c:50
cl_event event
Definition: glew.h:3556