| [2066] | 1 | /* | 
|---|
|  | 2 | orxonox - the future of 3D-vertical-scrollers | 
|---|
|  | 3 |  | 
|---|
|  | 4 | Copyright (C) 2004 orx | 
|---|
|  | 5 |  | 
|---|
|  | 6 | This program is free software; you can redistribute it and/or modify | 
|---|
|  | 7 | it under the terms of the GNU General Public License as published by | 
|---|
|  | 8 | the Free Software Foundation; either version 2, or (at your option) | 
|---|
|  | 9 | any later version. | 
|---|
|  | 10 |  | 
|---|
|  | 11 | ### File Specific: | 
|---|
|  | 12 | main-programmer: Christian Meyer | 
|---|
| [2816] | 13 | co-programmer: Patrick Boenzli | 
|---|
| [2066] | 14 | */ | 
|---|
|  | 15 |  | 
|---|
|  | 16 |  | 
|---|
|  | 17 | #include "command_node.h" | 
|---|
|  | 18 | #include "keynames.h" | 
|---|
|  | 19 | #include "ini_parser.h" | 
|---|
| [2100] | 20 | #include "world_entity.h" | 
|---|
| [2636] | 21 | #include "game_loader.h" | 
|---|
| [3216] | 22 | #include "world.h" | 
|---|
| [2066] | 23 |  | 
|---|
|  | 24 | #include <stdio.h> | 
|---|
| [2166] | 25 | #include <string.h> | 
|---|
| [2105] | 26 | #include <stdlib.h> | 
|---|
| [2066] | 27 |  | 
|---|
|  | 28 | using namespace std; | 
|---|
|  | 29 |  | 
|---|
| [2141] | 30 | /** | 
|---|
| [2636] | 31 | \brief constructs a CommandNode to handle remote input | 
|---|
|  | 32 | \param ID: unique denumerator to identify the node in the network | 
|---|
| [2141] | 33 | */ | 
|---|
| [2066] | 34 | CommandNode::CommandNode (int ID) | 
|---|
|  | 35 | { | 
|---|
| [3214] | 36 | this->bound = new tList<WorldEntity>(); | 
|---|
| [3213] | 37 | this->aliases = NULL; | 
|---|
|  | 38 | this->netID = ID; | 
|---|
|  | 39 | this->bLocalInput = false; | 
|---|
|  | 40 | this->bEnabled = true; | 
|---|
| [3216] | 41 | this->world = NULL; | 
|---|
| [2066] | 42 | } | 
|---|
|  | 43 |  | 
|---|
| [2141] | 44 | /** | 
|---|
| [2636] | 45 | \brief constructs a CommandNode to handle local input | 
|---|
|  | 46 | \param filename: The path and name of the file to load the key bindings from | 
|---|
| [2141] | 47 | */ | 
|---|
| [2066] | 48 | CommandNode::CommandNode (char* filename = DEFAULT_KEYBIND_FILE) | 
|---|
|  | 49 | { | 
|---|
| [3213] | 50 | this->aliases = NULL; | 
|---|
|  | 51 | this->bLocalInput = true; | 
|---|
|  | 52 | this->netID = 0; | 
|---|
| [3214] | 53 | this->bound = new tList<WorldEntity>(); | 
|---|
| [3213] | 54 | this->bEnabled = true; | 
|---|
| [3216] | 55 | this->world = NULL; | 
|---|
| [3236] | 56 | this->loadBindings (filename); | 
|---|
| [2066] | 57 | } | 
|---|
|  | 58 |  | 
|---|
| [2141] | 59 | /** | 
|---|
| [2636] | 60 | \brief removes the CommandNode from memory | 
|---|
| [2141] | 61 | */ | 
|---|
| [2066] | 62 | CommandNode::~CommandNode () | 
|---|
|  | 63 | { | 
|---|
| [2636] | 64 | if( aliases != NULL) free (aliases); | 
|---|
| [3213] | 65 | if( bound != NULL) delete bound; /* \todo should this delete bound? dangerous FIX */ | 
|---|
| [2066] | 66 | } | 
|---|
|  | 67 |  | 
|---|
| [2816] | 68 |  | 
|---|
| [3194] | 69 | /** | 
|---|
|  | 70 | \brief this resets the command node | 
|---|
|  | 71 |  | 
|---|
|  | 72 | deleting all data contained in the command node to fill it up again | 
|---|
|  | 73 |  | 
|---|
|  | 74 | \todo coppling to different game-entities | 
|---|
|  | 75 | \todo reset/destroy has to be redesigned | 
|---|
|  | 76 | */ | 
|---|
|  | 77 |  | 
|---|
| [2816] | 78 | void CommandNode::reset() | 
|---|
|  | 79 | { | 
|---|
| [3194] | 80 | this->bound->destroy(); | 
|---|
| [3213] | 81 | //this->bound = NULL; /* \todo this produces a NULLpointer error.. FIX */ | 
|---|
|  | 82 | this->bEnabled = false; | 
|---|
| [3216] | 83 | this->world = NULL; | 
|---|
| [2816] | 84 | } | 
|---|
|  | 85 |  | 
|---|
| [3213] | 86 | void CommandNode::enable(bool bEnabled) | 
|---|
|  | 87 | { | 
|---|
|  | 88 | this->bEnabled = bEnabled; | 
|---|
|  | 89 | } | 
|---|
|  | 90 |  | 
|---|
| [3216] | 91 |  | 
|---|
| [2141] | 92 | /** | 
|---|
| [3216] | 93 | \brief adds Node to a GameWorld | 
|---|
|  | 94 |  | 
|---|
|  | 95 | this is usefull, if you want to catch events in a world class. usualy | 
|---|
|  | 96 | this is done automaticaly via GameLoader. Reset it via | 
|---|
|  | 97 | CommandNode::reset() | 
|---|
|  | 98 |  | 
|---|
|  | 99 | */ | 
|---|
|  | 100 | void CommandNode::addToWorld(World* world) | 
|---|
|  | 101 | { | 
|---|
|  | 102 | this->world = world; | 
|---|
|  | 103 | } | 
|---|
|  | 104 |  | 
|---|
|  | 105 |  | 
|---|
|  | 106 | /** | 
|---|
| [2636] | 107 | \brief loads new key bindings from a file | 
|---|
|  | 108 | \param filename: The path and name of the file to load the bindings from | 
|---|
| [2141] | 109 | */ | 
|---|
| [3225] | 110 | void CommandNode::loadBindings (char* filename) | 
|---|
| [2066] | 111 | { | 
|---|
| [2636] | 112 | FILE* stream; | 
|---|
|  | 113 |  | 
|---|
|  | 114 | printf("Loading key bindings from %s\n", filename); | 
|---|
|  | 115 |  | 
|---|
|  | 116 | if( filename == NULL) filename = DEFAULT_KEYBIND_FILE; | 
|---|
|  | 117 |  | 
|---|
|  | 118 | // remove old bindings if present | 
|---|
|  | 119 | if( aliases != NULL) | 
|---|
|  | 120 | { | 
|---|
|  | 121 | free (aliases); | 
|---|
|  | 122 | aliases = NULL; | 
|---|
|  | 123 | } | 
|---|
|  | 124 |  | 
|---|
|  | 125 | // create parser | 
|---|
|  | 126 | IniParser parser (filename); | 
|---|
| [3225] | 127 | if( parser.getSection ("Bindings") == -1) | 
|---|
| [2636] | 128 | { | 
|---|
|  | 129 | printf("Could not find key bindings in %s\n", filename); | 
|---|
|  | 130 | return; | 
|---|
|  | 131 | } | 
|---|
|  | 132 | // allocate empty lookup table | 
|---|
|  | 133 | aliases = (KeyBindings*) calloc (1, sizeof (KeyBindings)); | 
|---|
|  | 134 |  | 
|---|
|  | 135 | char namebuf[256]; | 
|---|
|  | 136 | char valuebuf[256]; | 
|---|
|  | 137 | memset (namebuf, 0, 256); | 
|---|
|  | 138 | memset (valuebuf, 0, 256); | 
|---|
|  | 139 | int* index; | 
|---|
|  | 140 |  | 
|---|
| [3236] | 141 | while( parser.nextVar (namebuf, valuebuf) != -1) | 
|---|
| [2636] | 142 | { | 
|---|
| [3236] | 143 | index = nameToIndex (namebuf); | 
|---|
| [2636] | 144 | switch( index[0]) | 
|---|
| [2066] | 145 | { | 
|---|
| [2636] | 146 | case 0: | 
|---|
| [3225] | 147 | printf("Key binding %d(%s) set to %s\n", index[1], SDLKToKeyname( index[1]), valuebuf); | 
|---|
| [2636] | 148 | strcpy (aliases->keys[index[1]], valuebuf); | 
|---|
|  | 149 | break; | 
|---|
|  | 150 | case 1: | 
|---|
| [3225] | 151 | printf("Button binding %d(%s) set to %s\n", index[1], SDLBToButtonname( index[1]), valuebuf); | 
|---|
| [2636] | 152 | strcpy (aliases->buttons[index[1]], valuebuf); | 
|---|
|  | 153 | break; | 
|---|
|  | 154 | default: | 
|---|
|  | 155 | break; | 
|---|
| [2066] | 156 | } | 
|---|
| [2636] | 157 | memset (namebuf, 0, 256); | 
|---|
|  | 158 | memset (valuebuf, 0, 256); | 
|---|
|  | 159 | } | 
|---|
| [2066] | 160 | } | 
|---|
|  | 161 |  | 
|---|
| [2141] | 162 | /** | 
|---|
| [2636] | 163 | \brief binds a WorldEntity to the CommandNode | 
|---|
|  | 164 | \param entity: Pointer to the entity to bind | 
|---|
| [2141] | 165 | */ | 
|---|
| [2066] | 166 | void CommandNode::bind (WorldEntity* entity) | 
|---|
|  | 167 | { | 
|---|
| [3225] | 168 | bound->add (entity); | 
|---|
| [2066] | 169 | } | 
|---|
|  | 170 |  | 
|---|
| [2141] | 171 | /** | 
|---|
| [2636] | 172 | \brief removes an entity from the list of the CommandNode | 
|---|
|  | 173 | \param entity: Pointer to the entity to relese | 
|---|
| [2141] | 174 | */ | 
|---|
| [2066] | 175 | void CommandNode::unbind (WorldEntity* entity) | 
|---|
|  | 176 | { | 
|---|
| [3225] | 177 | bound->remove (entity); | 
|---|
| [2066] | 178 | } | 
|---|
|  | 179 |  | 
|---|
| [3225] | 180 | int* CommandNode::nameToIndex (char* name) | 
|---|
| [2066] | 181 | { | 
|---|
| [2636] | 182 | coord[0] = -1; | 
|---|
|  | 183 | coord[1] = -1; | 
|---|
|  | 184 | int c; | 
|---|
| [3225] | 185 | if( (c = keynameToSDLK (name)) != -1) | 
|---|
| [2636] | 186 | { | 
|---|
|  | 187 | coord[1] = c; | 
|---|
|  | 188 | coord[0] = 0; | 
|---|
|  | 189 | } | 
|---|
| [3225] | 190 | if( (c = buttonnameToSDLB (name)) != -1) | 
|---|
| [2636] | 191 | { | 
|---|
|  | 192 | coord[1] = c; | 
|---|
|  | 193 | coord[0] = 1; | 
|---|
|  | 194 | } | 
|---|
|  | 195 | return coord; | 
|---|
| [2066] | 196 | } | 
|---|
|  | 197 |  | 
|---|
| [2141] | 198 | /** | 
|---|
| [2636] | 199 | \brief tells the CommandNode to run through all pending events and relay them accordingly | 
|---|
| [2141] | 200 | */ | 
|---|
| [2066] | 201 | void CommandNode::process () | 
|---|
|  | 202 | { | 
|---|
| [3213] | 203 | if( this->bEnabled) | 
|---|
|  | 204 | { | 
|---|
| [3225] | 205 | if( bLocalInput) processLocal (); | 
|---|
|  | 206 | else processNetwork (); | 
|---|
| [3213] | 207 | } | 
|---|
| [2066] | 208 | } | 
|---|
|  | 209 |  | 
|---|
| [3236] | 210 | void CommandNode::processLocal () | 
|---|
| [2066] | 211 | { | 
|---|
| [2636] | 212 | SDL_Event event; | 
|---|
|  | 213 | Command cmd; | 
|---|
|  | 214 | while( SDL_PollEvent (&event)) | 
|---|
|  | 215 | { | 
|---|
|  | 216 | memset (cmd.cmd, 0, CMD_LENGHT); | 
|---|
|  | 217 | switch( event.type) | 
|---|
| [2066] | 218 | { | 
|---|
| [2636] | 219 | case SDL_KEYDOWN: | 
|---|
|  | 220 | strcpy (cmd.cmd, aliases->keys[event.key.keysym.sym]); | 
|---|
|  | 221 | cmd.bUp = false; | 
|---|
| [3225] | 222 | if( strlen (cmd.cmd) > 0) relay(&cmd); | 
|---|
| [2636] | 223 | break; | 
|---|
|  | 224 | case SDL_KEYUP: | 
|---|
|  | 225 | strcpy( cmd.cmd, aliases->keys[event.key.keysym.sym]); | 
|---|
|  | 226 | cmd.bUp = true; | 
|---|
| [3225] | 227 | if( strlen (cmd.cmd) > 0) relay(&cmd); | 
|---|
| [2636] | 228 | break; | 
|---|
|  | 229 | case SDL_MOUSEMOTION: | 
|---|
|  | 230 | strcpy( cmd.cmd, "cursor"); | 
|---|
|  | 231 | cmd.x = event.motion.x; | 
|---|
|  | 232 | cmd.y = event.motion.y; | 
|---|
|  | 233 | cmd.xrel = event.motion.xrel; | 
|---|
|  | 234 | cmd.yrel = event.motion.yrel; | 
|---|
|  | 235 | break; | 
|---|
|  | 236 | case SDL_MOUSEBUTTONUP: | 
|---|
|  | 237 | strcpy( cmd.cmd, aliases->buttons[event.button.button]); | 
|---|
|  | 238 | cmd.bUp = true; | 
|---|
| [3225] | 239 | if( strlen (cmd.cmd) > 0) relay(&cmd); | 
|---|
| [2636] | 240 | break; | 
|---|
|  | 241 | case SDL_MOUSEBUTTONDOWN: | 
|---|
|  | 242 | strcpy( cmd.cmd, aliases->buttons[event.button.button]); | 
|---|
|  | 243 | cmd.bUp = false; | 
|---|
| [3225] | 244 | if( strlen (cmd.cmd) > 0) relay(&cmd); | 
|---|
| [2636] | 245 | break; | 
|---|
|  | 246 | case SDL_JOYAXISMOTION: | 
|---|
|  | 247 | case SDL_JOYBALLMOTION: | 
|---|
|  | 248 | case SDL_JOYHATMOTION: | 
|---|
|  | 249 | case SDL_JOYBUTTONDOWN: | 
|---|
|  | 250 | case SDL_JOYBUTTONUP: | 
|---|
|  | 251 | break; | 
|---|
|  | 252 | default: | 
|---|
|  | 253 | Orxonox *orx = Orxonox::getInstance(); | 
|---|
| [3225] | 254 | orx->eventHandler(&event); | 
|---|
| [2636] | 255 | break; | 
|---|
| [2066] | 256 | } | 
|---|
| [2636] | 257 | } | 
|---|
| [2066] | 258 | } | 
|---|
|  | 259 |  | 
|---|
| [2816] | 260 |  | 
|---|
| [3225] | 261 | void CommandNode::processNetwork () | 
|---|
| [2066] | 262 | { | 
|---|
|  | 263 |  | 
|---|
|  | 264 | } | 
|---|
|  | 265 |  | 
|---|
| [2816] | 266 |  | 
|---|
| [2066] | 267 | void CommandNode::relay (Command* cmd) | 
|---|
|  | 268 | { | 
|---|
| [3215] | 269 |  | 
|---|
| [2636] | 270 | Orxonox *orx = Orxonox::getInstance(); | 
|---|
| [3225] | 271 | if( orx->systemCommand (cmd)) return; | 
|---|
| [3216] | 272 |  | 
|---|
| [2636] | 273 | GameLoader* gl = GameLoader::getInstance(); | 
|---|
| [3216] | 274 | if( gl->worldCommand(cmd)) return; | 
|---|
|  | 275 |  | 
|---|
| [3225] | 276 | if( bLocalInput) sendOverNetwork (cmd); | 
|---|
| [2636] | 277 |  | 
|---|
| [3216] | 278 | if( this->world->command(cmd)) return; | 
|---|
|  | 279 |  | 
|---|
| [2816] | 280 | WorldEntity* entity = bound->enumerate(); | 
|---|
| [3216] | 281 | while( entity != NULL) | 
|---|
| [2636] | 282 | { | 
|---|
| [2816] | 283 | entity->command (cmd); | 
|---|
|  | 284 | entity = bound->nextElement(); | 
|---|
| [2636] | 285 | } | 
|---|
| [2066] | 286 | } | 
|---|
| [2096] | 287 |  | 
|---|
| [2816] | 288 |  | 
|---|
| [2141] | 289 | /** | 
|---|
| [2636] | 290 | \brief sets the network identifier of the CommandNode | 
|---|
|  | 291 | \param ID: the new ID to use | 
|---|
| [2141] | 292 | */ | 
|---|
| [3225] | 293 | void CommandNode::setNetID (int ID) | 
|---|
| [2096] | 294 | { | 
|---|
| [2636] | 295 | netID = ID; | 
|---|
| [2096] | 296 | } | 
|---|
|  | 297 |  | 
|---|
| [3225] | 298 | void CommandNode::sendOverNetwork (Command* cmd) | 
|---|
| [2096] | 299 | { | 
|---|
|  | 300 | } | 
|---|