Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/Shell.cc @ 1591

Last change on this file since 1591 was 1591, checked in by landauf, 16 years ago

Again some heavy changes in ObjectList and Iterator:
there are now two types of iterators:

Iterator<ClassName> can iterate through any objectlist, either given by ObjectList<AnyClassName>::begin() or anyidentifier→getObjects()→begin(). Important note Iterator<ClassName> uses dynamic_cast.
And yes, it's possible to do this: Iterator<WorldEntity> it = ObjectList<SpaceShip>::begin()

ObjectList<ClassName>::iterator is the second iterator - it uses the ObjectList in a templated manner and therefore doesn't need dynamic_cast. But the only thing you can do is iterating through exactly the right ObjectList: ObjectList<ClassName>::iterator it = ObjectList<ClassName>::begin(). Anything else fails.

Those changes bring, at my system, something around +12% FPS compared with trunk and +25% FPS compared with the last revision of core3. Although I have to admit the FPS gain is only that high because iterating through objects is the main thing we're doing ingame right now. It would look totally different with physics, sound, AI, scripts, triggers and so on.

  • Property svn:eol-style set to native
File size: 11.9 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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "Shell.h"
30#include "CommandExecutor.h"
31#include "CoreIncludes.h"
32#include "ConfigValueIncludes.h"
33#include "Core.h"
34#include "ConsoleCommand.h"
35#include "input/InputInterfaces.h"
36#include "util/OutputHandler.h"
37
38#define SHELL_UPDATE_LISTENERS(function) \
39    for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ) \
40        (*(it++))->function()
41
42namespace orxonox
43{
44    SetConsoleCommand(Shell, clearShell, true);
45    SetConsoleCommand(Shell, history, true);
46
47    SetConsoleCommandShortcutGeneric(log,     createConsoleCommand(createFunctor(&OutputHandler::log),     "log"    ));
48    SetConsoleCommandShortcutGeneric(error,   createConsoleCommand(createFunctor(&OutputHandler::error),   "error"  ));
49    SetConsoleCommandShortcutGeneric(warning, createConsoleCommand(createFunctor(&OutputHandler::warning), "warning"));
50    SetConsoleCommandShortcutGeneric(info,    createConsoleCommand(createFunctor(&OutputHandler::info),    "info"   ));
51    SetConsoleCommandShortcutGeneric(debug,   createConsoleCommand(createFunctor(&OutputHandler::debug),   "debug"  ));
52
53    Shell::Shell()
54    {
55        RegisterRootObject(Shell);
56
57        this->scrollPosition_ = 0;
58        this->maxHistoryLength_ = 100;
59        this->historyPosition_ = 0;
60        this->historyOffset_ = 0;
61        this->finishedLastLine_ = true;
62        this->bAddOutputLevel_ = false;
63
64        this->clearLines();
65
66        this->inputBuffer_ = 0;
67        this->setInputBuffer(new InputBuffer());
68
69        this->outputBuffer_.registerListener(this);
70        OutputHandler::getOutStream().setOutputBuffer(this->outputBuffer_);
71
72        this->setConfigValues();
73    }
74
75    Shell& Shell::createShell()
76    {
77        int level = Core::getSoftDebugLevel(OutputHandler::LD_Shell);
78        Core::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
79        static Shell instance;
80        Core::setSoftDebugLevel(OutputHandler::LD_Shell, level);
81        return instance;
82    }
83
84    Shell& Shell::getInstance()
85    {
86        static Shell& instance = createShell();
87        return instance;
88    }
89
90    void Shell::setConfigValues()
91    {
92        SetConfigValue(maxHistoryLength_, 100);
93        SetConfigValue(historyOffset_, 0);
94        SetConfigValueVector(commandHistory_, std::vector<std::string>());
95
96        if (this->historyOffset_ >= this->maxHistoryLength_)
97            this->historyOffset_ = 0;
98
99        while (this->commandHistory_.size() > this->maxHistoryLength_)
100        {
101            unsigned int index = this->commandHistory_.size() - 1;
102            this->commandHistory_.erase(this->commandHistory_.begin() + index);
103            ModifyConfigValue(commandHistory_, remove, index);
104        }
105    }
106
107    void Shell::setInputBuffer(InputBuffer* buffer)
108    {
109        if (this->inputBuffer_)
110        {
111            this->inputBuffer_->unregisterListener(this);
112            // TODO: may be very dangerous. InputManager already deletes InputBuffer instance!!!
113            delete this->inputBuffer_;
114        }
115
116        this->inputBuffer_ = buffer;
117        this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
118        this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false);
119        this->inputBuffer_->registerListener(this, &Shell::hintandcomplete, '\t', true);
120        this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true);
121        this->inputBuffer_->registerListener(this, &Shell::deletechar, KeyCode::Delete);
122        this->inputBuffer_->registerListener(this, &Shell::exit, (char)27, true);
123        this->inputBuffer_->registerListener(this, &Shell::cursor_right, KeyCode::Right);
124        this->inputBuffer_->registerListener(this, &Shell::cursor_left, KeyCode::Left);
125        this->inputBuffer_->registerListener(this, &Shell::cursor_end, KeyCode::End);
126        this->inputBuffer_->registerListener(this, &Shell::cursor_home, KeyCode::Home);
127        this->inputBuffer_->registerListener(this, &Shell::history_up, KeyCode::Up);
128        this->inputBuffer_->registerListener(this, &Shell::history_down, KeyCode::Down);
129        this->inputBuffer_->registerListener(this, &Shell::scroll_up, KeyCode::PageUp);
130        this->inputBuffer_->registerListener(this, &Shell::scroll_down, KeyCode::PageDown);
131    }
132
133    void Shell::clearShell()
134    {
135        Shell::getInstance().clearLines();
136    }
137
138    void Shell::history()
139    {
140        Shell& instance = Shell::getInstance();
141
142        for (int i = instance.historyOffset_; i < (int)instance.commandHistory_.size(); ++i)
143            instance.addLine(instance.commandHistory_[i], -1);
144        for (int i =  0; i < (int)instance.historyOffset_; ++i)
145            instance.addLine(instance.commandHistory_[i], -1);
146    }
147
148    void Shell::registerListener(ShellListener* listener)
149    {
150        this->listeners_.insert(this->listeners_.end(), listener);
151    }
152
153    void Shell::unregisterListener(ShellListener* listener)
154    {
155        for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
156        {
157            if ((*it) == listener)
158                this->listeners_.erase(it++);
159            else
160                ++it;
161        }
162    }
163
164    void Shell::setCursorPosition(unsigned int cursor)
165    {
166        this->inputBuffer_->setCursorPosition(cursor);
167        SHELL_UPDATE_LISTENERS(cursorChanged);
168    }
169
170    void Shell::setInput(const std::string& input)
171    {
172        this->inputBuffer_->set(input);
173        this->inputChanged();
174    }
175
176    void Shell::addLine(const std::string& line, int level)
177    {
178        int original_level = OutputHandler::getOutStream().getOutputLevel();
179        OutputHandler::getOutStream().setOutputLevel(level);
180
181        if (!this->finishedLastLine_)
182            this->outputBuffer_ << std::endl;
183
184        this->outputBuffer_ << line << std::endl;
185        OutputHandler::getOutStream().setOutputLevel(original_level);
186    }
187
188    void Shell::clearLines()
189    {
190        this->lines_.clear();
191        this->scrollIterator_ = this->lines_.begin();
192
193        this->scrollPosition_ = 0;
194        this->finishedLastLine_ = true;
195
196        SHELL_UPDATE_LISTENERS(linesChanged);
197    }
198
199    std::list<std::string>::const_iterator Shell::getNewestLineIterator() const
200    {
201        if (this->scrollPosition_)
202            return this->scrollIterator_;
203        else
204            return this->lines_.begin();
205    }
206
207    std::list<std::string>::const_iterator Shell::getEndIterator() const
208    {
209        return this->lines_.end();
210    }
211
212    void Shell::addToHistory(const std::string& command)
213    {
214        ModifyConfigValue(commandHistory_, set, this->historyOffset_, command);
215        this->historyPosition_ = 0;
216        ModifyConfigValue(historyOffset_, set, (this->historyOffset_ + 1) % this->maxHistoryLength_);
217    }
218
219    std::string Shell::getFromHistory() const
220    {
221        unsigned int index = mod(((int)this->historyOffset_) - ((int)this->historyPosition_), this->maxHistoryLength_);
222        if (index < this->commandHistory_.size() && this->historyPosition_ != 0)
223            return this->commandHistory_[index];
224        else
225            return "";
226    }
227
228    void Shell::outputChanged()
229    {
230        std::string output;
231        bool newline;
232        do
233        {
234            newline = this->outputBuffer_.getLine(&output);
235
236            if (!newline && output == "")
237                break;
238
239            if (this->finishedLastLine_)
240            {
241                if (this->bAddOutputLevel_)
242                    output.insert(0, 1, (char)OutputHandler::getOutStream().getOutputLevel());
243
244                this->lines_.insert(this->lines_.begin(), output);
245
246                if (this->scrollPosition_)
247                    this->scrollPosition_++;
248                else
249                    this->scrollIterator_ = this->lines_.begin();
250
251                this->finishedLastLine_ = newline;
252
253                if (!this->scrollPosition_)
254                {
255                    SHELL_UPDATE_LISTENERS(lineAdded);
256                }
257            }
258            else
259            {
260                (*this->lines_.begin()) += output;
261                this->finishedLastLine_ = newline;
262                SHELL_UPDATE_LISTENERS(onlyLastLineChanged);
263            }
264
265        } while (newline);
266    }
267
268    void Shell::inputChanged()
269    {
270        SHELL_UPDATE_LISTENERS(inputChanged);
271        SHELL_UPDATE_LISTENERS(cursorChanged);
272    }
273
274    void Shell::execute()
275    {
276        this->addToHistory(this->inputBuffer_->get());
277        this->addLine(this->inputBuffer_->get(), 0);
278
279        if (!CommandExecutor::execute(this->inputBuffer_->get()))
280            this->addLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1);
281
282        this->clear();
283    }
284
285    void Shell::hintandcomplete()
286    {
287        this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
288        this->addLine(CommandExecutor::hint(this->inputBuffer_->get()), -1);
289
290        this->inputChanged();
291    }
292
293    void Shell::backspace()
294    {
295        this->inputBuffer_->removeBehindCursor();
296        SHELL_UPDATE_LISTENERS(inputChanged);
297        SHELL_UPDATE_LISTENERS(cursorChanged);
298    }
299
300    void Shell::deletechar()
301    {
302        this->inputBuffer_->removeAtCursor();
303        SHELL_UPDATE_LISTENERS(inputChanged);
304    }
305
306    void Shell::clear()
307    {
308        this->inputBuffer_->clear();
309        this->historyPosition_ = 0;
310        SHELL_UPDATE_LISTENERS(inputChanged);
311        SHELL_UPDATE_LISTENERS(cursorChanged);
312    }
313
314    void Shell::cursor_right()
315    {
316        this->inputBuffer_->increaseCursor();
317        SHELL_UPDATE_LISTENERS(cursorChanged);
318    }
319
320    void Shell::cursor_left()
321    {
322        this->inputBuffer_->decreaseCursor();
323        SHELL_UPDATE_LISTENERS(cursorChanged);
324    }
325
326    void Shell::cursor_end()
327    {
328        this->inputBuffer_->setCursorToEnd();
329        SHELL_UPDATE_LISTENERS(cursorChanged);
330    }
331
332    void Shell::cursor_home()
333    {
334        this->inputBuffer_->setCursorToBegin();
335        SHELL_UPDATE_LISTENERS(cursorChanged);
336    }
337
338    void Shell::history_up()
339    {
340        if (this->historyPosition_ < this->commandHistory_.size())
341        {
342            this->historyPosition_++;
343            this->inputBuffer_->set(this->getFromHistory());
344        }
345    }
346
347    void Shell::history_down()
348    {
349        if (this->historyPosition_ > 0)
350        {
351            this->historyPosition_--;
352            this->inputBuffer_->set(this->getFromHistory());
353        }
354    }
355
356    void Shell::scroll_up()
357    {
358        if (this->scrollIterator_ != this->lines_.end())
359        {
360            ++this->scrollIterator_;
361            ++this->scrollPosition_;
362
363            SHELL_UPDATE_LISTENERS(linesChanged);
364        }
365    }
366
367    void Shell::scroll_down()
368    {
369        if (this->scrollIterator_ != this->lines_.begin())
370        {
371            --this->scrollIterator_;
372            --this->scrollPosition_;
373
374            SHELL_UPDATE_LISTENERS(linesChanged);
375        }
376    }
377
378    void Shell::exit()
379    {
380        if (this->inputBuffer_->getSize() > 0)
381        {
382            this->clear();
383            return;
384        }
385
386        this->clear();
387        this->scrollPosition_ = 0;
388        this->scrollIterator_ = this->lines_.begin();
389
390        SHELL_UPDATE_LISTENERS(exit);
391    }
392}
Note: See TracBrowser for help on using the repository browser.