static decimal GetAxisMapPoints(string axis, string up = null, string down = null) { var points = 0m; MapType type; int index; if (SettingsConverter.TryParseIniValue(axis, out type, out index)) { // If proper axis mapped then give full point. points += 1m; } else { // For every map 0.25 points. if (SettingsConverter.TryParseIniValue(up, out type, out index)) { points += 0.25m; } if (SettingsConverter.TryParseIniValue(down, out type, out index)) { points += 0.25m; } } return(points); }
/// <summary> /// Calculate map completion percent based on user device (controller) capabilities. /// </summary> public static int GetCompletionPoints(PadSetting ps, UserDevice ud = null) { // Xbox 360 Controller have 6 axis. Use device count if less. var maxAxis = ud != null && ud.CapAxeCount > 0 && ud.CapAxeCount < 6m ? ud.CapAxeCount : 6m; // Xbox 360 Controller have 14 buttons. Use device count if less. var maxButtons = ud != null && ud.CapButtonCount > 0 && ud.CapButtonCount < 14m ? ud.CapButtonCount : 14m; // Use device motor count. var maxMotors = ud != null ? ud.DiActuatorMask : 0m; var motorPoints = 0m; // If force feedback enabled then... if (ps.ForceEnable == "1") { // Give all available points. motorPoints = maxMotors; } // Count axis points (maximum 6 points). var axisPoints = 0m; axisPoints += GetAxisMapPoints(ps.LeftThumbAxisX, ps.LeftThumbLeft, ps.LeftThumbRight); axisPoints += GetAxisMapPoints(ps.LeftThumbAxisY, ps.LeftThumbUp, ps.LeftThumbDown); axisPoints += GetAxisMapPoints(ps.RightThumbAxisX, ps.RightThumbLeft, ps.RightThumbRight); axisPoints += GetAxisMapPoints(ps.RightThumbAxisY, ps.RightThumbUp, ps.RightThumbDown); axisPoints += GetAxisMapPoints(ps.LeftTrigger); axisPoints += GetAxisMapPoints(ps.RightTrigger); // Count button points (maximum 14 points). var buttonPoints = 0m; MapType type; int index; if (SettingsConverter.TryParseIniValue(ps.ButtonA, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.ButtonB, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.ButtonX, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.ButtonY, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.ButtonBack, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.ButtonStart, out type, out index)) { buttonPoints += 1m; } // If DPad is properly mapped to POV then... if (SettingsConverter.TryParseIniValue(ps.DPadDown, out type, out index) && type == MapType.POV) { // Add 4 points. buttonPoints += 4m; } else { // Add point for each button. if (SettingsConverter.TryParseIniValue(ps.DPadUp, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.DPadDown, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.DPadLeft, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.DPadRight, out type, out index)) { buttonPoints += 1m; } } if (SettingsConverter.TryParseIniValue(ps.LeftThumbButton, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.RightThumbButton, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.LeftShoulder, out type, out index)) { buttonPoints += 1m; } if (SettingsConverter.TryParseIniValue(ps.RightShoulder, out type, out index)) { buttonPoints += 1m; } // Calculate completion percent. var completion = (int)(100m * ( (axisPoints + buttonPoints + motorPoints) / (maxAxis + maxButtons + maxMotors) )); return(completion); }
/// <summary> /// Convert DiStates to XInput states. /// </summary> void UpdateXiStates() { // Get all mapped devices. var settings = SettingsManager.UserSettings.ItemsToArraySyncronized() .Where(x => x.MapTo > (int)MapTo.None) .ToArray(); for (int i = 0; i < settings.Length; i++) { var setting = settings[i]; var ud = SettingsManager.GetDevice(setting.InstanceGuid); // If device was not found then continue. if (ud == null) { continue; } // Create GamePad to map to. var gp = new Gamepad(); // Assing state with default values. setting.XiState = gp; // If device Direct Input state failed then... if (ud.JoState == null) { continue; } // If device is offline then continue. if (!ud.IsOnline) { continue; } //// If device is not set or test device then... //var device = ud.Device; //if (device == null) // // Continue loop. // continue; var padSetting = SettingsManager.GetPadSetting(setting.PadSettingChecksum); // If setting was not found then continue. if (padSetting == null) { continue; } var diState = ud.DiState; // If custom directInput state is not available then continue. if (diState == null) { continue; } bool success; int index; SettingType type; // -------------------------------------------------------- // Convert DInput POV Hat value to D-PAD buttons. // -------------------------------------------------------- // Create array to store 4 buttons for each POV. var dPadButtons = new bool[4 * diState.Povs.Length]; // Loop trough D-Pad button states. for (int d = 0; d < diState.Povs.Length; ++d) { // Get degree value from the POV. int povdeg = diState.Povs[d]; // If POV is pressed into one of the directions then... if (povdeg >= 0) { // Split PoV degrees into 8 groups by // converting PoV degree from 0 to 36000 to number from 0 to 7. // This will allow to have more flexible degree values mapped to buttons. var y = ((2250 + povdeg) / 4500) % 8; // XINPUT_GAMEPAD_DPAD_UP dPadButtons[d * 4 + 0] = (y >= 0 && y <= 1) || y == 7; // XINPUT_GAMEPAD_DPAD_RIGHT dPadButtons[d * 4 + 1] = (y >= 1 && y <= 3); // XINPUT_GAMEPAD_DPAD_DOWN dPadButtons[d * 4 + 2] = (y >= 3 && y <= 5); // XINPUT_GAMEPAD_DPAD_LEFT dPadButtons[d * 4 + 3] = (y >= 5 && y <= 7); } } // -------------------------------------------------------- // MAP: D-PAD // -------------------------------------------------------- success = SettingsConverter.TryParseIniValue(padSetting.DPad, out type, out index); // If POV index is mapped to the D-PAD if (success && index > 0 && type == SettingType.POV) { var dPadIndex = index - 1; // -------------------------------------------------------- // Target: Button (DPad). // -------------------------------------------------------- if (dPadButtons[dPadIndex * 4 + 0]) { gp.Buttons |= GamepadButtonFlags.DPadUp; } if (dPadButtons[dPadIndex * 4 + 1]) { gp.Buttons |= GamepadButtonFlags.DPadRight; } if (dPadButtons[dPadIndex * 4 + 2]) { gp.Buttons |= GamepadButtonFlags.DPadDown; } if (dPadButtons[dPadIndex * 4 + 3]) { gp.Buttons |= GamepadButtonFlags.DPadLeft; } } // -------------------------------------------------------- // MAP: // -------------------------------------------------------- // Get all mapped items. var maps = padSetting.Maps; foreach (var map in maps) { // If not mapped then continue. if (map.Index == 0) { continue; } // -------------------------------------------------------- // MAP Source: Button // -------------------------------------------------------- if (map.IsButton) { // If mapped index is in range then... if (map.Index < diState.Buttons.Length) { var pressed = diState.Buttons[map.Index - 1]; if (pressed) { // -------------------------------------------------------- // Target: Button. // -------------------------------------------------------- if (map.Target == TargetType.Button) { gp.Buttons |= map.ButtonFlag; } // -------------------------------------------------------- // Target: Trigger. // -------------------------------------------------------- else if (map.Target == TargetType.LeftTrigger) { gp.LeftTrigger = byte.MaxValue; } else if (map.Target == TargetType.RightTrigger) { gp.RightTrigger = byte.MaxValue; } // -------------------------------------------------------- // Target: Thumb. // -------------------------------------------------------- else if (map.Target == TargetType.LeftThumbX) { gp.LeftThumbX = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } else if (map.Target == TargetType.LeftThumbY) { gp.LeftThumbY = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } else if (map.Target == TargetType.RightThumbX) { gp.RightThumbX = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } else if (map.Target == TargetType.RightThumbY) { gp.RightThumbY = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } // -------------------------------------------------------- // Target: Max. // -------------------------------------------------------- } } } // -------------------------------------------------------- // MAP Source: D-PAD button converted from POV. // -------------------------------------------------------- else if (map.Type == SettingType.POV) { // -------------------------------------------------------- // Target: POV. // -------------------------------------------------------- if (map.Target == TargetType.Button) { //gp.Buttons |= map.ButtonFlag; } } // -------------------------------------------------------- // MAP Source: D-PAD button converted from POV. // -------------------------------------------------------- else if (map.Type == SettingType.DPOVButton) { // If mapped index is in range then... if (map.Index < dPadButtons.Length) { var pressed = dPadButtons[map.Index - 1]; if (pressed) { // -------------------------------------------------------- // Target: Button. // -------------------------------------------------------- if (map.Target == TargetType.Button) { gp.Buttons |= map.ButtonFlag; } // -------------------------------------------------------- // Target: Trigger. // -------------------------------------------------------- else if (map.Target == TargetType.LeftTrigger) { gp.LeftTrigger = byte.MaxValue; } else if (map.Target == TargetType.RightTrigger) { gp.RightTrigger = byte.MaxValue; } // -------------------------------------------------------- // Target: Thumb. // -------------------------------------------------------- else if (map.Target == TargetType.LeftThumbX) { gp.LeftThumbX = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } else if (map.Target == TargetType.LeftThumbY) { gp.LeftThumbY = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } else if (map.Target == TargetType.RightThumbX) { gp.RightThumbX = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } else if (map.Target == TargetType.RightThumbY) { gp.RightThumbY = map.AxisValue.HasValue ? map.IsInverted ? (short)0 : map.AxisValue.Value : map.IsInverted ? short.MinValue : short.MaxValue; } } } } // -------------------------------------------------------- // MAP Source: Axis or Slider. // -------------------------------------------------------- else if (map.IsAxis || map.IsSlider) { // Get source value. int[] values = map.IsAxis ? diState.Axis : diState.Sliders; // If index is out of range then... if (map.Index > values.Length) { continue; } // Get value. var v = (ushort)values[map.Index - 1]; //// -------------------------------------------------------- //// MAP: Axis Positive / Negative Map. //// -------------------------------------------------------- //if (map.Target == TargetType.LeftThumbX) //{ // var success2 = SettingsConverter.TryParseIniValue(padSetting.LeftThumbUp, out type, out index); // if (success2 && index > 0 && type == SettingType.Button) // { // } //} // Destination range. //var min = short.MinValue; // -32768; //var max = short.MaxValue; // 32767; /// If half value (H) then... //else if (!map.IsInverted && map.IsHalf) //{ // // If value is in [32768;65535] range then... // v = (v > max) // // Convert [32768;65535] range to [0;65535] range. // ? (ushort)ConvertHelper.ConvertRange(max + 1, ushort.MaxValue, ushort.MinValue, ushort.MaxValue, v) // : (ushort)0; //} // If inverted half value (IH) then... //else if (map.IsInverted && map.IsHalf) //{ // // If value is in [0;32767] range then... // v = (v <= max) // // Convert [32767;0] range to [0;65535] range. // ? (ushort)ConvertHelper.ConvertRange(max, 0, ushort.MinValue, ushort.MaxValue, v) // : (ushort)0; //} // -------------------------------------------------------- // Target: Button. // -------------------------------------------------------- if (map.Target == TargetType.Button) { // If value is inverted (I) then... if (map.IsInverted) { // Convert [0;65535] range to [65535;0] range. v = (ushort)(ushort.MaxValue - v); } // If value is inverted (I) then... if (map.IsHalf) { // Map only if [32768;65535]; if (v > short.MaxValue) { v = (ushort)(v + short.MinValue); } else { v = 0; } } // If axis reached beyond dead zone then... if (v > map.DeadZone) { gp.Buttons |= map.ButtonFlag; } } // -------------------------------------------------------- // Target: Trigger. // -------------------------------------------------------- else if (map.Target == TargetType.LeftTrigger || map.Target == TargetType.RightTrigger) { var triggerValue = (byte)ConvertHelper.GetThumbValue(v, map.DeadZone, map.AntiDeadZone, map.Linear, map.IsInverted, map.IsHalf, false); if (map.Target == TargetType.LeftTrigger) { gp.LeftTrigger = triggerValue; } if (map.Target == TargetType.RightTrigger) { gp.RightTrigger = triggerValue; } } // -------------------------------------------------------- // Target: Thumb. // -------------------------------------------------------- else if (map.Target != TargetType.None) { var thumbValue = (short)ConvertHelper.GetThumbValue(v, map.DeadZone, map.AntiDeadZone, map.Linear, map.IsInverted, map.IsHalf); if (map.Target == TargetType.LeftThumbX) { gp.LeftThumbX = thumbValue; } if (map.Target == TargetType.LeftThumbY) { gp.LeftThumbY = thumbValue; } if (map.Target == TargetType.RightThumbX) { gp.RightThumbX = thumbValue; } if (map.Target == TargetType.RightThumbY) { gp.RightThumbY = thumbValue; } } } } setting.XiState = gp; // [ 32768 steps | 32768 steps ] // ushort [ 0 32767 | 32768 65535 ] DInput // short [ -32768 -1 | 0 32767 ] XInput // [ 128 steps | 128 steps ] // byte [ 0 127 | 128 255 ] // sbyte [ -128 -1 | 0 127 ] // From Button: OFF | ON // From Axis : 0 - D - 65535 (D - DeadZone) // To Button: OFF | ON // From IAxis: 65535 - 0 x = uint.Max - x; // From HAxis: 32768 - 65535 map only if x > 32768; x = (x - 32768) * 2 + 1; // From IHAxis: 32767 - 0 map only if x <= 32767; x = (32767 - x) * 2 + 1; // From Axis: 0 - 65535 x = x; // To Triger: 0 - 255 scale: 255 // To Axis: -32768 - 32767 shift: -32768 } var ev = StatesUpdated; if (ev != null) { ev(this, new DInputEventArgs()); } }