Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/shell/shell.cc @ 9861

Last change on this file since 9861 was 9861, checked in by bensch, 18 years ago

Changed the ShellBuffer to DebugBuffer, as the dependency is only one way, and it makes no sense for the rest of Orxonox Modules to know the Shell

File size: 15.9 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program 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, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SHELL
17
18#include "shell.h"
19#include "shell_command.h"
20#include "debug_buffer.h"
21#include "shell_input.h"
22
23#include "multi_line_text.h"
24
25#include "graphics_engine.h"
26#include "material.h"
27#include "event_handler.h"
28#include "debug.h"
29
30namespace OrxShell
31{
32
33  SHELL_COMMAND(clear, Shell, clear)
34  ->describe("Clears the shell from unwanted lines (empties all buffers)")
35  ->setAlias("clear");
36  SHELL_COMMAND(deactivate, Shell, deactivate)
37  ->describe("Deactivates the Shell. (moves it into background)")
38  ->setAlias("hide");
39  SHELL_COMMAND(textsize, Shell, setTextSize)
40  ->describe("Sets the size of the Text size, linespacing")
41  ->defaultValues(15, 0);
42  SHELL_COMMAND(textcolor, Shell, setTextColor)
43  ->describe("Sets the Color of the Shells Text (red, green, blue, alpha)")
44  ->defaultValues(SHELL_DEFAULT_TEXT_COLOR);
45  SHELL_COMMAND(backgroundcolor, Shell, setBackgroundColor)
46  ->describe("Sets the Color of the Shells Background (red, green, blue, alpha)")
47  ->defaultValues(SHELL_DEFAULT_BACKGROUND_COLOR);
48  SHELL_COMMAND(backgroundimage, Shell, setBackgroundImage)
49  ->describe("sets the background image to load for the Shell")
50  ->completionPlugin(0, OrxShell::CompletorFileSystem());
51  SHELL_COMMAND(font, Shell, setFont)
52  ->describe("Sets the font of the Shell")
53  ->defaultValues(SHELL_DEFAULT_FONT)
54  ->completionPlugin(0, OrxShell::CompletorFileSystem(".ttf", "fonts/"));
55
56  ObjectListDefinition(Shell);
57
58  /**
59   * standard constructor
60   */
61  Shell::Shell ()
62  {
63    this->registerObject(this, Shell::_objectList);
64
65    this->setName("Shell");
66
67    this->shellBuffer = DebugBuffer::getInstance();
68
69    // EVENT-Handler subscription of '`' to all States.
70    this->subscribeEvent(ES_ALL, SDLK_BACKQUOTE);
71    this->subscribeEvent(ES_ALL, SDLK_F12);
72    this->subscribeEvent(ES_SHELL, SDLK_PAGEUP);
73    this->subscribeEvent(ES_SHELL, SDLK_PAGEDOWN);
74    this->subscribeEvent(ES_SHELL, EV_VIDEO_RESIZE);
75    EventHandler::getInstance()->withUNICODE(ES_SHELL, true);
76
77    // BUFFER
78    this->bufferIterator = this->shellBuffer->getBuffer().begin();
79
80    // INPUT LINE
81    this->setLayer(E2D_LAYER_ABOVE_ALL);
82    this->shellInput.setLayer(E2D_LAYER_ABOVE_ALL);
83
84    // Element2D and generals
85    this->setSizeX2D(GraphicsEngine::getInstance()->getResolutionX());
86    this->setAbsCoor2D(3, -400);
87    this->textSize = 15;
88    this->lineSpacing = 0;
89    this->bActive = false;
90    this->fontFile = SHELL_DEFAULT_FONT;
91
92    this->setBufferDisplaySize(10);
93
94    this->setTextColor(SHELL_DEFAULT_TEXT_COLOR);
95    this->setBackgroundColor(SHELL_DEFAULT_BACKGROUND_COLOR);
96
97
98    this->deactivate();
99  }
100
101  /**
102   * @brief standard deconstructor
103   */
104  Shell::~Shell ()
105  {
106    // delete the displayable Buffers
107    while (!this->bufferText.empty())
108    {
109      delete this->bufferText.front();
110      this->bufferText.pop_front();
111    }
112  }
113
114  /**
115   * @brief activates the shell
116   *
117   * This also feeds the Last few lines from the main buffers into the displayBuffer
118   */
119  void Shell::activate()
120  {
121    if (this->bActive == true)
122      PRINTF(3)("The shell is already active\n");
123    this->bActive = true;
124    this->activate2D();
125
126    EventHandler::getInstance()->pushState(ES_SHELL);
127
128    this->setRelCoorSoft2D(0, 0, 5);
129
130    this->linesProcessed = this->shellBuffer->getLineCount();
131    std::list<std::string>::const_iterator textLine = this->bufferIterator = this->shellBuffer->getBuffer().begin();
132    for (std::list<MultiLineText*>::iterator text = this->bufferText.begin(); text != this->bufferText.end(); ++text)
133    {
134      (*text)->setVisibility(true);
135      if (textLine !=  this->shellBuffer->getBuffer().end())
136      {
137        (*text)->setText((*textLine));
138        textLine++;
139      }
140      else
141        (*text)->setText("");
142    }
143    this->shellInput.setVisibility(true);
144    this->updateResolution( GraphicsEngine::getInstance()->getResolutionX());
145    this->repositionText();
146  }
147
148  /**
149   * @brief deactiveates the Shell.
150   */
151  void Shell::deactivate()
152  {
153    if (this->bActive == false)
154      PRINTF(3)("The shell is already inactive\n");
155    this->bActive = false;
156    this->deactivate2D();
157
158    EventHandler::getInstance()->popState();
159
160    this->setRelCoorSoft2D(0, -(int)this->shellHeight, 5);
161
162    for (std::list<MultiLineText*>::iterator text = this->bufferText.begin(); text != this->bufferText.end(); ++text)
163      (*text)->setVisibility(false);
164    this->shellInput.setVisibility(false);
165
166    // Go to the End again.
167    this->bufferIterator = this->shellBuffer->getBuffer().begin();
168  }
169
170  /**
171   * @brief sets the File to load the fonts from
172   * @param fontFile the file to load the font from
173   *
174   * it is quite important, that the font pointed too really exists!
175   * (be aware that within orxonox fontFile is relative to the Data-Dir)
176   */
177  void Shell::setFont(const std::string& fontFile)
178  {
179    this->fontFile = fontFile;
180
181    this->applySettings();
182  }
183
184  /**
185   * @brief sets the size of the text and spacing
186   * @param textSize the size of the Text in Pixels
187   * @param lineSpacing the size of the Spacing between two lines in pixels
188   *
189   * this also rebuilds the entire Text, inputLine and displayBuffer,
190   * to be accurate again.
191   */
192  void Shell::setTextSize(unsigned int textSize, unsigned int lineSpacing)
193  {
194    this->textSize = textSize;
195    this->lineSpacing = lineSpacing;
196
197    this->applySettings();
198  }
199
200  /**
201   * @brief sets the color of the Font.
202   * @param r: red
203   * @param g: green
204   * @param b: blue
205   * @param a: alpha-value.
206   */
207  void Shell::setTextColor(float r, float g, float b, float a)
208  {
209    this->textColor[0] = r;
210    this->textColor[1] = g;
211    this->textColor[2] = b;
212    this->textColor[3] = a;
213
214    this->applySettings();
215  }
216
217  /**
218   * @brief sets the color of the Backgrond.
219   * @param r: red
220   * @param g: green
221   * @param b: blue
222   * @param a: alpha-value.
223   */
224  void Shell::setBackgroundColor(float r, float g, float b, float a)
225  {
226    this->backgroundMaterial.setDiffuse(r, g, b);
227    this->backgroundMaterial.setTransparency(a);
228  }
229
230  /**
231   * @brief sets a nice background image to the Shell's background
232   * @param fileName the filename of the Image to load
233   */
234  void Shell::setBackgroundImage(const std::string& fileName)
235  {
236    this->backgroundMaterial.setDiffuseMap(fileName);
237  }
238
239
240  /**
241   * @brief updates the Shell's Width
242   * @param width the new Width.
243   */
244  void Shell::updateResolution(unsigned int width)
245  {
246    if (width == this->getSizeX2D())
247      return;
248    this->setSizeX2D(width);
249    for (std::list<MultiLineText*>::iterator textIt = this->bufferText.begin(); textIt != this->bufferText.end(); ++textIt)
250    {
251      (*textIt)->setLineWidth(width);
252    }
253  }
254
255  /**
256   * @brief repositiones all the Texts to their position.
257   */
258  void Shell::repositionText()
259  {
260    int linePos = -1;
261    std::list<MultiLineText*>::iterator textIt;
262    for (textIt = this->bufferText.begin() ; textIt != this->bufferText.end(); ++textIt )
263    {
264      linePos += (*textIt)->getLineCount();
265      (*textIt)->setRelCoorSoft2D(this->calculateLinePosition(linePos), 8);
266    }
267  }
268
269
270  /**
271   * @brief applies the Shells Settings to a single Text of the Shell.
272   * @param text the Text to apply the settings to.
273   */
274  void Shell::applyTextSettings(Text* text)
275  {
276    text->setSize(this->textSize);
277    text->setFont(this->fontFile, this->textSize);
278    text->setColor(this->textColor[0], this->textColor[1], this->textColor[2]);
279    text->setBlending(this->textColor[3]);
280    text->setLayer(this->getLayer());
281    if (text->getParent2D() != this)
282      text->setParent2D(this);
283  }
284
285  /**
286   * @brief resets the Values of all visible shell's commandos to the Shell's stored values
287   *
288   * this functions synchronizes the stored Data with the visible one.
289   */
290  void Shell::applySettings()
291  {
292    this->applyTextSettings(&this->shellInput);
293    this->shellInput.setRelCoor2D(15, (this->textSize + this->lineSpacing)*(this->bufferDisplaySize));
294
295    /* Here we create a Copy of the Buffer, so that we do not f**k up the List when some
296     * output is routed from Some other Thread or by Changing any Values.
297     */
298    std::list<MultiLineText*> bufferTextCopy = this->bufferText;
299    for (std::list<MultiLineText*>::iterator textIt = bufferTextCopy.begin(); textIt != bufferTextCopy.end(); ++textIt)
300    {
301      this->applyTextSettings(*textIt);
302      (*textIt)->setLineSpacing(this->lineSpacing);
303      (*textIt)->setLineWidth(this->getSizeX2D() * GraphicsEngine::getInstance()->getResolutionX());
304    }
305    this->repositionText();
306
307    this->shellHeight = (this->textSize + this->lineSpacing) * (bufferDisplaySize+1);
308  }
309
310  /**
311   * @brief sets The count of Lines to display in the buffer.
312   * @param bufferDisplaySize the count of lines to display in the Shell-Buffer.
313   */
314  void Shell::setBufferDisplaySize(unsigned int bufferDisplaySize)
315  {
316    unsigned int oldSize = this->bufferText.size();
317    if (oldSize > bufferDisplaySize)
318    {
319      for (unsigned int i = bufferDisplaySize; i <= oldSize; i++)
320      {
321        delete this->bufferText.back();
322        this->bufferText.pop_back();
323      }
324    }
325    else if (oldSize < bufferDisplaySize)
326    {
327      for (unsigned int i = oldSize; i <= bufferDisplaySize; i++)
328      {
329        this->bufferText.push_back(new MultiLineText);
330      }
331    }
332    this->bufferDisplaySize = bufferDisplaySize;
333    this->applySettings();
334  }
335
336  /**
337   * @brief deletes all the Buffers
338   */
339  void Shell::flush()
340  {
341    for (std::list<MultiLineText*>::iterator textIt = this->bufferText.begin(); textIt != this->bufferText.end(); ++textIt)
342    {
343      (*textIt)->setText("");  // remove all chars from the BufferTexts.
344    }
345    this->shellBuffer->flush();
346    // BUFFER FLUSHING
347  }
348
349  /**
350   * @brief prints out some text to the input-buffers
351   * @param text the text to output.
352   */
353  void Shell::printToDisplayBuffer(const std::string& text)
354  {
355    // Remove Last Entry and prepend it to the front.
356    this->bufferText.push_front(this->bufferText.back());
357    this->bufferText.pop_back();
358
359    // Set the new Text.
360    this->bufferText.front()->setText(text);
361    this->bufferIterator = this->shellBuffer->getBuffer().begin();
362
363    // The LineCount will be started here.
364
365    // The First Line gets a special Animation
366    this->bufferText.front()->setRelCoor2D(this->calculateLinePosition(0)- Vector2D(-1000,0));
367
368    // Move all lines one Entry up.
369    this->repositionText();
370  }
371
372
373  /**
374   * @brief moves the Display buffer (up + or down - )
375   * @param lineCount the count by which to shift the InputBuffer.
376   *
377   * @todo make this work
378   */
379  void Shell::moveDisplayBuffer(int lineCount)
380  {
381    // moving the iterator to the right position (counting the steps)
382    int moves = 0;
383    while (moves != lineCount)
384    {
385      if (moves < lineCount)
386      {
387        if(this->bufferIterator == --this->shellBuffer->getBuffer().end())
388          break;
389        ++moves;
390        ++this->bufferIterator;
391      }
392      else
393      {
394        if (this->bufferIterator == this->shellBuffer->getBuffer().begin())
395          break;
396        --moves;
397        --this->bufferIterator;
398      }
399    }
400
401
402    // redisplay the buffers
403    std::list<MultiLineText*>::iterator textIt;
404
405    // Give a Graphical Representation that no move is possible.
406    if (moves == 0)
407    {
408      int linePos = -1;
409      for (textIt = this->bufferText.begin(); textIt != this->bufferText.end(); ++textIt)
410      {
411        linePos += (*textIt)->getLineCount();
412        (*textIt)->setRelCoor2D(this->calculateLinePosition(linePos)+ Vector2D(20,0));
413        (*textIt)->setRelCoorSoft2D(this->calculateLinePosition(linePos), 10);
414      }
415      return;
416    }
417
418    // Move all the Lines.
419    int linePos = moves;
420    std::list<std::string>::const_iterator it = this->bufferIterator;
421    for (textIt = this->bufferText.begin(); textIt != this->bufferText.end(); ++textIt, ++it)
422    {
423      if (it == this->shellBuffer->getBuffer().end())
424      {
425        PRINTF(1)("LAST LINE REACHED\n");
426        break;
427      }
428
429
430      (*textIt)->setRelCoor2D(calculateLinePosition( (linePos++ > 0) ? linePos : 0));
431      (*textIt)->setText((*it));
432    }
433    while (textIt != this->bufferText.end())
434    {
435      (*textIt)->setText("");
436      textIt++;
437    }
438
439    this->repositionText();
440  }
441
442  /**
443   * @brief clears the Shell (empties all buffers)
444   */
445  void Shell::clear()
446  {
447    this->flush();
448    DebugBuffer::addBufferLineStatic("orxonox - shell\n ==================== \n", NULL);
449  }
450
451  /**
452   * @brief listens for some event
453   * @param event the Event happened
454   */
455  void Shell::process(const Event &event)
456  {
457    if (event.bPressed)
458    {
459      if (event.type == SDLK_BACKQUOTE || event.type == SDLK_F12)
460      {
461        if (this->bActive == false)
462          this->activate();
463        else
464          this->deactivate();
465      }
466      else if (event.type == SDLK_PAGEUP)
467      {
468        this->moveDisplayBuffer(+this->bufferDisplaySize-1);
469      }
470      else if (event.type == SDLK_PAGEDOWN)
471      {
472        this->moveDisplayBuffer(-this->bufferDisplaySize+1);
473      }
474      else if (event.type == EV_VIDEO_RESIZE)
475      {
476        this->updateResolution(event.resize.w);
477        this->repositionText();
478      }
479    }
480  }
481
482  void Shell::tick(float dt)
483  {
484    if (this->linesProcessed < this->shellBuffer->getLineCount())
485    {
486      unsigned int pollLines = this->shellBuffer->getLineCount() - this->linesProcessed;
487      if (this->bufferText.size() < pollLines)
488        pollLines = this->bufferText.size();
489      if (unlikely(this->shellBuffer->getBuffer().size() < pollLines))
490        pollLines = this->shellBuffer->getBuffer().size();
491
492      std::list<std::string>::const_iterator line = this->shellBuffer->getBuffer().begin();
493      unsigned int i;
494      for(i = 0; i < pollLines; i++)
495        line ++;
496      for (i = 0; i < pollLines; i++)
497      {
498        this->printToDisplayBuffer((*--line));
499      }
500    }
501    this->linesProcessed = this->shellBuffer->getLineCount();
502  }
503
504
505  /**
506   * displays the Shell
507   */
508  void Shell::draw() const
509  {
510    // transform for alignment.
511    // setting the Blending effects
512
513    this->backgroundMaterial.select();
514
515    glBegin(GL_TRIANGLE_STRIP);
516
517    glTexCoord2f(0, 0);
518    glVertex2f(this->getAbsCoor2D().x,   this->getAbsCoor2D().);
519
520    glTexCoord2f(1, 0);
521    glVertex2f(GraphicsEngine::getInstance()->getResolutionX() - this->getAbsCoor2D().x, this->getAbsCoor2D().);
522
523    glTexCoord2f(0, 1);
524    glVertex2f(this->getAbsCoor2D().x, this->getAbsCoor2D().y + this->shellHeight);
525
526    glTexCoord2f(1, 1);
527    glVertex2f(GraphicsEngine::getInstance()->getResolutionX() - this->getAbsCoor2D().x, this->getAbsCoor2D().y + this->shellHeight);
528
529    glEnd();
530  }
531
532  ///////////////////////
533  // HELPER FUNCTIONS  //
534  ///////////////////////
535
536  /**
537   * @brief calculates the position of a Buffer-Display Line
538   * @param lineNumber the lineNumber from the bottom to calculate the position from
539   * @returns the Position of the Line.
540   */
541  Vector2D Shell::calculateLinePosition(unsigned int lineNumber)
542  {
543    return Vector2D(5.0f, (float)(this->textSize + this->lineSpacing)*(float)((int)this->bufferDisplaySize - (int)lineNumber - (int)1));
544  }
545
546
547
548  /**
549   * @brief displays some nice output from the Shell
550   */
551  void Shell::debug() const
552  {
553    PRINT(3)("Debugging output to console (not this shell)\n");
554
555    //   if (this->pressedKey != SDLK_FIRST)
556    //     printf("%s::%f %f\n", SDLKToKeyname(this->pressedKey), this->delayed, this->repeatDelay);
557
558
559    this->shellBuffer->debug();
560  }
561
562  /**
563   * @brief a Handy Function, to Test the behaviour of the Shell.
564   */
565  void Shell::testShell() const
566  {
567    for (unsigned int i = 0; i < 100; i++)
568      PRINT(0)("%d\n", i);
569  }
570  SHELL_COMMAND(test, Shell, testShell);
571
572}
Note: See TracBrowser for help on using the repository browser.