Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/core/input/Button.cc @ 2662

Last change on this file since 2662 was 2344, checked in by rgrieder, 16 years ago

Completed destruction of static elements like XMLPort, Identifier, etc.
Of initially about 250 memory leaks (not in the actual meaning but the memory was never freed anyway) only 1 remains in TinyCpp.

  • Core class is now a normal Singleton that gets created and destroyed in main.
  • The same goes for Language, LuaBind, SignalHandler and PlayerManager.
  • Added a new std::set to the CommandExecutor so that the external ConsoleCommands can get destroyed too.
  • Code for destroying CommandLineArguments
  • Added destruction code for ConstructionCallbacks in Identifier
  • Moved internal identifier map (the one with the typeid(.) names) in a static function in Identifier. This was necessary in order to destroy ALL Identifiers with the static destruction function. Before it was possible to create an Identifier with having a class instance (that would call RegisterObject) for instance by simply accessing it via getIdentifier.
  • Removed a big memory leak in Button (forgot to destroy the ConfigValueContainers)
  • Added destruction code for InputBufferListenerTuples in InputBuffer destructor.
  • Added destruction code for load and save executors in both XMLPortParam and XMLPortObject
  • Added destruction code for ConsoleCommands in GSRoot, GSGraphics and GSLevel (temporary solution anyway)
  • Deleting the CEGUILua script module seems to work properly now, one memory leak less (GUIManager.cc)
  • Added global destruction calls in Main.cc
  • Property svn:eol-style set to native
File size: 9.0 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 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30@file
31@brief
32    Implementation of the different input handlers.
33*/
34
35#include "Button.h"
36
37#include "util/Convert.h"
38#include "util/SubString.h"
39#include "util/String.h"
40#include "util/Debug.h"
41#include "core/ConsoleCommand.h"
42#include "core/CommandEvaluation.h"
43#include "core/CommandExecutor.h"
44#include "core/ConfigValueContainer.h"
45
46namespace orxonox
47{
48    /**
49    @note
50        bButtonThresholdUser_: We set it to true so that setConfigValues in KeyBinder sets the value
51        correctly the first time. It is then set to false first and changed later in Button::parse().
52    */
53    Button::Button()
54        : configContainer_(0)
55        , bButtonThresholdUser_(false)
56        , paramCommandBuffer_(0)
57    {
58        nCommands_[0]=0;
59        nCommands_[1]=0;
60        nCommands_[2]=0;
61        this->configContainer_ = 0;
62        clear();
63    }
64
65    void Button::clear()
66    {
67        for (unsigned int j = 0; j < 3; j++)
68        {
69            if (nCommands_[j])
70            {
71                // delete all commands and the command pointer array
72                for (unsigned int i = 0; i < nCommands_[j]; i++)
73                    delete commands_[j][i];
74                delete[] commands_[j];
75                commands_[j] = 0;
76                nCommands_[j] = 0;
77            }
78            else
79            {
80                commands_[j] = 0;
81            }
82        }
83
84        if (this->configContainer_)
85            delete this->configContainer_;
86        this->configContainer_ = 0;
87    }
88
89    void Button::readConfigValue(ConfigFileType configFile)
90    {
91        // create/get ConfigValueContainer
92        if (!configContainer_)
93        {
94            configContainer_ = new ConfigValueContainer(configFile, 0, groupName_, name_, "", name_);
95            configContainer_->callback(this, &Button::parse);
96        }
97        configContainer_->getValue(&bindingString_, this);
98    }
99
100    void Button::parse()
101    {
102        // delete all commands
103        clear();
104
105        if (isEmpty(bindingString_))
106            return;
107
108        // reset this to false first when parsing (was true before when parsing for the first time)
109        bButtonThresholdUser_ = false;
110
111        // use std::vector for a temporary dynamic array
112        std::vector<BaseCommand*> commands[3];
113
114        // separate the commands
115        SubString commandStrings(bindingString_, "|", SubString::WhiteSpaces, false,
116            '\\', false, '"', false, '(', ')', false, '\0');
117
118        for (unsigned int iCommand = 0; iCommand < commandStrings.size(); iCommand++)
119        {
120            if (commandStrings[iCommand] != "")
121            {
122                SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
123                    '\\', false, '"', false, '(', ')', false, '\0');
124
125                KeybindMode::Enum mode = KeybindMode::None;
126                float paramModifier = 1.0f;
127                std::string commandStr = "";
128
129                for (unsigned int iToken = 0; iToken < tokens.size(); ++iToken)
130                {
131                    std::string token = getLowercase(tokens[iToken]);
132
133                    if (token == "onpress")
134                        mode = KeybindMode::OnPress;
135                    else if (token == "onrelease")
136                        mode = KeybindMode::OnRelease;
137                    else if (token == "onhold")
138                        mode = KeybindMode::OnHold;
139                    else if (token == "buttonthreshold")
140                    {
141                        // for real axes, we can feed a ButtonThreshold argument
142                        ++iToken;
143                        if (iToken == tokens.size())
144                            continue;
145                        // may fail, but doesn't matter (default value already set)
146                        if (!convertValue(&buttonThreshold_, tokens[iToken + 1]))
147                            parseError("Could not parse 'ButtonThreshold' argument. \
148                                Switching to default value.", true);
149                        else
150                            this->bButtonThresholdUser_ = true;
151                    }
152                    else if (token == "scale")
153                    {
154                        ++iToken;
155                        if (iToken == tokens.size() || !convertValue(&paramModifier, tokens[iToken]))
156                            parseError("Could not parse 'scale' argument. Switching to default value.", true);
157                    }
158                    else
159                    {
160                        // no input related argument
161                        // we interpret everything from here as a command string
162                        while (iToken != tokens.size())
163                            commandStr += tokens[iToken++] + " ";
164                    }
165                }
166
167                if (commandStr == "")
168                {
169                    parseError("No command string given.", false);
170                    continue;
171                }
172
173                // evaluate the command
174                CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
175                if (!eval.isValid())
176                {
177                    parseError("Command evaluation failed.", true);
178                    continue;
179                }
180
181                // check for param command
182                int paramIndex = eval.getConsoleCommand()->getInputConfiguredParam_();
183                if (paramIndex >= 0)
184                {
185                    // parameter supported command
186                    ParamCommand* cmd = new ParamCommand();
187                    cmd->scale_ = paramModifier;
188
189                    // add command to the buffer if not yet existing
190                    for (unsigned int iParamCmd = 0; iParamCmd < paramCommandBuffer_->size(); iParamCmd++)
191                    {
192                        if ((*paramCommandBuffer_)[iParamCmd]->evaluation_.getConsoleCommand()
193                            == eval.getConsoleCommand())
194                        {
195                            // already in list
196                            cmd->paramCommand_ = (*paramCommandBuffer_)[iParamCmd];
197                            break;
198                        }
199                    }
200                    if (cmd->paramCommand_ == 0)
201                    {
202                        cmd->paramCommand_ = new BufferedParamCommand();
203                        paramCommandBuffer_->push_back(cmd->paramCommand_);
204                        cmd->paramCommand_->evaluation_ = eval;
205                        cmd->paramCommand_->paramIndex_ = paramIndex;
206                    }
207
208
209                    // we don't know whether this is an actual axis or just a button
210                    if (mode == KeybindMode::None)
211                    {
212                        if (!addParamCommand(cmd))
213                        {
214                            mode = eval.getConsoleCommand()->getKeybindMode();
215                            commands[mode].push_back(cmd);
216                        }
217                    }
218                }
219                else
220                {
221                    SimpleCommand* cmd = new SimpleCommand();
222                    cmd->evaluation_ = eval;
223
224                    if (mode == KeybindMode::None)
225                        mode = eval.getConsoleCommand()->getKeybindMode();
226
227                    commands[mode].push_back(cmd);
228                }
229            }
230        }
231
232        for (unsigned int j = 0; j < 3; j++)
233        {
234            nCommands_[j] = commands[j].size();
235            if (nCommands_[j])
236            {
237                commands_[j] = new BaseCommand*[nCommands_[j]];
238                for (unsigned int i = 0; i < commands[j].size(); i++)
239                    commands_[j][i] = commands[j][i];
240            }
241            else
242                commands_[j] = 0;
243        }
244    }
245
246    inline void Button::parseError(std::string message, bool serious)
247    {
248        if (serious)
249        {
250            COUT(2) << "Error while parsing binding for button/axis " << this->name_ << ". "
251                << message << std::endl;
252        }
253        else
254        {
255            COUT(3) << "Warning while parsing binding for button/axis " << this->name_ << ". "
256                << message << std::endl;
257        }
258    }
259}
Note: See TracBrowser for help on using the repository browser.