/// <summary> /// Applies button re-mapping to the supplied report. /// </summary> /// <param name="report">The report to manipulate.</param> public void Remap(ScpHidReport report) { // skip disabled mapping if (!IsEnabled) { return; } switch (MappingTarget.CommandType) { case CommandType.GamepadButton: foreach (var button in SourceButtons) { // turbo is special, apply first if (Turbo.IsEnabled) { Turbo.ApplyOn(report, button); } // get target button IDsButton target = MappingTarget.CommandTarget as Ds3Button; // if target is no valid button or none, skip setting it if (target == null) { continue; } // if it's a DS4, translate button if (report.Model == DsModel.DS4) { target = Ds4Button.Buttons.First(b => b.Name.Equals(target.Name)); } // if original isn't pressed we can ignore if (!report[button].IsPressed) { continue; } // unset original button report.Unset(button); // set new button report.Set(target); } break; } }
/// <summary> /// Applies turbo algorithm for a specified <see cref="IDsButton" /> on a given <see cref="ScpHidReport" />. /// </summary> /// <param name="report">The HID report to manipulate.</param> /// <param name="button">The button to trigger turbo on.</param> public void ApplyOn(ScpHidReport report, IDsButton button) { // button type must match model, madness otherwise! if ((report.Model != DsModel.DS3 || !(button is Ds3Button)) && (report.Model != DsModel.DS4 || !(button is Ds4Button))) return; // if button got released... if (_isActive && !report[button].IsPressed) { // ...disable, reset and return _isActive = false; _delayedFrame.Reset(); _engagedFrame.Reset(); _releasedFrame.Reset(); return; } // if turbo is enabled and button is pressed... if (!_isActive && report[button].IsPressed) { // ...start calculating the activation delay... if (!_delayedFrame.IsRunning) _delayedFrame.Restart(); // ...if we are still activating, don't do anything if (_delayedFrame.ElapsedMilliseconds < Delay) return; // time to activate! _isActive = true; _delayedFrame.Reset(); } // if the button was released... if (!report[button].IsPressed) { // ...restore default states and skip processing _isActive = false; return; } // reset engaged ("keep pressed") time frame... if (!_engagedFrame.IsRunning) _engagedFrame.Restart(); // ...do not change state while within frame and button is still pressed, then skip if (_engagedFrame.ElapsedMilliseconds < Interval && report[button].IsPressed) return; // reset released time frame ("forecefully release") for button if (!_releasedFrame.IsRunning) _releasedFrame.Restart(); // while we're still within the released time frame... if (_releasedFrame.ElapsedMilliseconds < Release) { // ...re-set the button state to released report.Unset(button); } else { // all frames passed, reset and start over _isActive = false; _delayedFrame.Stop(); _engagedFrame.Stop(); _releasedFrame.Stop(); } }
/// <summary> /// Applies button re-mapping to the supplied report. /// </summary> /// <param name="report">The report to manipulate.</param> public void Remap(ScpHidReport report) { // skip disabled mapping if (!IsEnabled) return; switch (MappingTarget.CommandType) { case CommandType.GamepadButton: foreach (var button in SourceButtons) { // turbo is special, apply first if (Turbo.IsEnabled) { Turbo.ApplyOn(report, button); } // get target button IDsButton target = MappingTarget.CommandTarget as Ds3Button; // if target is no valid button or none, skip setting it if (target == null) continue; // if it's a DS4, translate button if (report.Model == DsModel.DS4) { target = Ds4Button.Buttons.First(b => b.Name.Equals(target.Name)); } // if original isn't pressed we can ignore if (!report[button].IsPressed) continue; // unset original button report.Unset(button); // set new button report.Set(target); } break; case CommandType.Keystrokes: foreach (var button in SourceButtons) { var target = (VirtualKeyCode) Enum.ToObject(typeof(VirtualKeyCode), MappingTarget.CommandTarget); if (report[button].IsPressed) { VirtualInput.Keyboard.KeyDown(target); } else { VirtualInput.Keyboard.KeyUp(target); } } break; } }
/// <summary> /// Applies turbo algorithm for a specified <see cref="IDsButton" /> on a given <see cref="ScpHidReport" />. /// </summary> /// <param name="report">The HID report to manipulate.</param> /// <param name="button">The button to trigger turbo on.</param> public void ApplyOn(ScpHidReport report, IDsButton button) { // button type must match model, madness otherwise! if ((report.Model != DsModel.DS3 || !(button is Ds3Button)) && (report.Model != DsModel.DS4 || !(button is Ds4Button))) { return; } // if button got released... if (_isActive && !report[button].IsPressed) { // ...disable, reset and return _isActive = false; _delayedFrame.Reset(); _engagedFrame.Reset(); _releasedFrame.Reset(); return; } // if turbo is enabled and button is pressed... if (!_isActive && report[button].IsPressed) { // ...start calculating the activation delay... if (!_delayedFrame.IsRunning) { _delayedFrame.Restart(); } // ...if we are still activating, don't do anything if (_delayedFrame.ElapsedMilliseconds < Delay) { return; } // time to activate! _isActive = true; _delayedFrame.Reset(); } // if the button was released... if (!report[button].IsPressed) { // ...restore default states and skip processing _isActive = false; return; } // reset engaged ("keep pressed") time frame... if (!_engagedFrame.IsRunning) { _engagedFrame.Restart(); } // ...do not change state while within frame and button is still pressed, then skip if (_engagedFrame.ElapsedMilliseconds < Interval && report[button].IsPressed) { return; } // reset released time frame ("forecefully release") for button if (!_releasedFrame.IsRunning) { _releasedFrame.Restart(); } // while we're still within the released time frame... if (_releasedFrame.ElapsedMilliseconds < Release) { // ...re-set the button state to released report.Unset(button); } else { // all frames passed, reset and start over _isActive = false; _delayedFrame.Stop(); _engagedFrame.Stop(); _releasedFrame.Stop(); } }