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: | ||||
| 						HandleFileDrop(_event); | ||||
| 						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); | ||||
| 		} | ||||
| 
 | ||||
| 		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() | ||||
| 		{ | ||||
| 			long currentTicks = gameTimer.Elapsed.Ticks; | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| using System; | ||||
| using MoonWorks.Math; | ||||
| using SDL2; | ||||
| 
 | ||||
|  | @ -6,7 +5,7 @@ namespace MoonWorks.Input | |||
| { | ||||
| 	public class Axis | ||||
| 	{ | ||||
| 		IntPtr GamepadHandle; | ||||
| 		public Gamepad Parent { get; } | ||||
| 		SDL.SDL_GameControllerAxis SDL_Axis; | ||||
| 
 | ||||
| 		public AxisCode Code { get; private set; } | ||||
|  | @ -17,11 +16,11 @@ namespace MoonWorks.Input | |||
| 		public float Value { get; private set; } | ||||
| 
 | ||||
| 		public Axis( | ||||
| 			IntPtr gamepadHandle, | ||||
| 			Gamepad parent, | ||||
| 			AxisCode code, | ||||
| 			SDL.SDL_GameControllerAxis sdlAxis | ||||
| 		) { | ||||
| 			GamepadHandle = gamepadHandle; | ||||
| 			Parent = parent; | ||||
| 			SDL_Axis = sdlAxis; | ||||
| 			Code = code; | ||||
| 		} | ||||
|  | @ -29,7 +28,7 @@ namespace MoonWorks.Input | |||
| 		internal void Update() | ||||
| 		{ | ||||
| 			Value = MathHelper.Normalize( | ||||
| 				SDL.SDL_GameControllerGetAxis(GamepadHandle, SDL_Axis), | ||||
| 				SDL.SDL_GameControllerGetAxis(Parent.Handle, SDL_Axis), | ||||
| 				short.MinValue, short.MaxValue, | ||||
| 				-1, 1 | ||||
| 			); | ||||
|  |  | |||
|  | @ -8,7 +8,9 @@ namespace MoonWorks.Input | |||
| 	public class Gamepad | ||||
| 	{ | ||||
| 		internal IntPtr Handle; | ||||
| 		internal int Index; | ||||
| 		internal int JoystickInstanceID; | ||||
| 
 | ||||
| 		public int Slot { get; internal set; } | ||||
| 
 | ||||
| 		public GamepadButton A { get; } | ||||
| 		public GamepadButton B { get; } | ||||
|  | @ -61,37 +63,40 @@ namespace MoonWorks.Input | |||
| 
 | ||||
| 		private VirtualButton[] VirtualButtons; | ||||
| 
 | ||||
| 		internal Gamepad(IntPtr handle, int index) | ||||
| 		internal Gamepad(IntPtr handle, int slot) | ||||
| 		{ | ||||
| 			Handle = handle; | ||||
| 			Index = index; | ||||
| 			Slot = slot; | ||||
| 
 | ||||
| 			IntPtr joystickHandle = SDL.SDL_GameControllerGetJoystick(Handle); | ||||
| 			JoystickInstanceID = SDL.SDL_JoystickInstanceID(joystickHandle); | ||||
| 
 | ||||
| 			AnyPressed = false; | ||||
| 
 | ||||
| 			A = new GamepadButton(handle, GamepadButtonCode.A, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A); | ||||
| 			B = new GamepadButton(handle, GamepadButtonCode.B, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B); | ||||
| 			X = new GamepadButton(handle, GamepadButtonCode.X, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X); | ||||
| 			Y = new GamepadButton(handle, GamepadButtonCode.Y, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y); | ||||
| 			A = new GamepadButton(this, GamepadButtonCode.A, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A); | ||||
| 			B = new GamepadButton(this, GamepadButtonCode.B, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B); | ||||
| 			X = new GamepadButton(this, GamepadButtonCode.X, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X); | ||||
| 			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); | ||||
| 			Guide = new GamepadButton(handle, GamepadButtonCode.Guide, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_GUIDE); | ||||
| 			Start = new GamepadButton(handle, GamepadButtonCode.Start, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START); | ||||
| 			Back = new GamepadButton(this, GamepadButtonCode.Back, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK); | ||||
| 			Guide = new GamepadButton(this, GamepadButtonCode.Guide, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_GUIDE); | ||||
| 			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); | ||||
| 			RightStick = new GamepadButton(handle, GamepadButtonCode.RightStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSTICK); | ||||
| 			LeftStick = new GamepadButton(this, GamepadButtonCode.LeftStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK); | ||||
| 			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); | ||||
| 			RightShoulder = new GamepadButton(handle, GamepadButtonCode.RightShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); | ||||
| 			LeftShoulder = new GamepadButton(this, GamepadButtonCode.LeftShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER); | ||||
| 			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); | ||||
| 			DpadDown = new GamepadButton(handle, GamepadButtonCode.DpadDown, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN); | ||||
| 			DpadLeft = new GamepadButton(handle, GamepadButtonCode.DpadLeft, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT); | ||||
| 			DpadRight = new GamepadButton(handle, GamepadButtonCode.DpadRight, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT); | ||||
| 			DpadUp = new GamepadButton(this, GamepadButtonCode.DpadUp, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP); | ||||
| 			DpadDown = new GamepadButton(this, GamepadButtonCode.DpadDown, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN); | ||||
| 			DpadLeft = new GamepadButton(this, GamepadButtonCode.DpadLeft, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT); | ||||
| 			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); | ||||
| 			LeftY = new Axis(handle, AxisCode.LeftY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY); | ||||
| 			RightX = new Axis(handle, AxisCode.RightX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTX); | ||||
| 			RightY = new Axis(handle, AxisCode.RightY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTY); | ||||
| 			LeftX = new Axis(this, AxisCode.LeftX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX); | ||||
| 			LeftY = new Axis(this, AxisCode.LeftY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY); | ||||
| 			RightX = new Axis(this, AxisCode.RightX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTX); | ||||
| 			RightY = new Axis(this, AxisCode.RightY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTY); | ||||
| 
 | ||||
| 			LeftXLeft = new AxisButton(LeftX, false); | ||||
| 			LeftXRight = new AxisButton(LeftX, true); | ||||
|  | @ -103,8 +108,8 @@ namespace MoonWorks.Input | |||
| 			RightYUp = new AxisButton(RightY, false); | ||||
| 			RightYDown = new AxisButton(RightY, true); | ||||
| 
 | ||||
| 			TriggerLeft = new Trigger(handle, TriggerCode.Left, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT); | ||||
| 			TriggerRight = new Trigger(handle, TriggerCode.Right, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT); | ||||
| 			TriggerLeft = new Trigger(this, TriggerCode.Left, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT); | ||||
| 			TriggerRight = new Trigger(this, TriggerCode.Right, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT); | ||||
| 
 | ||||
| 			TriggerLeftButton = new TriggerButton(TriggerLeft); | ||||
| 			TriggerRightButton = new TriggerButton(TriggerRight); | ||||
|  |  | |||
|  | @ -24,16 +24,10 @@ namespace MoonWorks.Input | |||
| 
 | ||||
| 			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[i] = new Gamepad(SDL.SDL_GameControllerOpen(i), i); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					gamepads[i] = new Gamepad(IntPtr.Zero, -1); | ||||
| 				} | ||||
| 				gamepads[slot] = new Gamepad(IntPtr.Zero, slot); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -74,14 +68,49 @@ namespace MoonWorks.Input | |||
| 
 | ||||
| 		public bool GamepadExists(int slot) | ||||
| 		{ | ||||
| 			if (slot < 0 || slot >= MAX_GAMEPADS) | ||||
| 			{ | ||||
| 				return false; | ||||
| 			} | ||||
| 
 | ||||
| 			return !gamepads[slot].IsDummy; | ||||
| 		} | ||||
| 
 | ||||
| 		// From 0-4 | ||||
| 		public Gamepad GetGamepad(int 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) | ||||
| 		{ | ||||
| 			if (TextInput != null) | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| using System; | ||||
| using MoonWorks.Math; | ||||
| using SDL2; | ||||
| 
 | ||||
|  | @ -6,7 +5,7 @@ namespace MoonWorks.Input | |||
| { | ||||
| 	public class Trigger | ||||
| 	{ | ||||
| 		public IntPtr GamepadHandle; | ||||
| 		public Gamepad Parent { get; } | ||||
| 		public SDL.SDL_GameControllerAxis SDL_Axis; | ||||
| 
 | ||||
| 		public TriggerCode Code { get; } | ||||
|  | @ -17,11 +16,11 @@ namespace MoonWorks.Input | |||
| 		public float Value { get; private set; } | ||||
| 
 | ||||
| 		public Trigger( | ||||
| 			IntPtr gamepadHandle, | ||||
| 			Gamepad parent, | ||||
| 			TriggerCode code, | ||||
| 			SDL.SDL_GameControllerAxis sdlAxis | ||||
| 		) { | ||||
| 			GamepadHandle = gamepadHandle; | ||||
| 			Parent = parent; | ||||
| 			Code = code; | ||||
| 			SDL_Axis = sdlAxis; | ||||
| 		} | ||||
|  | @ -29,7 +28,7 @@ namespace MoonWorks.Input | |||
| 		internal void Update() | ||||
| 		{ | ||||
| 			Value = MathHelper.Normalize( | ||||
| 				SDL.SDL_GameControllerGetAxis(GamepadHandle, SDL_Axis), | ||||
| 				SDL.SDL_GameControllerGetAxis(Parent.Handle, SDL_Axis), | ||||
| 				0, short.MaxValue, | ||||
| 				0, 1 | ||||
| 			); | ||||
|  |  | |||
|  | @ -1,25 +1,23 @@ | |||
| using System; | ||||
| using SDL2; | ||||
| 
 | ||||
| namespace MoonWorks.Input | ||||
| { | ||||
| 	public class GamepadButton : VirtualButton | ||||
| 	{ | ||||
| 		IntPtr GamepadHandle; | ||||
| 		public Gamepad Parent { get; } | ||||
| 		SDL.SDL_GameControllerButton SDL_Button; | ||||
| 		public GamepadButtonCode Code { get; } | ||||
| 
 | ||||
| 		public GamepadButtonCode Code { get; private set; } | ||||
| 
 | ||||
| 		internal GamepadButton(IntPtr gamepadHandle, GamepadButtonCode code, SDL.SDL_GameControllerButton sdlButton) | ||||
| 		internal GamepadButton(Gamepad parent, GamepadButtonCode code, SDL.SDL_GameControllerButton sdlButton) | ||||
| 		{ | ||||
| 			GamepadHandle = gamepadHandle; | ||||
| 			Parent = parent; | ||||
| 			Code = code; | ||||
| 			SDL_Button = sdlButton; | ||||
| 		} | ||||
| 
 | ||||
| 		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