Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/output/src/orxonox/chat/ChatInputHandler.cc @ 8959

Last change on this file since 8959 was 8829, checked in by landauf, 13 years ago

enhanced chat system. chat related code is now separated into network-side code (located in Host, Client, Server) and client-side code (located in ChatManager).
note that there are now two chat related listeners: NetworkChatListener, which is used to send chat from the network to ChatManager, and ChatListener, which is used to send online and offline chat from ChatManager to the actual chat interfaces (ChatOverlay, ChatInputHandler, …).
the "chat" console command now supports a second argument which is the clientID of the receiver. this allows private messages (or gameplay messages directed to only one specific player).

  • Property svn:eol-style set to native
File size: 10.2 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
[8829]47#include "chat/ChatManager.h"
[8079]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 )
[8809]201      orxout(internal_warning) << "Empty ListBoxTextItem given to "
202        "ChatInputhandler::sub_setcolor()." << endl;
[7043]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 */
[8829]215  void ChatInputHandler::incomingChat(const std::string& message, const std::string& name)
[6876]216  {
[7043]217    /* create item */
[8829]218    CEGUI::ListboxTextItem *toadd = new CEGUI::ListboxTextItem( message );
[7043]219
220    /* setup colors */
[8826]221    if (name != "")
222      sub_setcolor( toadd, name );
[7043]223
224    /* now add */
[6885]225    this->lb_history->addItem( dynamic_cast<CEGUI::ListboxItem*>(toadd) );
[7127]226    this->lb_history->ensureItemIsVisible(
[7043]227      dynamic_cast<CEGUI::ListboxItem*>(toadd) );
[6885]228
[7043]229    /* make sure the history handles it */
[6885]230    this->lb_history->handleUpdatedItemData();
[7127]231  }
[6885]232
233
[7043]234  /* sub for inputchanged */
[7127]235  void ChatInputHandler::sub_adjust_dispoffset( int maxlen,
236    int cursorpos,
[6885]237    int inplen )
238  {
[6876]239    /* already start offsetting 5 characters before end */
240    if( cursorpos+5 > maxlen )
[7127]241    {
[6876]242      /* always stay 5 characters ahead of end, looks better */
243      ((disp_offset = cursorpos-maxlen+5) >= 0) ? 1 : disp_offset = 0;
244
245      /* enforce visibility of cursor */
246      (disp_offset > cursorpos ) ? disp_offset = 0 : 1;
247    }
[7127]248
[6876]249    /* make sure we don't die at substr */
250    if( inplen <= disp_offset ) disp_offset = 0;
251  }
252
[6776]253  /* callbacks for InputBuffer */
254  void ChatInputHandler::inputChanged()
255  {
[6846]256    /* update the cursor and the window */
257    std::string raw = this->inpbuf->get();
[6876]258    int cursorpos = this->inpbuf->getCursorPosition();
[7127]259
[6846]260    /* get string before cursor */
[6876]261    std::string left = raw.substr( 0, cursorpos );
[6837]262
[6846]263    /* see if there's a string after the cursor */
264    std::string right = "";
265    if( raw.length() >= left.length()+1 )
[6876]266      right = raw.substr( cursorpos );
[7127]267
[6846]268    /* set the text */
[6876]269    std::string assembled = "$ " + left + "|" + right;
270
[6879]271    if( this->fullchat )
[7127]272    {
[6879]273      /* adjust curser position - magic number 5 for font width */
[7183]274      sub_adjust_dispoffset( (int)(this->input->getUnclippedInnerRect().getWidth()/6),
[6879]275        cursorpos, assembled.length() );
276      this->input->setProperty( "Text", assembled.substr( disp_offset ) );
277    }
278    else
279    {
280      /* adjust curser position - magic number 5 for font width */
[7183]281      sub_adjust_dispoffset( (int)(this->inputonly->getUnclippedInnerRect().getWidth()/6),
[6879]282        cursorpos, assembled.length() );
283      this->inputonly->setProperty( "Text", assembled.substr( disp_offset) );
284    }
[6876]285
286    /* reset display offset */
287    disp_offset = 0;
[6776]288  }
289
290  void ChatInputHandler::addline()
291  {
292    /* actually do send what was input */
293    /* a) get the string out of the inputbuffer */
[6788]294    std::string msgtosend = this->inpbuf->get();
[6776]295
[6846]296    if( msgtosend.length() == 0 )
297    { this->deactivate();
298      return;
299    }
300
[6776]301    /* b) clear the input buffer */
[6788]302    if (this->inpbuf->getSize() > 0)
303      this->inpbuf->clear();
[6776]304
305    /* c) send the chat via some call */
[8829]306    ChatManager::chat( msgtosend );
[6776]307
[6885]308    /* d) stop listening to input - only if this is not fullchat */
[6879]309    if( !this->fullchat )
310      this->deactivate();
[6846]311
[6776]312  }
313
314  void ChatInputHandler::backspace()
[6846]315  { this->inpbuf->removeBehindCursor(); }
[6776]316
317  void ChatInputHandler::deleteChar()
[6846]318  { this->inpbuf->removeAtCursor(); }
[6776]319
320  void ChatInputHandler::cursorRight()
[6846]321  { this->inpbuf->increaseCursor(); }
[7127]322
[6776]323  void ChatInputHandler::cursorLeft()
[6846]324  { this->inpbuf->decreaseCursor(); }
[7127]325
[6776]326  void ChatInputHandler::cursorEnd()
[6846]327  { this->inpbuf->setCursorToEnd(); }
[6776]328
329  void ChatInputHandler::cursorHome()
[6846]330  { this->inpbuf->setCursorToBegin(); }
[6776]331
332  void ChatInputHandler::exit()
[6879]333  {
334    /* b) clear the input buffer */
335    if (this->inpbuf->getSize() > 0)
336      this->inpbuf->clear();
[6776]337
[6879]338    /* d) stop listening to input  */
339    this->deactivate();
340  }
341
[6776]342}
Note: See TracBrowser for help on using the repository browser.