Electronicks / JoyShockMapper

A tool for PC gamers to play games with DualShock 4s, JoyCons, and Pro Controllers. Gyro aiming, flick stick.
Other
332 stars 20 forks source link

[Feature Request] Combined postitional and integrated input from the same source #85

Closed somebelse closed 10 months ago

somebelse commented 1 year ago

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.

somebelse commented 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.

somebelse commented 1 year ago

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
}
somebelse commented 1 year ago

CombinedMouseAndJoystick.zip

Proof of concept using AutoHotKey

Electronicks commented 10 months ago

HYBRID_AIM added in v3.5.0