Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9531 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
Line 
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"
30
31#include <cassert>
32#include <string>
33#include <CEGUIWindow.h>
34#include <CEGUIWindowManager.h>
35#include <elements/CEGUIListbox.h>
36#include <elements/CEGUIListboxItem.h>
37#include <elements/CEGUIListboxTextItem.h>
38
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
47#include "chat/ChatManager.h"
48#include "PlayerManager.h"
49#include "infos/PlayerInfo.h"
50
51namespace orxonox
52{
53  /* singleton */
54  ManageScopedSingleton( ChatInputHandler, ScopeID::Graphics, false );
55
56  /* add commands to console */
57  SetConsoleCommand( "startchat", &ChatInputHandler::activate_static );
58  SetConsoleCommand( "startchat_small", &ChatInputHandler::activate_small_static );
59
60  /* constructor */
61  ChatInputHandler::ChatInputHandler()
62  {
63    /* register the object  */
64    RegisterObject(ChatInputHandler);
65
66    /* create necessary objects */
67    this->inpbuf = new InputBuffer();
68    this->disp_offset = 0;
69    assert( this->inpbuf != NULL );
70
71    /* generate chatbox ui and chatbox-inputonly ui */
72    GUIManager::getInstance().loadGUI( "ChatBox" );
73    GUIManager::getInstance().loadGUI( "ChatBox-inputonly" );
74
75    /* setup colors */
76    setupColors();
77
78    /* configure the input buffer */
79    configureInputBuffer();
80
81    this->inputState = InputManager::getInstance().createInputState( "chatinput", false, false, InputStatePriority::Dynamic );
82    this->inputState->setKeyHandler(this->inpbuf);
83  }
84
85  ChatInputHandler::~ChatInputHandler()
86  {
87    /* Clean up */
88    InputManager::getInstance().destroyState("chatinput");
89    delete this->inpbuf;
90  }
91
92  /* configure input buffer, sub for the constructor */
93  void ChatInputHandler::configureInputBuffer()
94  {
95    /* INSTALL CALLBACKS */
96    /* input has changed */
97    this->inpbuf->registerListener(this, &ChatInputHandler::inputChanged, true);
98
99    /* add a line */
100    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\r',   false);
101    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\n',   false);
102
103    /* backspace */
104    this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\b',   true);
105    //this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\177', true);
106
107    /* exit the chatinputhandler thingy (tbd) */
108    this->inpbuf->registerListener(this, &ChatInputHandler::exit,            '\033', true); // escape
109
110    /* delete character */
111    this->inpbuf->registerListener(this, &ChatInputHandler::deleteChar,      KeyCode::Delete);
112
113    /* cursor movement */
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);
118
119    /* GET WINDOW POINTERS */
120    input = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox/input" );
121    inputonly = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox-inputonly/input" );
122
123    /* get pointer to the history window */
124    CEGUI::Window *history = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox/history" );
125
126    /* cast it to a listbox */
127    lb_history = dynamic_cast<CEGUI::Listbox*>(history);
128
129    /* assert wee */
130    assert( lb_history );
131  }
132
133  /* setup the colors, sub for the constructor */
134  void ChatInputHandler::setupColors()
135  {
136    /* auto variables */
137    float red = 1.0, green = 0.5, blue = 0.5;
138    int i = 0;
139
140    // three loops: red tones, blue tones and green tones
141    // reds
142    for( i = 0; i < NumberOfColors/3; ++i )
143    { this->text_colors[ i ] = CEGUI::colour( red, green, blue );
144      green += 0.2f, blue += 0.2f;
145    }
146
147    // greens
148    red = 0.5, green = 1, blue = 0.5;
149    for( ; i < NumberOfColors*2/3; ++i )
150    { this->text_colors[ i ] = CEGUI::colour( red, green, blue );
151      red += 0.2f, blue += 0.2f;
152    }
153
154    // blues
155    red = 0.5, green = 0.5, blue = 1;
156    for( ; i < NumberOfColors; ++i )
157    { this->text_colors[ i ] = CEGUI::colour( red, green, blue );
158      red += 0.2f, green += 0.2f;
159    }
160  }
161
162
163  /* activate, deactivate */
164  void ChatInputHandler::activate_static()
165  { ChatInputHandler::getInstance().activate( true ); }
166
167  void ChatInputHandler::activate_small_static()
168  { ChatInputHandler::getInstance().activate( false ); }
169
170  void ChatInputHandler::activate( bool full )
171  {
172    /* start listening */
173    InputManager::getInstance().enterState("chatinput");
174
175    /* MARK add spawning of chat widget stuff here.*/
176    if( full )
177      GUIManager::getInstance().showGUI( "ChatBox" );
178    else
179      GUIManager::getInstance().showGUI( "ChatBox-inputonly" );
180
181    this->fullchat = full;
182  }
183
184  void ChatInputHandler::deactivate()
185  {
186    /* stop listening */
187    InputManager::getInstance().leaveState("chatinput");
188
189    /* un-spawning of chat widget stuff */
190    GUIManager::getInstance().hideGUI( "ChatBox" );
191    GUIManager::getInstance().hideGUI( "ChatBox-inputonly" );
192  }
193
194
195  /* subs for incomingChat */
196  void ChatInputHandler::sub_setcolor( CEGUI::ListboxTextItem *tocolor,
197    std::string name )
198  {
199    /* sanity checks */
200    if( !tocolor )
201      orxout(internal_warning) << "Empty ListBoxTextItem given to "
202        "ChatInputhandler::sub_setcolor()." << endl;
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 */
211    tocolor->setTextColours( this->text_colors[ hash ] );
212  }
213
214  /* handle incoming chat */
215  void ChatInputHandler::incomingChat(const std::string& message, const std::string& name)
216  {
217    /* create item */
218    CEGUI::ListboxTextItem *toadd = new CEGUI::ListboxTextItem( message );
219
220    /* setup colors */
221    if (name != "")
222      sub_setcolor( toadd, name );
223
224    /* now add */
225    this->lb_history->addItem( dynamic_cast<CEGUI::ListboxItem*>(toadd) );
226    this->lb_history->ensureItemIsVisible(
227      dynamic_cast<CEGUI::ListboxItem*>(toadd) );
228
229    /* make sure the history handles it */
230    this->lb_history->handleUpdatedItemData();
231  }
232
233
234  /* sub for inputchanged */
235  void ChatInputHandler::sub_adjust_dispoffset( int maxlen,
236    int cursorpos,
237    int inplen )
238  {
239    /* already start offsetting 5 characters before end */
240    if( cursorpos+5 > maxlen )
241    {
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    }
248
249    /* make sure we don't die at substr */
250    if( inplen <= disp_offset ) disp_offset = 0;
251  }
252
253  /* callbacks for InputBuffer */
254  void ChatInputHandler::inputChanged()
255  {
256    /* update the cursor and the window */
257    std::string raw = this->inpbuf->get();
258    int cursorpos = this->inpbuf->getCursorPosition();
259
260    /* get string before cursor */
261    std::string left = raw.substr( 0, cursorpos );
262
263    /* see if there's a string after the cursor */
264    std::string right = "";
265    if( raw.length() >= left.length()+1 )
266      right = raw.substr( cursorpos );
267
268    /* set the text */
269    std::string assembled = "$ " + left + "|" + right;
270
271    if( this->fullchat )
272    {
273      /* adjust curser position - magic number 5 for font width */
274      sub_adjust_dispoffset( (int)(this->input->getUnclippedInnerRect().getWidth()/6),
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 */
281      sub_adjust_dispoffset( (int)(this->inputonly->getUnclippedInnerRect().getWidth()/6),
282        cursorpos, assembled.length() );
283      this->inputonly->setProperty( "Text", assembled.substr( disp_offset) );
284    }
285
286    /* reset display offset */
287    disp_offset = 0;
288  }
289
290  void ChatInputHandler::addline()
291  {
292    /* actually do send what was input */
293    /* a) get the string out of the inputbuffer */
294    std::string msgtosend = this->inpbuf->get();
295
296    if( msgtosend.length() == 0 )
297    { this->deactivate();
298      return;
299    }
300
301    /* b) clear the input buffer */
302    if (this->inpbuf->getSize() > 0)
303      this->inpbuf->clear();
304
305    /* c) send the chat via some call */
306    ChatManager::chat( msgtosend );
307
308    /* d) stop listening to input - only if this is not fullchat */
309    if( !this->fullchat )
310      this->deactivate();
311
312  }
313
314  void ChatInputHandler::backspace()
315  { this->inpbuf->removeBehindCursor(); }
316
317  void ChatInputHandler::deleteChar()
318  { this->inpbuf->removeAtCursor(); }
319
320  void ChatInputHandler::cursorRight()
321  { this->inpbuf->increaseCursor(); }
322
323  void ChatInputHandler::cursorLeft()
324  { this->inpbuf->decreaseCursor(); }
325
326  void ChatInputHandler::cursorEnd()
327  { this->inpbuf->setCursorToEnd(); }
328
329  void ChatInputHandler::cursorHome()
330  { this->inpbuf->setCursorToBegin(); }
331
332  void ChatInputHandler::exit()
333  {
334    /* b) clear the input buffer */
335    if (this->inpbuf->getSize() > 0)
336      this->inpbuf->clear();
337
338    /* d) stop listening to input  */
339    this->deactivate();
340  }
341
342}
Note: See TracBrowser for help on using the repository browser.