Closed somebelse closed 1 year ago
After a bit of retrospection all the needed parameters are probably already part of MOUSE_AREA and AIM.
I made some pseudo code to formulate my idea better. I can't really code and have no knowledge how JSM works under the hood. I may think in a completely wrong direction.
speed = output_MOUSE_AREA
On_enter_outer_deadzone{
has_touched = true
Touch_axis = normalized_deflection_angle
Touch_speed = radial_speed
}
If in_outer_deadzone{
speed = tangential_speed
}
If has_touched{
deflection_along_touch_axis = dot_product(deflection, touchaxis)
If deflection_along_touch_axis > 0 and not in_inner_deadzone{
Output = touch_speed * deflection_along_touch_axis ^ linearity
}else{
has_touched = false
}
}
Output += speed + output_AIM
Without the outer edge thing it should just be MOUSE_AREA and AIM added together.
Even more pseudo code. The implementation of the modes is probably redundant, as the other modes exist already.
/* parameters */
global_factor = ???
mouse_factor = ???
quadratic_acceleration = ???
joystick_factor = ???
joystick_linearity = ???
inner_deadzone = ???
outer_deadzone = ???
delta_t = ???
/* initialisation */
prev_deflection_ x, _y = 0, 0
has_touched = false
livezone = outer_deadzone - inner_deadzone
decimal_residue_x, _y = 0, 0
update_loop(delta_t){
prev_deflection_x, _y = deflection_x, _y
deflection_x = raw_x - 16384
deflection_y = raw_y - 16384
deflection = sqrt(deflection_x ** 2 + deflection_y ** 2)
angle = atan2(deflection_y , deflection_x)
delta_x = deflection_x - prev_deflection_x
delta_y = deflection_y - prev_deflection_y
magnitude_delta = sqrt(delta_x ** 2 + delta_y ** 2)
angle_delta = atan2(delta_y ,delta_x)
/* deadzones */
/* outer */
if (deflection >= outer_deadzone){
/* entering outer */
if (prev_deflection < outer_deadzone){
has_touched = true
angle_touch = angle
push_x = (1 + quadratic_acceleration * magnitude_delta / delta_t) * cos(angle_delta - angle) * cos(angle)
push_y = (1 + quadratic_acceleration * magnitude_delta / delta_t) * cos(angle_delta - angle) * sin(angle)
}
magnitude = 1
/* clip radial delta */
if (cos(angle_delta - angle) > 0){
//??????? math class has been a while
normal_x = sin(angle)
normal_y = - cos(angle)
dot_product = normal_x * delta_x + normal_y * delta_y
delta_x, _y = dot_product * normal_x, _y
// Mouse acceleration should stay untouched
}
}else{
/* inner */
if (deflection < inner_deadzone){
magnitude = 0
has_touched = false
}else{
/* "livezone" */
magnitude = pow((deflection - inner_deadzone) livezone, joystick_linearity)
}
}
/* mouse behavior */
output_x, _y = mouse_factor * (1 + quadratic_acceleration * magnitude_delta / delta_t) * delta_x, _y)
/* joystick behavior */
magnitude_x = magnitude * cos(angle)
magnitude_y = magnitude * sin(angle)
output_x, _y += joystick_factor * delta_t * magnitude_x, _y
/* edge touch push */
if has_touched{
deflection_touch_axis = deflection * cos(angle - angle_touch)
if (deflection_touch_axis < inner_deadzone){
has_touched = false
}else{
magnitude_push = pow((deflection_touch_axis - inner_deadzone) / livezone, joystick_linearity)
if (magnitude_push > 1){
magnitude_push = 1
}
output_x, _y += mouse_factor * magnitude_push * push_x, _y
}
}
output_x, _y *= global_factor
output_x, _y += decimal_residue_x, _y
decimal_residue_x, _y = output_x, _y - floor(output_x, _y)
delta_mouse_x, _y = output_x, _y
}
Proof of concept using AutoHotKey
HYBRID_AIM added in v3.5.0
A joystick (or gyro) that can act like a mouse and anolog stick at the same time added together.
The stick would act like a mouse but you'd be constantly pushed back to the center else you move further.
Furthermore the outer edge could act like trackball mode in that it would freeze the last speed (in the axis away from the center) and temporarily scales the anolog curve in that direction until its axis returns to the center.
Would need parameters of
I'd be happy to help in testing. I have a 360 Controller, a Laptop with Windows 10 and Ubuntu and a Steam Deck running SteamOS.