Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/orxonox/chat/ChatInputHandler.cc @ 10407

Last change on this file since 10407 was 10407, checked in by landauf, 9 years ago

moved Scope and ScopedSingletonManager from util to core.
TODO I had to disable two tests in ScopeTest.cc because now that it runs in the core library, there are too many singletons which get loaded in graphics scope (with too many dependencies). this should be fixed

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