source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/Controls/Keyboard.cs @ 4507

Revision 4507, 22.6 KB checked in by anlakane, 6 years ago (diff)

Talletus.

RevLine 
[4507]1#region MIT License
2/*
3 * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4 * Information Technology.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#endregion
25
26/*
27 * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28 */
29
30using System;
31using Microsoft.Xna.Framework.Input;
32
33using XnaKeyboard = Microsoft.Xna.Framework.Input.Keyboard;
34using System.Collections.Generic;
35
36namespace Jypeli.Controls
37{
38    /// <summary>
39    /// Näppäimistö peliohjaimena.
40    /// </summary>
41    public class Keyboard : Controller<KeyboardState>
42    {
43#if WINDOWS
44        internal static KeyboardTextBuffer Buffer = new KeyboardTextBuffer();
45#endif
46
47        internal Keyboard()
48        {
49            oldState = XnaKeyboard.GetState();
50        }
51
52        /// <summary>
53        /// Tarkistaa, liittyykö näppäimeen k merkkiä.
54        /// </summary>
55        /// <param name="k">Näppäin</param>
56        /// <returns>boolean</returns>
57        public static bool IsChar( Key k )
58        {
59            return ToMaybeChar( k ).HasValue;
60        }
61
62        /// <summary>
63        /// Palauttaa näppäimen merkille c.
64        /// Jos merkille ei ole näppäintä, palautetaan Key.None.
65        /// </summary>
66        /// <param name="c">Merkki</param>
67        /// <returns>Näppäin</returns>
68        public static Key FromChar( char c )
69        {
70            Key result = Key.None;
71#if WINDOWS
72            Enum.TryParse<Key>( c.ToString(), true, out result );
73#endif
74            return result;
75        }
76
77        /// <summary>
78        /// Palauttaa merkin, joka liittyy näppäimeen k.
79        /// Jos näppäimeen ei liity merkkiä, tapahtuu poikkeus ArgumentException.
80        /// </summary>
81        /// <param name="k">Näppäin</param>
82        /// <returns>Merkki</returns>
83        public static char ToChar( Key k )
84        {
85            char? ch = ToMaybeChar( k );
86            if ( !ch.HasValue ) throw new ArgumentException( k.ToString() + " has no character attached to it." );
87            return ch.Value;
88        }
89
90        private static char? ToMaybeChar( Key k )
91        {
92            if ( k == Key.Space ) return ' ';
93
94            string keyStr = k.ToString();
95            if ( keyStr.Length == 1 ) return char.ToLower( keyStr[0] );
96            if ( keyStr.Length == 2 && keyStr[0] == 'D' ) return keyStr[1];
97            if ( keyStr.Length == 7 && keyStr.StartsWith( "NumPad" ) ) return keyStr[6];
98
99            if ( k == Key.OemQuotes ) return 'ä';
100            if ( k == Key.OemTilde ) return 'ö';
101            if ( k == Key.OemPlus || k == Key.Add ) return '+';
102            if ( k == Key.Subtract ) return '-';
103            if ( k == Key.Multiply ) return '*';
104            if ( k == Key.Divide ) return '/';
105            if ( k == Key.Aring ) return 'å';
106            if ( k == Key.LessOrGreater ) return '<';
107
108            return null;
109        }
110
111        private static Keys ToXnaKeys( Key k )
112        {
113            return (Keys)k;
114        }
115
116        protected override bool IsTriggered( Listener listener )
117        {
118            if ( listener.Type == ListeningType.KeyboardKey )
119            {
120                return KeyTriggered( listener );
121            }
122
123            if ( listener.Type == ListeningType.KeyboardAll )
124            {
125                List<Key> keys = KeysTriggered( listener.State );
126                return keys.Count > 0;
127            }
128
129            return base.IsTriggered( listener );
130        }
131
132        private bool KeyTriggered( Listener listener )
133        {
134            Keys k = ToXnaKeys( listener.Key );
135
136            switch ( listener.State )
137            {
138                case ButtonState.Irrelevant:
139                    return true;
140
141                case ButtonState.Released:
142                    return ( oldState.IsKeyDown( k ) && newState.IsKeyUp( k ) );
143
144                case ButtonState.Pressed:
145                    return ( oldState.IsKeyUp( k ) && newState.IsKeyDown( k ) );
146
147                case ButtonState.Up:
148                    return ( newState.IsKeyUp( k ) );
149
150                case ButtonState.Down:
151                    return ( newState.IsKeyDown( k ) );
152            }
153
154            return false;
155        }
156
157        internal List<Key> KeysTriggered( ButtonState state )
158        {
159            List<Keys> pressedBefore = new List<Keys>( oldState.GetPressedKeys() );
160            List<Keys> pressedNow = new List<Keys>( newState.GetPressedKeys() );
161            List<Key> triggered = new List<Key>();
162
163            switch ( state )
164            {
165                case ButtonState.Released:
166                    for ( int i = 0; i < pressedBefore.Count; i++ )
167                    {
168                        if ( !pressedNow.Contains( pressedBefore[i] ) )
169                            triggered.Add( (Key)pressedBefore[i] );
170                    }
171                    break;
172
173                case ButtonState.Pressed:
174                    for ( int i = 0; i < pressedNow.Count; i++ )
175                    {
176                        if ( !pressedBefore.Contains( pressedNow[i] ) )
177                            triggered.Add( (Key)pressedNow[i] );
178                    }
179                    break;
180
181                case ButtonState.Up:
182                    throw new NotImplementedException( "Not implemented" );
183
184                case ButtonState.Down:
185                    for ( int i = 0; i < pressedNow.Count; i++ )
186                    {
187                        triggered.Add( (Key)pressedNow[i] );
188                    }
189                    break;
190            }
191
192            return triggered;
193        }
194
195        internal override bool IsBufferEmpty()
196        {
197            return ( newState.GetPressedKeys().Length == 0 );
198        }
199
200        /// <summary>
201        /// Ottaa käytöstä poistetun napin <c>k</c> takaisin käyttöön.
202        /// </summary>
203        public void Enable( Key k )
204        {
205            base.Enable( listener => ( listener.Key == k ) );
206        }
207
208        /// <summary>
209        /// Poistaa napin <c>k</c> käytöstä.
210        /// </summary>
211        public void Disable( Key k )
212        {
213            base.Disable( listener => ( listener.Key == k ) );
214        }
215
216        internal override KeyboardState GetCurrentState()
217        {
218            return XnaKeyboard.GetState();
219        }
220
221        /// <summary>
222        /// Palauttaa annetun näppäimen tilan (ks. <c>ButtonState</c>).
223        /// </summary>
224        /// <param name="k">Näppäin.</param>
225        /// <returns>Näppäimen tila</returns>
226        public ButtonState GetKeyState( Key k )
227        {
228            Keys key = ToXnaKeys( k );
229            bool down = newState.IsKeyDown( key );
230            bool lastdown = oldState.IsKeyDown( key );
231
232            if ( lastdown && down )
233                return ButtonState.Down;
234            if ( !lastdown && down )
235                return ButtonState.Pressed;
236            if ( lastdown && !down )
237                return ButtonState.Released;
238
239            return ButtonState.Up;
240        }
241
242        /// <summary>
243        /// Tarkistaa, onko kumpikaan shift-näppäimistä painettuna.
244        /// </summary>
245        /// <returns>
246        ///     <c>true</c> jos alhaalla, muuten <c>painettuna</c>.
247        /// </returns>
248        public bool IsShiftDown()
249        {
250            return newState.IsKeyDown( Keys.LeftShift ) || newState.IsKeyDown( Keys.RightShift );
251        }
252
253        /// <summary>
254        /// Tarkistaa, onko kumpikaan ctrl-näppäimistä painettuna.
255        /// </summary>
256        /// <returns>
257        ///     <c>true</c> jos alhaalla, muuten <c>painettuna</c>.
258        /// </returns>
259        public bool IsCtrlDown()
260        {
261            return newState.IsKeyDown( Keys.LeftControl ) || newState.IsKeyDown( Keys.RightControl );
262        }
263
264        /// <summary>
265        /// Tarkistaa, onko kumpikaan alt-näppäimistä painettuna.
266        /// </summary>
267        /// <returns>
268        ///     <c>true</c> jos alhaalla, muuten <c>painettuna</c>.
269        /// </returns>
270        public bool IsAltDown()
271        {
272            return newState.IsKeyDown( Keys.LeftAlt ) || newState.IsKeyDown( Keys.RightAlt );
273        }
274
275        internal override string GetControlText( Listener listener )
276        {
277            if ( listener.Key == Key.Add ) return "NumPad+";
278            if ( listener.Key == Key.Subtract ) return "NumPad-";
279            if ( listener.Key == Key.Multiply ) return "NumPad*";
280            if ( listener.Key == Key.Divide ) return "NumPad/";
281            if ( listener.Key == Key.OemQuotes ) return "Ä";
282            if ( listener.Key == Key.OemTilde ) return "Ö";
283            if ( listener.Key == Key.Left ) return "Left arrow";
284            if ( listener.Key == Key.Right ) return "Right arrow";
285            if ( listener.Key == Key.Up ) return "Up arrow";
286            if ( listener.Key == Key.Down ) return "Down arrow";
287
288            return listener.Key.ToString();
289        }
290
291        #region Listen
292        public Listener Listen( Key k, ButtonState state, Handler handler, String helpText )
293        {
294            Listener l = new SimpleListener( this, ListeningType.KeyboardKey, helpText, handler );
295            l.Key = k;
296            l.State = state;
297            Add( l );
298            return l;
299        }
300
301        public Listener Listen<T1>( Key k, ButtonState state, Handler<T1> handler, String helpText, T1 p1 )
302        {
303            Listener l = new SimpleListener<T1>( this, ListeningType.KeyboardKey, helpText, handler, p1 );
304            l.Key = k;
305            l.State = state;
306            Add( l );
307            return l;
308        }
309
310        public Listener Listen<T1, T2>( Key k, ButtonState state, Handler<T1, T2> handler, String helpText, T1 p1, T2 p2 )
311        {
312            Listener l = new SimpleListener<T1, T2>( this, ListeningType.KeyboardKey, helpText, handler, p1, p2 );
313            l.Key = k;
314            l.State = state;
315            Add( l );
316            return l;
317        }
318
319        public Listener Listen<T1, T2, T3>( Key k, ButtonState state, Handler<T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
320        {
321            Listener l = new SimpleListener<T1, T2, T3>( this, ListeningType.KeyboardKey, helpText, handler, p1, p2, p3 );
322            l.Key = k;
323            l.State = state;
324            Add( l );
325            return l;
326        }
327
328        public Listener Listen<T1, T2, T3, T4>( Key k, ButtonState state, Handler<T1, T2, T3, T4> handler, String helpText, T1 p1, T2 p2, T3 p3, T4 p4 )
329        {
330            Listener l = new SimpleListener<T1, T2, T3, T4>( this, ListeningType.KeyboardKey, helpText, handler, p1, p2, p3, p4 );
331            l.Key = k;
332            l.State = state;
333            Add( l );
334            return l;
335        }
336        #endregion
337
338        #region ListenWSAD
339        /// <summary>
340        /// Kuuntelee W, S, A ja D -näppäimiä.
341        /// </summary>
342        /// <param name="state">Näppäinten kuunneltava tila</param>
343        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
344        /// <param name="helpText">Ohjeteksti.</param>
345        public void ListenWSAD( ButtonState state, Handler<Vector> handler, String helpText )
346        {
347            Listen( Key.W, state, handler, helpText, Vector.UnitY );
348            Listen( Key.S, state, handler, helpText, -Vector.UnitY );
349            Listen( Key.A, state, handler, helpText, -Vector.UnitX );
350            Listen( Key.D, state, handler, helpText, Vector.UnitX );
351        }
352
353        /// <summary>
354        /// Kuuntelee W, S, A ja D -näppäimiä.
355        /// </summary>
356        /// <typeparam name="T1">Ensimmäisen oman parametrin tyyppi</typeparam>
357        /// <param name="state">Näppäinten kuunneltava tila</param>
358        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
359        /// <param name="helpText">Ohjeteksti.</param>
360        /// <param name="p1">Ensimmäisen oman parametrin arvo</param>
361        public void ListenWSAD<T1>( ButtonState state, Handler<Vector, T1> handler, String helpText, T1 p1 )
362        {
363            Listen( Key.W, state, handler, helpText, Vector.UnitY, p1 );
364            Listen( Key.S, state, handler, helpText, -Vector.UnitY, p1 );
365            Listen( Key.A, state, handler, helpText, -Vector.UnitX, p1 );
366            Listen( Key.D, state, handler, helpText, Vector.UnitX, p1 );
367        }
368
369        /// <summary>
370        /// Kuuntelee W, S, A ja D -näppäimiä.
371        /// </summary>
372        /// <typeparam name="T1">Ensimmäisen oman parametrin tyyppi</typeparam>
373        /// <typeparam name="T2">Toisen oman parametrin tyyppi</typeparam>
374        /// <param name="state">Näppäinten kuunneltava tila</param>
375        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
376        /// <param name="helpText">Ohjeteksti.</param>
377        /// <param name="p1">Ensimmäisen oman parametrin arvo</param>
378        /// <param name="p2">Toisen oman parametrin arvo</param>
379        public void ListenWSAD<T1, T2>( ButtonState state, Handler<Vector, T1, T2> handler, String helpText, T1 p1, T2 p2 )
380        {
381            Listen( Key.W, state, handler, helpText, Vector.UnitY, p1, p2 );
382            Listen( Key.S, state, handler, helpText, -Vector.UnitY, p1, p2 );
383            Listen( Key.A, state, handler, helpText, -Vector.UnitX, p1, p2 );
384            Listen( Key.D, state, handler, helpText, Vector.UnitX, p1, p2 );
385        }
386
387        /// <summary>
388        /// Kuuntelee W, S, A ja D -näppäimiä.
389        /// </summary>
390        /// <typeparam name="T1">Ensimmäisen oman parametrin tyyppi</typeparam>
391        /// <typeparam name="T2">Toisen oman parametrin tyyppi</typeparam>
392        /// <param name="state">Näppäinten kuunneltava tila</param>
393        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
394        /// <param name="helpText">Ohjeteksti.</param>
395        /// <param name="p1">Ensimmäisen oman parametrin arvo</param>
396        /// <param name="p2">Toisen oman parametrin arvo</param>
397        public void ListenWSAD<T1, T2, T3>( ButtonState state, Handler<Vector, T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
398        {
399            Listen( Key.W, state, handler, helpText, Vector.UnitY, p1, p2, p3 );
400            Listen( Key.S, state, handler, helpText, -Vector.UnitY, p1, p2, p3 );
401            Listen( Key.A, state, handler, helpText, -Vector.UnitX, p1, p2, p3 );
402            Listen( Key.D, state, handler, helpText, Vector.UnitX, p1, p2, p3 );
403        }
404        #endregion
405
406        #region ListenArrows
407        /// <summary>
408        /// Kuuntelee nuolinäppäimiä.
409        /// </summary>
410        /// <param name="state">Näppäinten kuunneltava tila</param>
411        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
412        /// <param name="helpText">Ohjeteksti.</param>
413        public void ListenArrows( ButtonState state, Handler<Vector> handler, String helpText )
414        {
415            Listen( Key.Up, state, handler, helpText, Vector.UnitY );
416            Listen( Key.Down, state, handler, helpText, -Vector.UnitY );
417            Listen( Key.Left, state, handler, helpText, -Vector.UnitX );
418            Listen( Key.Right, state, handler, helpText, Vector.UnitX );
419        }
420
421        /// <summary>
422        /// Kuuntelee nuolinäppäimiä.
423        /// </summary>
424        /// <typeparam name="T1">Ensimmäisen oman parametrin tyyppi</typeparam>
425        /// <param name="state">Näppäinten kuunneltava tila</param>
426        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
427        /// <param name="helpText">Ohjeteksti.</param>
428        /// <param name="p1">Ensimmäisen oman parametrin arvo</param>
429        public void ListenArrows<T1>( ButtonState state, Handler<Vector, T1> handler, String helpText, T1 p1 )
430        {
431            Listen( Key.Up, state, handler, helpText, Vector.UnitY, p1 );
432            Listen( Key.Down, state, handler, helpText, -Vector.UnitY, p1 );
433            Listen( Key.Left, state, handler, helpText, -Vector.UnitX, p1 );
434            Listen( Key.Right, state, handler, helpText, Vector.UnitX, p1 );
435        }
436
437        /// <summary>
438        /// Kuuntelee nuolinäppäimiä.
439        /// </summary>
440        /// <typeparam name="T1">Ensimmäisen oman parametrin tyyppi</typeparam>
441        /// <typeparam name="T2">Toisen oman parametrin tyyppi</typeparam>
442        /// <param name="state">Näppäinten kuunneltava tila</param>
443        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
444        /// <param name="helpText">Ohjeteksti.</param>
445        /// <param name="p1">Ensimmäisen oman parametrin arvo</param>
446        /// <param name="p2">Toisen oman parametrin arvo</param>
447        public void ListenArrows<T1, T2>( ButtonState state, Handler<Vector, T1, T2> handler, String helpText, T1 p1, T2 p2 )
448        {
449            Listen( Key.Up, state, handler, helpText, Vector.UnitY, p1, p2 );
450            Listen( Key.Down, state, handler, helpText, -Vector.UnitY, p1, p2 );
451            Listen( Key.Left, state, handler, helpText, -Vector.UnitX, p1, p2 );
452            Listen( Key.Right, state, handler, helpText, Vector.UnitX, p1, p2 );
453        }
454
455        /// <summary>
456        /// Kuuntelee nuolinäppäimiä.
457        /// </summary>
458        /// <typeparam name="T1">Ensimmäisen oman parametrin tyyppi</typeparam>
459        /// <typeparam name="T2">Toisen oman parametrin tyyppi</typeparam>
460        /// <param name="state">Näppäinten kuunneltava tila</param>
461        /// <param name="handler">Tapahtumakäsittelijä. Ensimmäinen parametri on automaattisesti yksikköpituinen vektori.</param>
462        /// <param name="helpText">Ohjeteksti.</param>
463        /// <param name="p1">Ensimmäisen oman parametrin arvo</param>
464        /// <param name="p2">Toisen oman parametrin arvo</param>
465        public void ListenArrows<T1, T2, T3>( ButtonState state, Handler<Vector, T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
466        {
467            Listen( Key.Up, state, handler, helpText, Vector.UnitY, p1, p2, p3 );
468            Listen( Key.Down, state, handler, helpText, -Vector.UnitY, p1, p2, p3 );
469            Listen( Key.Left, state, handler, helpText, -Vector.UnitX, p1, p2, p3 );
470            Listen( Key.Right, state, handler, helpText, Vector.UnitX, p1, p2, p3 );
471        }
472        #endregion
473
474        #region ListenAll
475        public Listener ListenAll( ButtonState state, MultiKeyHandler handler, String helpText )
476        {
477            Listener l = new MultiKeyListener( this, helpText, handler );
478            l.State = state;
479            Add( l );
480            return l;
481        }
482
483        public Listener ListenAll<T1>( ButtonState state, MultiKeyHandler<T1> handler, String helpText, T1 p1 )
484        {
485            Listener l = new MultiKeyListener<T1>( this, helpText, handler, p1 );
486            l.State = state;
487            Add( l );
488            return l;
489        }
490
491        public Listener ListenAll<T1, T2>( ButtonState state, MultiKeyHandler<T1, T2> handler, String helpText, T1 p1, T2 p2 )
492        {
493            Listener l = new MultiKeyListener<T1, T2>( this, helpText, handler, p1, p2 );
494            l.State = state;
495            Add( l );
496            return l;
497        }
498
499        public Listener ListenAll<T1, T2, T3>( ButtonState state, MultiKeyHandler<T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
500        {
501            Listener l = new MultiKeyListener<T1, T2, T3>( this, helpText, handler, p1, p2, p3 );
502            l.State = state;
503            Add( l );
504            return l;
505        }
506
507        public Listener ListenAll<T1, T2, T3, T4>( ButtonState state, MultiKeyHandler<T1, T2, T3, T4> handler, String helpText, T1 p1, T2 p2, T3 p3, T4 p4 )
508        {
509            Listener l = new MultiKeyListener<T1, T2, T3, T4>( this, helpText, handler, p1, p2, p3, p4 );
510            l.State = state;
511            Add( l );
512            return l;
513        }
514
515        public Listener ListenAll( ButtonState state, Action<Key> handler )
516        {
517            Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { keys.ForEach( handler ); } );
518            l.State = state;
519            Add( l );
520            return l;
521        }
522
523        public Listener ListenAll<T1>( ButtonState state, Action<Key, T1> handler, T1 p1 )
524        {
525            Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { foreach ( var k in keys ) handler( k, p1 ); } );
526            l.State = state;
527            Add( l );
528            return l;
529        }
530
531        public Listener ListenAll<T1, T2>( ButtonState state, Action<Key, T1, T2> handler, T1 p1, T2 p2 )
532        {
533            Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { foreach ( var k in keys ) handler( k, p1, p2 ); } );
534            l.State = state;
535            Add( l );
536            return l;
537        }
538
539        public Listener ListenAll<T1, T2, T3>( ButtonState state, Action<Key, T1, T2, T3> handler, T1 p1, T2 p2, T3 p3 )
540        {
541            Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { foreach ( var k in keys ) handler( k, p1, p2, p3 ); } );
542            l.State = state;
543            Add( l );
544            return l;
545        }
546        #endregion
547    }
548}
Note: See TracBrowser for help on using the repository browser.