5 // Stefanos A. <stapostol@gmail.com>
7 // Copyright (c) 2006-2013 Stefanos Apostolopoulos
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 using System.Collections.Generic;
31 namespace OpenTK.Input
33 internal sealed class GamePadConfiguration
35 private static readonly char[] ConfigurationSeparator = new char[] { ',' };
37 private readonly List<GamePadConfigurationItem> configuration_items =
38 new List<GamePadConfigurationItem>();
40 public Guid Guid { get; private set; }
42 public string Name { get; private set; }
44 public GamePadConfiguration(string configuration)
46 ParseConfiguration(configuration);
49 public List<GamePadConfigurationItem>.Enumerator GetEnumerator()
51 return configuration_items.GetEnumerator();
55 /// Parses a GamePad configuration string.
56 /// This string must follow the rules for SDL2
57 /// GameController outlined here:
58 /// http://wiki.libsdl.org/SDL_GameControllerAddMapping
60 /// <param name="configuration"></param>
61 private void ParseConfiguration(string configuration)
63 if (String.IsNullOrEmpty(configuration))
65 throw new ArgumentNullException();
68 // The mapping string has the format "GUID,name,config"
69 // - GUID is a unigue identifier returned by Joystick.GetGuid()
70 // - name is a human-readable name for the controller
71 // - config is a comma-separated list of configurations as follows:
72 // - [gamepad axis or button name]:[joystick axis, button or hat number]
73 string[] items = configuration.Split(ConfigurationSeparator, StringSplitOptions.RemoveEmptyEntries);
76 throw new ArgumentException();
79 GamePadConfiguration map = this;
80 map.Guid = new Guid(items[0]);
82 for (int i = 2; i < items.Length; i++)
84 string[] config = items[i].Split(':');
85 GamePadConfigurationTarget target = ParseTarget(config[0]);
86 GamePadConfigurationSource source = ParseSource(config[1]);
87 configuration_items.Add(new GamePadConfigurationItem(source, target));
92 /// Parses a gamepad configuration target string
94 /// <param name="target">The string to parse</param>
95 /// <returns>The configuration target (Button index, axis index etc.)</returns>
96 private static GamePadConfigurationTarget ParseTarget(string target)
102 return new GamePadConfigurationTarget(Buttons.A);
104 return new GamePadConfigurationTarget(Buttons.B);
106 return new GamePadConfigurationTarget(Buttons.X);
108 return new GamePadConfigurationTarget(Buttons.Y);
110 return new GamePadConfigurationTarget(Buttons.Start);
112 return new GamePadConfigurationTarget(Buttons.Back);
114 return new GamePadConfigurationTarget(Buttons.BigButton);
116 return new GamePadConfigurationTarget(Buttons.LeftShoulder);
117 case "rightshoulder":
118 return new GamePadConfigurationTarget(Buttons.RightShoulder);
120 return new GamePadConfigurationTarget(Buttons.LeftStick);
122 return new GamePadConfigurationTarget(Buttons.RightStick);
124 return new GamePadConfigurationTarget(Buttons.DPadUp);
126 return new GamePadConfigurationTarget(Buttons.DPadDown);
128 return new GamePadConfigurationTarget(Buttons.DPadLeft);
130 return new GamePadConfigurationTarget(Buttons.DPadRight);
134 return new GamePadConfigurationTarget(GamePadAxes.LeftX);
136 return new GamePadConfigurationTarget(GamePadAxes.LeftY);
138 return new GamePadConfigurationTarget(GamePadAxes.RightX);
140 return new GamePadConfigurationTarget(GamePadAxes.RightY);
144 return new GamePadConfigurationTarget(GamePadAxes.LeftTrigger);
146 return new GamePadConfigurationTarget(GamePadAxes.RightTrigger);
151 return new GamePadConfigurationTarget();
156 /// Creates a new gamepad configuration source from the given string
158 /// <param name="item">The string to parse</param>
159 /// <returns>The new gamepad configuration source</returns>
160 private static GamePadConfigurationSource ParseSource(string item)
162 if (String.IsNullOrEmpty(item))
164 return new GamePadConfigurationSource();
170 return new GamePadConfigurationSource(isAxis:true, index:ParseIndex(item));
173 return new GamePadConfigurationSource(isAxis:false, index:ParseIndex(item));
177 HatPosition position;
178 JoystickHat hat = ParseHat(item, out position);
179 return new GamePadConfigurationSource(hat, position);
183 throw new InvalidOperationException("[Input] Invalid GamePad configuration value");
188 /// Parses a string in the format a#" where:
189 /// - # is a zero-based integer number
191 /// <param name="item">The string to parse</param>
192 /// <returns>The index of the axis or button</returns>
193 private static int ParseIndex(string item)
195 // item is in the format "a#" where # a zero-based integer number
196 return Int32.Parse(item.Substring(1)); ;
200 /// Parses a string in the format "h#.#" where:
201 /// - the 1st # is the zero-based hat id
202 /// - the 2nd # is a bit-flag defining the hat position
204 /// <param name="item">The string to parse</param>
205 /// <param name="position">The hat position assigned via 'out'</param>
206 /// <returns>The new joystick hat</returns>
207 private static JoystickHat ParseHat(string item, out HatPosition position)
209 JoystickHat hat = JoystickHat.Hat0;
210 int id = Int32.Parse(item.Substring(1, 1));
211 int pos = Int32.Parse(item.Substring(3));
213 position = HatPosition.Centered;
216 case 1: position = HatPosition.Up; break;
217 case 2: position = HatPosition.Right; break;
218 case 3: position = HatPosition.UpRight; break;
219 case 4: position = HatPosition.Down; break;
220 case 6: position = HatPosition.DownRight; break;
221 case 8: position = HatPosition.Left; break;
222 case 9: position = HatPosition.UpLeft; break;
223 case 12: position = HatPosition.DownLeft; break;
224 default: position = HatPosition.Centered; break;