mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-13 11:20:31 +00:00
Merge remote-tracking branch 'upstream/HEAD' into dev
This commit is contained in:
@@ -117,10 +117,18 @@ namespace osu.Framework.Graphics.Transforms
|
||||
|
||||
protected void ComputeSingleValue(float dt, ref float current, ref float velocity, float target, float targetVelocity)
|
||||
{
|
||||
float k2Stable = MathF.Max(MathF.Max(k2, dt * dt / 2 + dt * k1 / 2), dt * k1);
|
||||
float k2Stable = MathF.Max(MathF.Max(k2, (dt * dt) / 2 + (dt * k1) / 2), dt * k1);
|
||||
|
||||
current += dt * velocity;
|
||||
velocity += (dt * (target + k3 * targetVelocity - current - k1 * velocity)) / k2Stable;
|
||||
velocity += (dt * (target + (k3 * targetVelocity) - current - (k1 * velocity))) / k2Stable;
|
||||
}
|
||||
|
||||
protected void ComputeSingleValue(float dt, ref double current, ref double velocity, double target, double targetVelocity)
|
||||
{
|
||||
float k2Stable = MathF.Max(MathF.Max(k2, (dt * dt) / 2 + (dt * k1) / 2), dt * k1);
|
||||
|
||||
current += dt * velocity;
|
||||
velocity += (dt * (target + (k3 * targetVelocity) - current - (k1 * velocity))) / k2Stable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +144,18 @@ namespace osu.Framework.Graphics.Transforms
|
||||
}
|
||||
}
|
||||
|
||||
public class DoubleSpring : Spring<double>
|
||||
{
|
||||
protected override double GetTargetVelocity(double target, double previousTarget, float dt) => (target - previousTarget) / dt;
|
||||
|
||||
protected override double ComputeNextValue(float dt, double target, double targetVelocity)
|
||||
{
|
||||
ComputeSingleValue(dt, ref Current, ref Velocity, target, targetVelocity);
|
||||
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public class Vector2Spring : Spring<Vector2>
|
||||
{
|
||||
protected override Vector2 GetTargetVelocity(Vector2 target, Vector2 previousTarget, float dt) => (target - previousTarget) / dt;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -44,7 +45,7 @@ namespace osu.Framework.Input.Handlers.Tablet
|
||||
|
||||
public Bindable<float> Rotation { get; } = new Bindable<float>();
|
||||
|
||||
public BindableFloat PressureThreshold { get; } = new BindableFloat(0.0f)
|
||||
public BindableFloat PressureThreshold { get; } = new BindableFloat
|
||||
{
|
||||
MinValue = 0f,
|
||||
MaxValue = 1f,
|
||||
@@ -119,7 +120,34 @@ namespace osu.Framework.Input.Handlers.Tablet
|
||||
enqueueInput(new MousePositionRelativeInputFromPen { Delta = new Vector2(delta.X, delta.Y), DeviceType = lastTabletDeviceType });
|
||||
}
|
||||
|
||||
void IPressureHandler.SetPressure(float percentage) => enqueueInput(new MouseButtonInputFromPen(percentage > PressureThreshold.Value) { DeviceType = lastTabletDeviceType });
|
||||
private bool penPressed;
|
||||
|
||||
void IPressureHandler.SetPressure(float pressure)
|
||||
{
|
||||
// Most important for edge cases where users have pressure set to 0 or 1 and tablets can report fuzzy data.
|
||||
const float hysteresis_half = 0.02f;
|
||||
|
||||
pressure = Math.Clamp(pressure, 0f, 1f);
|
||||
|
||||
float releaseThreshold = PressureThreshold.Value - hysteresis_half;
|
||||
float pressThreshold = PressureThreshold.Value + hysteresis_half;
|
||||
|
||||
// keep press..release threshold range constant for edge cases.
|
||||
if (releaseThreshold < 0f)
|
||||
{
|
||||
pressThreshold = hysteresis_half * 2;
|
||||
releaseThreshold = 0f;
|
||||
}
|
||||
else if (pressThreshold > 1f)
|
||||
{
|
||||
releaseThreshold = 1 - (hysteresis_half * 2);
|
||||
pressThreshold = 1f;
|
||||
}
|
||||
|
||||
setPressed(penPressed
|
||||
? pressure > releaseThreshold
|
||||
: pressure > pressThreshold);
|
||||
}
|
||||
|
||||
private void handleTabletsChanged(object? sender, IEnumerable<TabletReference> tablets)
|
||||
{
|
||||
@@ -135,7 +163,22 @@ namespace osu.Framework.Input.Handlers.Tablet
|
||||
updateOutputArea(host.Window);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure we don't leave the simulated mouse button pressed if the tablet disappears.
|
||||
setPressed(false);
|
||||
tablet.Value = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setPressed(bool pressed)
|
||||
{
|
||||
// Importantly, only fire input when the state changes.
|
||||
// If we fire more often, this may intefere with users that click with mouse but use tablet for positional input (hovering).
|
||||
if (pressed == penPressed)
|
||||
return;
|
||||
|
||||
enqueueInput(new MouseButtonInputFromPen(pressed) { DeviceType = lastTabletDeviceType });
|
||||
penPressed = pressed;
|
||||
}
|
||||
|
||||
private void handleDeviceReported(object? sender, IDeviceReport report)
|
||||
|
||||
@@ -275,8 +275,7 @@ namespace osu.Framework.Platform.SDL2
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_CONTROLLERDEVICEREMOVED:
|
||||
SDL_GameControllerClose(controllers[evtCdevice.which].ControllerHandle);
|
||||
controllers.Remove(evtCdevice.which);
|
||||
removeJoystick(evtCdevice.which);
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_CONTROLLERDEVICEREMAPPED:
|
||||
@@ -323,6 +322,20 @@ namespace osu.Framework.Platform.SDL2
|
||||
controllers[instanceID] = new SDL2ControllerBindings(joystick, controller);
|
||||
}
|
||||
|
||||
private void removeJoystick(int which)
|
||||
{
|
||||
int instanceID = SDL_JoystickGetDeviceInstanceID(which);
|
||||
|
||||
if (controllers.Remove(instanceID, out var controller))
|
||||
{
|
||||
if (controller.ControllerHandle != IntPtr.Zero)
|
||||
SDL_GameControllerClose(controller.ControllerHandle);
|
||||
|
||||
if (controller.JoystickHandle != IntPtr.Zero)
|
||||
SDL_JoystickClose(controller.JoystickHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates <see cref="controllers"/> with joysticks that are already connected.
|
||||
/// </summary>
|
||||
@@ -343,12 +356,7 @@ namespace osu.Framework.Platform.SDL2
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_JOYDEVICEREMOVED:
|
||||
// if the joystick is already closed, ignore it
|
||||
if (!controllers.ContainsKey(evtJdevice.which))
|
||||
break;
|
||||
|
||||
SDL_JoystickClose(controllers[evtJdevice.which].JoystickHandle);
|
||||
controllers.Remove(evtJdevice.which);
|
||||
removeJoystick(evtJdevice.which);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,8 +324,7 @@ namespace osu.Framework.Platform.SDL3
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_EVENT_GAMEPAD_REMOVED:
|
||||
SDL_CloseGamepad(controllers[evtCdevice.which].GamepadHandle);
|
||||
controllers.Remove(evtCdevice.which);
|
||||
removeJoystick(evtCdevice.which);
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_EVENT_GAMEPAD_REMAPPED:
|
||||
@@ -370,6 +369,18 @@ namespace osu.Framework.Platform.SDL3
|
||||
controllers[instanceID] = new SDL3ControllerBindings(joystick, controller);
|
||||
}
|
||||
|
||||
private void removeJoystick(SDL_JoystickID instanceID)
|
||||
{
|
||||
if (controllers.Remove(instanceID, out var controller))
|
||||
{
|
||||
if (controller.GamepadHandle != null)
|
||||
SDL_CloseGamepad(controller.GamepadHandle);
|
||||
|
||||
if (controller.JoystickHandle != null)
|
||||
SDL_CloseJoystick(controller.JoystickHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates <see cref="controllers"/> with joysticks that are already connected.
|
||||
/// </summary>
|
||||
@@ -395,12 +406,7 @@ namespace osu.Framework.Platform.SDL3
|
||||
break;
|
||||
|
||||
case SDL_EventType.SDL_EVENT_JOYSTICK_REMOVED:
|
||||
// if the joystick is already closed, ignore it
|
||||
if (!controllers.ContainsKey(evtJdevice.which))
|
||||
break;
|
||||
|
||||
SDL_CloseJoystick(controllers[evtJdevice.which].JoystickHandle);
|
||||
controllers.Remove(evtJdevice.which);
|
||||
removeJoystick(evtJdevice.which);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user