improve gamepad init and support hotplugging
							parent
							
								
									646e5e9283
								
							
						
					
					
						commit
						f6fc80804e
					
				
							
								
								
									
										24
									
								
								src/Game.cs
								
								
								
								
							
							
						
						
									
										24
									
								
								src/Game.cs
								
								
								
								
							|  | @ -205,6 +205,14 @@ namespace MoonWorks | ||||||
| 					case SDL.SDL_EventType.SDL_DROPFILE: | 					case SDL.SDL_EventType.SDL_DROPFILE: | ||||||
| 						HandleFileDrop(_event); | 						HandleFileDrop(_event); | ||||||
| 						break; | 						break; | ||||||
|  | 
 | ||||||
|  | 					case SDL.SDL_EventType.SDL_CONTROLLERDEVICEADDED: | ||||||
|  | 						HandleControllerAdded(_event); | ||||||
|  | 						break; | ||||||
|  | 
 | ||||||
|  | 					case SDL.SDL_EventType.SDL_CONTROLLERDEVICEREMOVED: | ||||||
|  | 						HandleControllerRemoved(_event); | ||||||
|  | 						break; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -244,6 +252,22 @@ namespace MoonWorks | ||||||
| 			DropFile(filePath); | 			DropFile(filePath); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		private void HandleControllerAdded(SDL.SDL_Event evt) | ||||||
|  | 		{ | ||||||
|  | 			var index = evt.cdevice.which; | ||||||
|  | 			if (SDL.SDL_IsGameController(index) == SDL.SDL_bool.SDL_TRUE) | ||||||
|  | 			{ | ||||||
|  | 				System.Console.WriteLine($"New controller detected!"); | ||||||
|  | 				Inputs.AddGamepad(index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		private void HandleControllerRemoved(SDL.SDL_Event evt) | ||||||
|  | 		{ | ||||||
|  | 			System.Console.WriteLine($"Controller removal detected!"); | ||||||
|  | 			Inputs.RemoveGamepad(evt.cdevice.which); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		private TimeSpan AdvanceElapsedTime() | 		private TimeSpan AdvanceElapsedTime() | ||||||
| 		{ | 		{ | ||||||
| 			long currentTicks = gameTimer.Elapsed.Ticks; | 			long currentTicks = gameTimer.Elapsed.Ticks; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| using System; |  | ||||||
| using MoonWorks.Math; | using MoonWorks.Math; | ||||||
| using SDL2; | using SDL2; | ||||||
| 
 | 
 | ||||||
|  | @ -6,7 +5,7 @@ namespace MoonWorks.Input | ||||||
| { | { | ||||||
| 	public class Axis | 	public class Axis | ||||||
| 	{ | 	{ | ||||||
| 		IntPtr GamepadHandle; | 		public Gamepad Parent { get; } | ||||||
| 		SDL.SDL_GameControllerAxis SDL_Axis; | 		SDL.SDL_GameControllerAxis SDL_Axis; | ||||||
| 
 | 
 | ||||||
| 		public AxisCode Code { get; private set; } | 		public AxisCode Code { get; private set; } | ||||||
|  | @ -17,11 +16,11 @@ namespace MoonWorks.Input | ||||||
| 		public float Value { get; private set; } | 		public float Value { get; private set; } | ||||||
| 
 | 
 | ||||||
| 		public Axis( | 		public Axis( | ||||||
| 			IntPtr gamepadHandle, | 			Gamepad parent, | ||||||
| 			AxisCode code, | 			AxisCode code, | ||||||
| 			SDL.SDL_GameControllerAxis sdlAxis | 			SDL.SDL_GameControllerAxis sdlAxis | ||||||
| 		) { | 		) { | ||||||
| 			GamepadHandle = gamepadHandle; | 			Parent = parent; | ||||||
| 			SDL_Axis = sdlAxis; | 			SDL_Axis = sdlAxis; | ||||||
| 			Code = code; | 			Code = code; | ||||||
| 		} | 		} | ||||||
|  | @ -29,7 +28,7 @@ namespace MoonWorks.Input | ||||||
| 		internal void Update() | 		internal void Update() | ||||||
| 		{ | 		{ | ||||||
| 			Value = MathHelper.Normalize( | 			Value = MathHelper.Normalize( | ||||||
| 				SDL.SDL_GameControllerGetAxis(GamepadHandle, SDL_Axis), | 				SDL.SDL_GameControllerGetAxis(Parent.Handle, SDL_Axis), | ||||||
| 				short.MinValue, short.MaxValue, | 				short.MinValue, short.MaxValue, | ||||||
| 				-1, 1 | 				-1, 1 | ||||||
| 			); | 			); | ||||||
|  |  | ||||||
|  | @ -8,7 +8,9 @@ namespace MoonWorks.Input | ||||||
| 	public class Gamepad | 	public class Gamepad | ||||||
| 	{ | 	{ | ||||||
| 		internal IntPtr Handle; | 		internal IntPtr Handle; | ||||||
| 		internal int Index; | 		internal int JoystickInstanceID; | ||||||
|  | 
 | ||||||
|  | 		public int Slot { get; internal set; } | ||||||
| 
 | 
 | ||||||
| 		public GamepadButton A { get; } | 		public GamepadButton A { get; } | ||||||
| 		public GamepadButton B { get; } | 		public GamepadButton B { get; } | ||||||
|  | @ -61,37 +63,40 @@ namespace MoonWorks.Input | ||||||
| 
 | 
 | ||||||
| 		private VirtualButton[] VirtualButtons; | 		private VirtualButton[] VirtualButtons; | ||||||
| 
 | 
 | ||||||
| 		internal Gamepad(IntPtr handle, int index) | 		internal Gamepad(IntPtr handle, int slot) | ||||||
| 		{ | 		{ | ||||||
| 			Handle = handle; | 			Handle = handle; | ||||||
| 			Index = index; | 			Slot = slot; | ||||||
|  | 
 | ||||||
|  | 			IntPtr joystickHandle = SDL.SDL_GameControllerGetJoystick(Handle); | ||||||
|  | 			JoystickInstanceID = SDL.SDL_JoystickInstanceID(joystickHandle); | ||||||
| 
 | 
 | ||||||
| 			AnyPressed = false; | 			AnyPressed = false; | ||||||
| 
 | 
 | ||||||
| 			A = new GamepadButton(handle, GamepadButtonCode.A, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A); | 			A = new GamepadButton(this, GamepadButtonCode.A, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A); | ||||||
| 			B = new GamepadButton(handle, GamepadButtonCode.B, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B); | 			B = new GamepadButton(this, GamepadButtonCode.B, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B); | ||||||
| 			X = new GamepadButton(handle, GamepadButtonCode.X, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X); | 			X = new GamepadButton(this, GamepadButtonCode.X, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X); | ||||||
| 			Y = new GamepadButton(handle, GamepadButtonCode.Y, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y); | 			Y = new GamepadButton(this, GamepadButtonCode.Y, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y); | ||||||
| 
 | 
 | ||||||
| 			Back = new GamepadButton(handle, GamepadButtonCode.Back, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK); | 			Back = new GamepadButton(this, GamepadButtonCode.Back, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK); | ||||||
| 			Guide = new GamepadButton(handle, GamepadButtonCode.Guide, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_GUIDE); | 			Guide = new GamepadButton(this, GamepadButtonCode.Guide, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_GUIDE); | ||||||
| 			Start = new GamepadButton(handle, GamepadButtonCode.Start, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START); | 			Start = new GamepadButton(this, GamepadButtonCode.Start, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START); | ||||||
| 
 | 
 | ||||||
| 			LeftStick = new GamepadButton(handle, GamepadButtonCode.LeftStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK); | 			LeftStick = new GamepadButton(this, GamepadButtonCode.LeftStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK); | ||||||
| 			RightStick = new GamepadButton(handle, GamepadButtonCode.RightStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSTICK); | 			RightStick = new GamepadButton(this, GamepadButtonCode.RightStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSTICK); | ||||||
| 
 | 
 | ||||||
| 			LeftShoulder = new GamepadButton(handle, GamepadButtonCode.LeftShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER); | 			LeftShoulder = new GamepadButton(this, GamepadButtonCode.LeftShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER); | ||||||
| 			RightShoulder = new GamepadButton(handle, GamepadButtonCode.RightShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); | 			RightShoulder = new GamepadButton(this, GamepadButtonCode.RightShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); | ||||||
| 
 | 
 | ||||||
| 			DpadUp = new GamepadButton(handle, GamepadButtonCode.DpadUp, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP); | 			DpadUp = new GamepadButton(this, GamepadButtonCode.DpadUp, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP); | ||||||
| 			DpadDown = new GamepadButton(handle, GamepadButtonCode.DpadDown, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN); | 			DpadDown = new GamepadButton(this, GamepadButtonCode.DpadDown, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN); | ||||||
| 			DpadLeft = new GamepadButton(handle, GamepadButtonCode.DpadLeft, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT); | 			DpadLeft = new GamepadButton(this, GamepadButtonCode.DpadLeft, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT); | ||||||
| 			DpadRight = new GamepadButton(handle, GamepadButtonCode.DpadRight, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT); | 			DpadRight = new GamepadButton(this, GamepadButtonCode.DpadRight, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT); | ||||||
| 
 | 
 | ||||||
| 			LeftX = new Axis(handle, AxisCode.LeftX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX); | 			LeftX = new Axis(this, AxisCode.LeftX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX); | ||||||
| 			LeftY = new Axis(handle, AxisCode.LeftY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY); | 			LeftY = new Axis(this, AxisCode.LeftY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY); | ||||||
| 			RightX = new Axis(handle, AxisCode.RightX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTX); | 			RightX = new Axis(this, AxisCode.RightX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTX); | ||||||
| 			RightY = new Axis(handle, AxisCode.RightY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTY); | 			RightY = new Axis(this, AxisCode.RightY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTY); | ||||||
| 
 | 
 | ||||||
| 			LeftXLeft = new AxisButton(LeftX, false); | 			LeftXLeft = new AxisButton(LeftX, false); | ||||||
| 			LeftXRight = new AxisButton(LeftX, true); | 			LeftXRight = new AxisButton(LeftX, true); | ||||||
|  | @ -103,8 +108,8 @@ namespace MoonWorks.Input | ||||||
| 			RightYUp = new AxisButton(RightY, false); | 			RightYUp = new AxisButton(RightY, false); | ||||||
| 			RightYDown = new AxisButton(RightY, true); | 			RightYDown = new AxisButton(RightY, true); | ||||||
| 
 | 
 | ||||||
| 			TriggerLeft = new Trigger(handle, TriggerCode.Left, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT); | 			TriggerLeft = new Trigger(this, TriggerCode.Left, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT); | ||||||
| 			TriggerRight = new Trigger(handle, TriggerCode.Right, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT); | 			TriggerRight = new Trigger(this, TriggerCode.Right, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT); | ||||||
| 
 | 
 | ||||||
| 			TriggerLeftButton = new TriggerButton(TriggerLeft); | 			TriggerLeftButton = new TriggerButton(TriggerLeft); | ||||||
| 			TriggerRightButton = new TriggerButton(TriggerRight); | 			TriggerRightButton = new TriggerButton(TriggerRight); | ||||||
|  |  | ||||||
|  | @ -24,16 +24,10 @@ namespace MoonWorks.Input | ||||||
| 
 | 
 | ||||||
| 			gamepads = new Gamepad[MAX_GAMEPADS]; | 			gamepads = new Gamepad[MAX_GAMEPADS]; | ||||||
| 
 | 
 | ||||||
| 			for (var i = 0; i < 4; i += 1) | 			// initialize dummy controllers | ||||||
|  | 			for (var slot = 0; slot < MAX_GAMEPADS; slot += 1) | ||||||
| 			{ | 			{ | ||||||
| 				if (SDL.SDL_IsGameController(i) == SDL.SDL_bool.SDL_TRUE) | 				gamepads[slot] = new Gamepad(IntPtr.Zero, slot); | ||||||
| 				{ |  | ||||||
| 					gamepads[i] = new Gamepad(SDL.SDL_GameControllerOpen(i), i); |  | ||||||
| 				} |  | ||||||
| 				else |  | ||||||
| 				{ |  | ||||||
| 					gamepads[i] = new Gamepad(IntPtr.Zero, -1); |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -74,14 +68,49 @@ namespace MoonWorks.Input | ||||||
| 
 | 
 | ||||||
| 		public bool GamepadExists(int slot) | 		public bool GamepadExists(int slot) | ||||||
| 		{ | 		{ | ||||||
|  | 			if (slot < 0 || slot >= MAX_GAMEPADS) | ||||||
|  | 			{ | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			return !gamepads[slot].IsDummy; | 			return !gamepads[slot].IsDummy; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		// From 0-4 | ||||||
| 		public Gamepad GetGamepad(int slot) | 		public Gamepad GetGamepad(int slot) | ||||||
| 		{ | 		{ | ||||||
| 			return gamepads[slot]; | 			return gamepads[slot]; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		internal void AddGamepad(int index) | ||||||
|  | 		{ | ||||||
|  | 			for (var slot = 0; slot < MAX_GAMEPADS; slot += 1) | ||||||
|  | 			{ | ||||||
|  | 				if (!GamepadExists(slot)) | ||||||
|  | 				{ | ||||||
|  | 					gamepads[slot].Handle = SDL.SDL_GameControllerOpen(index); | ||||||
|  | 					System.Console.WriteLine($"Gamepad added to slot {slot}!"); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			System.Console.WriteLine("Too many gamepads already!"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		internal void RemoveGamepad(int joystickInstanceID) | ||||||
|  | 		{ | ||||||
|  | 			for (int slot = 0; slot < MAX_GAMEPADS; slot += 1) | ||||||
|  | 			{ | ||||||
|  | 				if (joystickInstanceID == gamepads[slot].JoystickInstanceID) | ||||||
|  | 				{ | ||||||
|  | 					SDL.SDL_GameControllerClose(gamepads[slot].Handle); | ||||||
|  | 					gamepads[slot].Handle = IntPtr.Zero; | ||||||
|  | 					System.Console.WriteLine($"Removing gamepad from slot {slot}!"); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		internal static void OnTextInput(char c) | 		internal static void OnTextInput(char c) | ||||||
| 		{ | 		{ | ||||||
| 			if (TextInput != null) | 			if (TextInput != null) | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| using System; |  | ||||||
| using MoonWorks.Math; | using MoonWorks.Math; | ||||||
| using SDL2; | using SDL2; | ||||||
| 
 | 
 | ||||||
|  | @ -6,7 +5,7 @@ namespace MoonWorks.Input | ||||||
| { | { | ||||||
| 	public class Trigger | 	public class Trigger | ||||||
| 	{ | 	{ | ||||||
| 		public IntPtr GamepadHandle; | 		public Gamepad Parent { get; } | ||||||
| 		public SDL.SDL_GameControllerAxis SDL_Axis; | 		public SDL.SDL_GameControllerAxis SDL_Axis; | ||||||
| 
 | 
 | ||||||
| 		public TriggerCode Code { get; } | 		public TriggerCode Code { get; } | ||||||
|  | @ -17,11 +16,11 @@ namespace MoonWorks.Input | ||||||
| 		public float Value { get; private set; } | 		public float Value { get; private set; } | ||||||
| 
 | 
 | ||||||
| 		public Trigger( | 		public Trigger( | ||||||
| 			IntPtr gamepadHandle, | 			Gamepad parent, | ||||||
| 			TriggerCode code, | 			TriggerCode code, | ||||||
| 			SDL.SDL_GameControllerAxis sdlAxis | 			SDL.SDL_GameControllerAxis sdlAxis | ||||||
| 		) { | 		) { | ||||||
| 			GamepadHandle = gamepadHandle; | 			Parent = parent; | ||||||
| 			Code = code; | 			Code = code; | ||||||
| 			SDL_Axis = sdlAxis; | 			SDL_Axis = sdlAxis; | ||||||
| 		} | 		} | ||||||
|  | @ -29,7 +28,7 @@ namespace MoonWorks.Input | ||||||
| 		internal void Update() | 		internal void Update() | ||||||
| 		{ | 		{ | ||||||
| 			Value = MathHelper.Normalize( | 			Value = MathHelper.Normalize( | ||||||
| 				SDL.SDL_GameControllerGetAxis(GamepadHandle, SDL_Axis), | 				SDL.SDL_GameControllerGetAxis(Parent.Handle, SDL_Axis), | ||||||
| 				0, short.MaxValue, | 				0, short.MaxValue, | ||||||
| 				0, 1 | 				0, 1 | ||||||
| 			); | 			); | ||||||
|  |  | ||||||
|  | @ -1,25 +1,23 @@ | ||||||
| using System; |  | ||||||
| using SDL2; | using SDL2; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Input | namespace MoonWorks.Input | ||||||
| { | { | ||||||
| 	public class GamepadButton : VirtualButton | 	public class GamepadButton : VirtualButton | ||||||
| 	{ | 	{ | ||||||
| 		IntPtr GamepadHandle; | 		public Gamepad Parent { get; } | ||||||
| 		SDL.SDL_GameControllerButton SDL_Button; | 		SDL.SDL_GameControllerButton SDL_Button; | ||||||
|  | 		public GamepadButtonCode Code { get; } | ||||||
| 
 | 
 | ||||||
| 		public GamepadButtonCode Code { get; private set; } | 		internal GamepadButton(Gamepad parent, GamepadButtonCode code, SDL.SDL_GameControllerButton sdlButton) | ||||||
| 
 |  | ||||||
| 		internal GamepadButton(IntPtr gamepadHandle, GamepadButtonCode code, SDL.SDL_GameControllerButton sdlButton) |  | ||||||
| 		{ | 		{ | ||||||
| 			GamepadHandle = gamepadHandle; | 			Parent = parent; | ||||||
| 			Code = code; | 			Code = code; | ||||||
| 			SDL_Button = sdlButton; | 			SDL_Button = sdlButton; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		internal override bool CheckPressed() | 		internal override bool CheckPressed() | ||||||
| 		{ | 		{ | ||||||
| 			return MoonWorks.Conversions.ByteToBool(SDL.SDL_GameControllerGetButton(GamepadHandle, SDL_Button)); | 			return MoonWorks.Conversions.ByteToBool(SDL.SDL_GameControllerGetButton(Parent.Handle, SDL_Button)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue