Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/ChatInputHandler.cc @ 8102

Last change on this file since 8102 was 8079, checked in by landauf, 14 years ago

merged usability branch back to trunk

incomplete summary of the changes in this branch:

  • enhanced keyboard navigation in GUIs
  • implemented new graphics menu and changeable window size at runtime
  • added developer mode
  • HUD shows if game is paused, game pauses if ingame menu is opened
  • removed a few obsolete commands and hid some that are more for internal use
  • numpad works in console and gui
  • faster loading of level info
  • enhanced usage of compositors (Shader class)
  • improved camera handling, configurable FOV and aspect ratio
  • Property svn:eol-style set to native
File size: 10.5 KB
RevLine 
[6776]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Sandro 'smerkli' Merkli
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ChatInputHandler.h"
[8079]30
31#include <cassert>
32#include <string>
[6846]33#include <CEGUIWindow.h>
[8079]34#include <CEGUIWindowManager.h>
[6934]35#include <elements/CEGUIListbox.h>
36#include <elements/CEGUIListboxItem.h>
37#include <elements/CEGUIListboxTextItem.h>
[6776]38
[8079]39#include "util/ScopedSingletonManager.h"
40#include "core/CoreIncludes.h"
41#include "core/GUIManager.h"
42#include "core/command/ConsoleCommand.h"
43#include "core/input/InputBuffer.h"
44#include "core/input/InputManager.h"
45#include "core/input/InputState.h"
46#include "network/Host.h"
47
48#include "PlayerManager.h"
49#include "infos/PlayerInfo.h"
50
[7127]51namespace orxonox
[6776]52{
[6777]53  /* singleton */
[6788]54  ManageScopedSingleton( ChatInputHandler, ScopeID::Graphics, false );
[6876]55
56  /* add commands to console */
[7284]57  SetConsoleCommand( "startchat", &ChatInputHandler::activate_static );
58  SetConsoleCommand( "startchat_small", &ChatInputHandler::activate_small_static );
[6777]59
[6776]60  /* constructor */
[6788]61  ChatInputHandler::ChatInputHandler()
[6776]62  {
[6777]63    /* register the object  */
64    RegisterObject(ChatInputHandler);
65
[6776]66    /* create necessary objects */
67    this->inpbuf = new InputBuffer();
[6876]68    this->disp_offset = 0;
[6846]69    assert( this->inpbuf != NULL );
[6776]70
[6870]71    /* generate chatbox ui and chatbox-inputonly ui */
[6846]72    GUIManager::getInstance().loadGUI( "ChatBox" );
[6870]73    GUIManager::getInstance().loadGUI( "ChatBox-inputonly" );
[6846]74
[7043]75    /* setup colors */
76    setupColors();
77
[6788]78    /* configure the input buffer */
[6791]79    configureInputBuffer();
[6788]80
81    this->inputState = InputManager::getInstance().createInputState( "chatinput", false, false, InputStatePriority::Dynamic );
82    this->inputState->setKeyHandler(this->inpbuf);
[6776]83  }
84
[8079]85  ChatInputHandler::~ChatInputHandler()
86  {
87    /* Clean up */
88    InputManager::getInstance().destroyState("chatinput");
89    delete this->inpbuf;
90  }
91
[7043]92  /* configure input buffer, sub for the constructor */
[6776]93  void ChatInputHandler::configureInputBuffer()
94  {
[6910]95    /* INSTALL CALLBACKS */
[6846]96    /* input has changed */
[6788]97    this->inpbuf->registerListener(this, &ChatInputHandler::inputChanged, true);
[6846]98
99    /* add a line */
[6788]100    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\r',   false);
101    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\n',   false);
[6776]102
[6846]103    /* backspace */
[6788]104    this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\b',   true);
[6890]105    //this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\177', true);
[6776]106
[6846]107    /* exit the chatinputhandler thingy (tbd) */
[6788]108    this->inpbuf->registerListener(this, &ChatInputHandler::exit,            '\033', true); // escape
[6776]109
[6846]110    /* delete character */
[6788]111    this->inpbuf->registerListener(this, &ChatInputHandler::deleteChar,      KeyCode::Delete);
[6776]112
[6846]113    /* cursor movement */
[6788]114    this->inpbuf->registerListener(this, &ChatInputHandler::cursorRight,     KeyCode::Right);
115    this->inpbuf->registerListener(this, &ChatInputHandler::cursorLeft,      KeyCode::Left);
116    this->inpbuf->registerListener(this, &ChatInputHandler::cursorEnd,       KeyCode::End);
117    this->inpbuf->registerListener(this, &ChatInputHandler::cursorHome,      KeyCode::Home);
[6846]118
[6910]119    /* GET WINDOW POINTERS */
[6846]120    input = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox/input" );
[6870]121    inputonly = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox-inputonly/input" );
122
[6910]123    /* get pointer to the history window */
[6846]124    CEGUI::Window *history = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox/history" );
[6910]125
126    /* cast it to a listbox */
[7127]127    lb_history = dynamic_cast<CEGUI::Listbox*>(history);
[6846]128
129    /* assert wee */
130    assert( lb_history );
[6776]131  }
132
[7043]133  /* setup the colors, sub for the constructor */
134  void ChatInputHandler::setupColors()
135  {
[7049]136    /* auto variables */
[7043]137    float red = 1.0, green = 0.5, blue = 0.5;
138    int i = 0;
[6777]139
[7049]140    // three loops: red tones, blue tones and green tones
[7043]141    // reds
142    for( i = 0; i < NumberOfColors/3; ++i )
[8079]143    { this->text_colors[ i ] = CEGUI::colour( red, green, blue );
[7183]144      green += 0.2f, blue += 0.2f;
[7043]145    }
146
147    // greens
148    red = 0.5, green = 1, blue = 0.5;
149    for( ; i < NumberOfColors*2/3; ++i )
[8079]150    { this->text_colors[ i ] = CEGUI::colour( red, green, blue );
[7183]151      red += 0.2f, blue += 0.2f;
[7043]152    }
153
[7127]154    // blues
[7043]155    red = 0.5, green = 0.5, blue = 1;
156    for( ; i < NumberOfColors; ++i )
[8079]157    { this->text_colors[ i ] = CEGUI::colour( red, green, blue );
[7183]158      red += 0.2f, green += 0.2f;
[7043]159    }
160  }
161
162
[6777]163  /* activate, deactivate */
[6791]164  void ChatInputHandler::activate_static()
[6870]165  { ChatInputHandler::getInstance().activate( true ); }
166
167  void ChatInputHandler::activate_small_static()
168  { ChatInputHandler::getInstance().activate( false ); }
169
170  void ChatInputHandler::activate( bool full )
[6777]171  {
172    /* start listening */
[6788]173    InputManager::getInstance().enterState("chatinput");
[6846]174
175    /* MARK add spawning of chat widget stuff here.*/
[6870]176    if( full )
177      GUIManager::getInstance().showGUI( "ChatBox" );
178    else
179      GUIManager::getInstance().showGUI( "ChatBox-inputonly" );
[6879]180
181    this->fullchat = full;
[6777]182  }
183
[7127]184  void ChatInputHandler::deactivate()
[6777]185  {
186    /* stop listening */
[6788]187    InputManager::getInstance().leaveState("chatinput");
[6846]188
[6876]189    /* un-spawning of chat widget stuff */
[6846]190    GUIManager::getInstance().hideGUI( "ChatBox" );
[6870]191    GUIManager::getInstance().hideGUI( "ChatBox-inputonly" );
[6777]192  }
193
[6885]194
[7043]195  /* subs for incomingChat */
196  void ChatInputHandler::sub_setcolor( CEGUI::ListboxTextItem *tocolor,
197    std::string name )
198  {
[7049]199    /* sanity checks */
[7043]200    if( !tocolor )
201      COUT(2) << "Empty ListBoxTextItem given to "
202        "ChatInputhandler::sub_setcolor().\n";
203
204    /* "hash" the name */
205    int hash = 0;
206    for( int i = name.length(); i > 0; --i )
207      hash += name[i-1];
208    hash = hash % this->NumberOfColors;
209
210    /* set the color according to the hash */
[8079]211    tocolor->setTextColours( this->text_colors[ hash ] );
[7043]212  }
213
214  /* handle incoming chat */
[7127]215  void ChatInputHandler::incomingChat(const std::string& message,
[6885]216    unsigned int senderID)
[6876]217  {
[7043]218    /* look up the actual name of the sender */
219    std::string text, name = "unknown";
[6885]220
[7043]221    /* setup player name info */
[6885]222    if (senderID != CLIENTID_UNKNOWN)
[7127]223    {
[6885]224       PlayerInfo* player = PlayerManager::getInstance().getClient(senderID);
225       if (player)
226         name = player->getName();
227    }
228
[7043]229    /* assemble the text */
230    text = name + ": " + message;
231
232    /* create item */
[6885]233    CEGUI::ListboxTextItem *toadd = new CEGUI::ListboxTextItem( text );
[7043]234
235    /* setup colors */
236    sub_setcolor( toadd, name );
237
238    /* now add */
[6885]239    this->lb_history->addItem( dynamic_cast<CEGUI::ListboxItem*>(toadd) );
[7127]240    this->lb_history->ensureItemIsVisible(
[7043]241      dynamic_cast<CEGUI::ListboxItem*>(toadd) );
[6885]242
[7043]243    /* make sure the history handles it */
[6885]244    this->lb_history->handleUpdatedItemData();
[7127]245  }
[6885]246
247
[7043]248  /* sub for inputchanged */
[7127]249  void ChatInputHandler::sub_adjust_dispoffset( int maxlen,
250    int cursorpos,
[6885]251    int inplen )
252  {
[6876]253    /* already start offsetting 5 characters before end */
254    if( cursorpos+5 > maxlen )
[7127]255    {
[6876]256      /* always stay 5 characters ahead of end, looks better */
257      ((disp_offset = cursorpos-maxlen+5) >= 0) ? 1 : disp_offset = 0;
258
259      /* enforce visibility of cursor */
260      (disp_offset > cursorpos ) ? disp_offset = 0 : 1;
261    }
[7127]262
[6876]263    /* make sure we don't die at substr */
264    if( inplen <= disp_offset ) disp_offset = 0;
265  }
266
[6776]267  /* callbacks for InputBuffer */
268  void ChatInputHandler::inputChanged()
269  {
[6846]270    /* update the cursor and the window */
271    std::string raw = this->inpbuf->get();
[6876]272    int cursorpos = this->inpbuf->getCursorPosition();
[7127]273
[6846]274    /* get string before cursor */
[6876]275    std::string left = raw.substr( 0, cursorpos );
[6837]276
[6846]277    /* see if there's a string after the cursor */
278    std::string right = "";
279    if( raw.length() >= left.length()+1 )
[6876]280      right = raw.substr( cursorpos );
[7127]281
[6846]282    /* set the text */
[6876]283    std::string assembled = "$ " + left + "|" + right;
284
[6879]285    if( this->fullchat )
[7127]286    {
[6879]287      /* adjust curser position - magic number 5 for font width */
[7183]288      sub_adjust_dispoffset( (int)(this->input->getUnclippedInnerRect().getWidth()/6),
[6879]289        cursorpos, assembled.length() );
290      this->input->setProperty( "Text", assembled.substr( disp_offset ) );
291    }
292    else
293    {
294      /* adjust curser position - magic number 5 for font width */
[7183]295      sub_adjust_dispoffset( (int)(this->inputonly->getUnclippedInnerRect().getWidth()/6),
[6879]296        cursorpos, assembled.length() );
297      this->inputonly->setProperty( "Text", assembled.substr( disp_offset) );
298    }
[6876]299
300    /* reset display offset */
301    disp_offset = 0;
[6776]302  }
303
304  void ChatInputHandler::addline()
305  {
306    /* actually do send what was input */
307    /* a) get the string out of the inputbuffer */
[6788]308    std::string msgtosend = this->inpbuf->get();
[6776]309
[6846]310    if( msgtosend.length() == 0 )
311    { this->deactivate();
312      return;
313    }
314
[6776]315    /* b) clear the input buffer */
[6788]316    if (this->inpbuf->getSize() > 0)
317      this->inpbuf->clear();
[6776]318
319    /* c) send the chat via some call */
[6777]320    Host::Chat( msgtosend );
[6776]321
[6885]322    /* d) stop listening to input - only if this is not fullchat */
[6879]323    if( !this->fullchat )
324      this->deactivate();
[6846]325
[6776]326  }
327
328  void ChatInputHandler::backspace()
[6846]329  { this->inpbuf->removeBehindCursor(); }
[6776]330
331  void ChatInputHandler::deleteChar()
[6846]332  { this->inpbuf->removeAtCursor(); }
[6776]333
334  void ChatInputHandler::cursorRight()
[6846]335  { this->inpbuf->increaseCursor(); }
[7127]336
[6776]337  void ChatInputHandler::cursorLeft()
[6846]338  { this->inpbuf->decreaseCursor(); }
[7127]339
[6776]340  void ChatInputHandler::cursorEnd()
[6846]341  { this->inpbuf->setCursorToEnd(); }
[6776]342
343  void ChatInputHandler::cursorHome()
[6846]344  { this->inpbuf->setCursorToBegin(); }
[6776]345
346  void ChatInputHandler::exit()
[6879]347  {
348    /* b) clear the input buffer */
349    if (this->inpbuf->getSize() > 0)
350      this->inpbuf->clear();
[6776]351
[6879]352    /* d) stop listening to input  */
353    this->deactivate();
354  }
355
[6776]356}
Note: See TracBrowser for help on using the repository browser.