[OpenTK] Introduce OpenTK (#336)
[platform/core/csapi/tizenfx.git] / external / src / OpenTK / OpenTK / Input / GamePadConfiguration.cs
1 //
2 // GamePadMapping.cs
3 //
4 // Author:
5 //       Stefanos A. <stapostol@gmail.com>
6 //
7 // Copyright (c) 2006-2013 Stefanos Apostolopoulos
8 //
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:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
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
25 // THE SOFTWARE.
26 //
27
28 using System;
29 using System.Collections.Generic;
30
31 namespace OpenTK.Input
32 {
33     internal sealed class GamePadConfiguration
34     {
35         private static readonly char[] ConfigurationSeparator = new char[] { ',' };
36
37         private readonly List<GamePadConfigurationItem> configuration_items =
38             new List<GamePadConfigurationItem>();
39
40         public Guid Guid { get; private set; }
41
42         public string Name { get; private set; }
43
44         public GamePadConfiguration(string configuration)
45         {
46             ParseConfiguration(configuration);
47         }
48
49         public List<GamePadConfigurationItem>.Enumerator GetEnumerator()
50         {
51             return configuration_items.GetEnumerator();
52         }
53
54         /// <summary>
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
59         /// </summary>
60         /// <param name="configuration"></param>
61         private void ParseConfiguration(string configuration)
62         {
63             if (String.IsNullOrEmpty(configuration))
64             {
65                 throw new ArgumentNullException();
66             }
67
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);
74             if (items.Length < 3)
75             {
76                 throw new ArgumentException();
77             }
78
79             GamePadConfiguration map = this;
80             map.Guid = new Guid(items[0]);
81             map.Name = items[1];
82             for (int i = 2; i < items.Length; i++)
83             {
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));
88             }
89         }
90
91         /// <summary>
92         /// Parses a gamepad configuration target string
93         /// </summary>
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)
97         {
98             switch (target)
99             {
100                 // Buttons
101                 case "a":
102                     return new GamePadConfigurationTarget(Buttons.A);
103                 case "b":
104                     return new GamePadConfigurationTarget(Buttons.B);
105                 case "x":
106                     return new GamePadConfigurationTarget(Buttons.X);
107                 case "y":
108                     return new GamePadConfigurationTarget(Buttons.Y);
109                 case "start":
110                     return new GamePadConfigurationTarget(Buttons.Start);
111                 case "back":
112                     return new GamePadConfigurationTarget(Buttons.Back);
113                 case "guide":
114                     return new GamePadConfigurationTarget(Buttons.BigButton);
115                 case "leftshoulder":
116                     return new GamePadConfigurationTarget(Buttons.LeftShoulder);
117                 case "rightshoulder":
118                     return new GamePadConfigurationTarget(Buttons.RightShoulder);
119                 case "leftstick":
120                     return new GamePadConfigurationTarget(Buttons.LeftStick);
121                 case "rightstick":
122                     return new GamePadConfigurationTarget(Buttons.RightStick);
123                 case "dpup":
124                     return new GamePadConfigurationTarget(Buttons.DPadUp);
125                 case "dpdown":
126                     return new GamePadConfigurationTarget(Buttons.DPadDown);
127                 case "dpleft":
128                     return new GamePadConfigurationTarget(Buttons.DPadLeft);
129                 case "dpright":
130                     return new GamePadConfigurationTarget(Buttons.DPadRight);
131
132                 // Axes
133                 case "leftx":
134                     return new GamePadConfigurationTarget(GamePadAxes.LeftX);
135                 case "lefty":
136                     return new GamePadConfigurationTarget(GamePadAxes.LeftY);
137                 case "rightx":
138                     return new GamePadConfigurationTarget(GamePadAxes.RightX);
139                 case "righty":
140                     return new GamePadConfigurationTarget(GamePadAxes.RightY);
141
142                 // Triggers
143                 case "lefttrigger":
144                     return new GamePadConfigurationTarget(GamePadAxes.LeftTrigger);
145                 case "righttrigger":
146                     return new GamePadConfigurationTarget(GamePadAxes.RightTrigger);
147
148
149                 // Unmapped
150                 default:
151                     return new GamePadConfigurationTarget();
152             }
153         }
154
155         /// <summary>
156         /// Creates a new gamepad configuration source from the given string
157         /// </summary>
158         /// <param name="item">The string to parse</param>
159         /// <returns>The new gamepad configuration source</returns>
160         private static GamePadConfigurationSource ParseSource(string item)
161         {
162             if (String.IsNullOrEmpty(item))
163             {
164                 return new GamePadConfigurationSource();
165             }
166
167             switch (item[0])
168             {
169                 case 'a':
170                     return new GamePadConfigurationSource(isAxis:true, index:ParseIndex(item));
171
172                 case 'b':
173                     return new GamePadConfigurationSource(isAxis:false, index:ParseIndex(item));
174
175                 case 'h':
176                     {
177                         HatPosition position;
178                         JoystickHat hat = ParseHat(item, out position);
179                         return new GamePadConfigurationSource(hat, position);
180                     }
181
182                 default:
183                     throw new InvalidOperationException("[Input] Invalid GamePad configuration value");
184             }
185         }
186
187         /// <summary>
188         /// Parses a string in the format a#" where:
189         /// - # is a zero-based integer number
190         /// </summary>
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)
194         {
195             // item is in the format "a#" where # a zero-based integer number
196             return Int32.Parse(item.Substring(1)); ;
197         }
198
199         /// <summary>
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
203         /// </summary>
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)
208         {
209             JoystickHat hat = JoystickHat.Hat0;
210             int id = Int32.Parse(item.Substring(1, 1));
211             int pos = Int32.Parse(item.Substring(3));
212
213             position = HatPosition.Centered;
214             switch (pos)
215             {
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;
225             }
226
227             return hat + id;
228         }
229     }
230 }