Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Finally! The InputManager is now working like I imagined it to. And it's even easier to use it as well.
A little explanation: Every time you change something about the input distribution, it is a change of 'state' represented by the class 'InputState'.
That can be for instance: "console", "game", "gui", etc. Every state has a name and a priority which describes who comes first. Now if one state doesn't handle mouse input or instance, then the one with the next lower priority gets it. To prevent that, you can add the 'EmptyHandler' to the state with setMouseHandler.
InputState is just an abstract base class. There are two classes implementing it: SimpleInputState and ExtendedInputState. The latter allows for multiple input handlers for one single device.

Basically, what you need to know is what you see in Orxonox.cc, InGameConsole.cc and Shell.cc.

  • Property svn:eol-style set to native
File size: 8.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 *      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#include "util/Convert.h"
37#include "util/SubString.h"
38#include "util/String.h"
39#include "core/Debug.h"
40#include "core/ConsoleCommand.h"
41#include "core/CommandEvaluation.h"
42#include "core/CommandExecutor.h"
43#include "InputCommands.h"
44
45namespace orxonox
46{
47    void Button::clear()
48    {
49        for (unsigned int j = 0; j < 3; j++)
50        {
51            if (nCommands_[j])
52            {
53                // delete all commands and the command pointer array
54                for (unsigned int i = 0; i < nCommands_[j]; i++)
55                    delete commands_[j][i];
56                delete[] commands_[j];
57                commands_[j] = 0;
58                nCommands_[j] = 0;
59            }
60            else
61            {
62                commands_[j] = 0;
63            }
64        }
65    }
66
67    void Button::parse(std::vector<BufferedParamCommand*>& paramCommandBuffer)
68    {
69        if (isEmpty(bindingString_))
70        {
71            clear();
72            return;
73        }
74
75        // use std::vector for a temporary dynamic array
76        std::vector<BaseCommand*> commands[3];
77
78
79        // separate the commands
80        SubString commandStrings(bindingString_, "|", SubString::WhiteSpaces, false,
81            '\\', false, '"', false, '(', ')', false, '\0');
82
83        for (unsigned int iCommand = 0; iCommand < commandStrings.size(); iCommand++)
84        {
85            if (commandStrings[iCommand] != "")
86            {
87                SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
88                    '\\', false, '"', false, '(', ')', false, '\0');
89
90                KeybindMode::Enum mode = KeybindMode::None;
91                float paramModifier = 1.0f;
92                std::string commandStr = "";
93
94                for (unsigned int iToken = 0; iToken < tokens.size(); ++iToken)
95                {
96                    std::string token = getLowercase(tokens[iToken]);
97
98                    if (token == "onpress")
99                        mode = KeybindMode::OnPress;
100                    else if (token == "onrelease")
101                        mode = KeybindMode::OnRelease;
102                    else if (token == "onhold")
103                        mode = KeybindMode::OnHold;
104                    else if (token == "buttonthreshold")
105                    {
106                        // for real axes, we can feed a ButtonThreshold argument
107                        ++iToken;
108                        if (iToken == tokens.size())
109                            continue;
110                        // may fail, but doesn't matter (default value already set)
111                        if (!convertValue(&buttonThreshold_, tokens[iToken + 1]))
112                            parseError("Could not parse 'ButtonThreshold' argument. \
113                                Switching to default value.", true);
114                    }
115                    else if (token == "scale")
116                    {
117                        ++iToken;
118                        if (iToken == tokens.size() || !convertValue(&paramModifier, tokens[iToken]))
119                            parseError("Could not parse 'scale' argument. Switching to default value.", true);
120                    }
121                    else
122                    {
123                        // no input related argument
124                        // we interpret everything from here as a command string
125                        while (iToken != tokens.size())
126                            commandStr += tokens[iToken++] + " ";
127                    }
128                }
129
130                if (commandStr == "")
131                {
132                    parseError("No command string given.", false);
133                    continue;
134                }
135
136                // evaluate the command
137                CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
138                if (!eval.isValid())
139                {
140                    parseError("Command evaluation failed.", true);
141                    continue;
142                }
143
144                // check for param command
145                int paramIndex = eval.getConsoleCommand()->getAxisParamIndex();
146                if (paramIndex >= 0)
147                {
148                    // parameter supported command
149                    ParamCommand* cmd = new ParamCommand();
150                    cmd->paramModifier_ = paramModifier;
151                    cmd->bRelative_ = eval.getConsoleCommand()->getIsAxisRelative();
152
153                    // add command to the buffer if not yet existing
154                    for (unsigned int iParamCmd = 0; iParamCmd < paramCommandBuffer.size(); iParamCmd++)
155                    {
156                        if (getLowercase(paramCommandBuffer[iParamCmd]->evaluation_.getOriginalCommand())
157                            == getLowercase(commandStr))
158                        {
159                            // already in list
160                            cmd->paramCommand_ = paramCommandBuffer[iParamCmd];
161                            break;
162                        }
163                    }
164                    if (cmd->paramCommand_ == 0)
165                    {
166                        cmd->paramCommand_ = new BufferedParamCommand();
167                        paramCommandBuffer.push_back(cmd->paramCommand_);
168                        cmd->paramCommand_->evaluation_ = eval;
169                        cmd->paramCommand_->paramIndex_ = paramIndex;
170                    }
171
172
173                    // we don't know whether this is an actual axis or just a button
174                    if (mode == KeybindMode::None)
175                    {
176                        if (!addParamCommand(cmd))
177                        {
178                            mode = eval.getConsoleCommand()->getKeybindMode();
179                            commands[mode].push_back(cmd);
180                        }
181                    }
182                }
183                else
184                {
185                    SimpleCommand* cmd = new SimpleCommand();
186                    cmd->evaluation_ = eval;
187
188                    if (mode == KeybindMode::None)
189                        mode = eval.getConsoleCommand()->getKeybindMode();
190
191                    commands[mode].push_back(cmd);
192                }
193            }
194        }
195
196        for (unsigned int j = 0; j < 3; j++)
197        {
198            nCommands_[j] = commands[j].size();
199            if (nCommands_[j])
200            {
201                commands_[j] = new BaseCommand*[nCommands_[j]];
202                for (unsigned int i = 0; i < commands[j].size(); i++)
203                    commands_[j][i] = commands[j][i];
204            }
205            else
206                commands_[j] = 0;
207        }
208    }
209
210    bool Button::execute(KeybindMode::Enum mode, float abs, float rel)
211    {
212        // execute all the parsed commands in the string
213        for (unsigned int iCommand = 0; iCommand < nCommands_[mode]; iCommand++)
214            commands_[mode][iCommand]->execute(abs, rel);
215        return true;
216    }
217
218    inline void Button::parseError(std::string message, bool serious)
219    {
220        if (serious)
221        {
222            COUT(2) << "Error while parsing binding for button/axis" << this->name_ << ". "
223                << message << std::endl;
224        }
225        else
226        {
227            COUT(3) << "Warning while parsing binding for button/axis" << this->name_ << ". "
228                << message << std::endl;
229        }
230    }
231}
Note: See TracBrowser for help on using the repository browser.