diff --git a/internal/mappingrules/math.go b/internal/mappingrules/math.go index bccae51..37de4a2 100644 --- a/internal/mappingrules/math.go +++ b/internal/mappingrules/math.go @@ -4,17 +4,22 @@ import ( "golang.org/x/exp/constraints" ) -func AbsInt[T constraints.Integer](value T) T { +type Numeric interface { + constraints.Integer | constraints.Float +} + +func Abs[T Numeric](value T) T { return max(value, -value) } // LerpInt linearly interpolates between two integer values using // a float64 index value func LerpInt[T constraints.Integer](min, max T, t float64) T { + t = Clamp(t, 0.0, 1.0) return T((1-t)*float64(min) + t*float64(max)) } -func ClampInt[T constraints.Integer](value, min, max T) T { +func Clamp[T Numeric](value, min, max T) T { if value < min { value = min } diff --git a/internal/mappingrules/rule_target_axis.go b/internal/mappingrules/rule_target_axis.go index 2ea2b58..8701b2c 100644 --- a/internal/mappingrules/rule_target_axis.go +++ b/internal/mappingrules/rule_target_axis.go @@ -51,7 +51,7 @@ func NewRuleTargetAxis(device_name string, return nil, errors.New("deadzone_end must be a higher value than deadzone_start") } - deadzoneSize := AbsInt(deadzoneEnd - deadzoneStart) + deadzoneSize := Abs(deadzoneEnd - deadzoneStart) // Our output range is limited to 16 bits, but we represent values internally with 32 bits. // As a result, we shouldn't need to worry about integer overruns @@ -82,6 +82,7 @@ func NewRuleTargetAxis(device_name string, // in the deadzone, among other things. func (target *RuleTargetAxis) NormalizeValue(value int32) int32 { axisStrength := float64(value-target.deadzoneSize) / float64(target.axisSize) + if target.Inverted { axisStrength = 1.0 - axisStrength } @@ -90,7 +91,7 @@ func (target *RuleTargetAxis) NormalizeValue(value int32) int32 { } func (target *RuleTargetAxis) CreateEvent(value int32, mode *string) *evdev.InputEvent { - value = ClampInt(value, AxisValueMin, AxisValueMax) + value = Clamp(value, AxisValueMin, AxisValueMax) return &evdev.InputEvent{ Type: evdev.EV_ABS, Code: target.Axis, diff --git a/internal/mappingrules/rule_target_axis_test.go b/internal/mappingrules/rule_target_axis_test.go index 15bcd0e..6d6e632 100644 --- a/internal/mappingrules/rule_target_axis_test.go +++ b/internal/mappingrules/rule_target_axis_test.go @@ -69,8 +69,8 @@ func (t *RuleTargetAxisTests) TestNewRuleTargetAxis() { // If Absinfo has an error, we should create a device with permissive bounds t.call.Unset() - t.mock.On("AbsInfos").Return(nil, errors.New("Test Error")) - ruleTarget, err = NewRuleTargetAxis("", t.mock, evdev.ABS_Y, false, -500, 500) + t.mock.On("AbsInfos").Return(map[evdev.EvCode]evdev.AbsInfo{}, errors.New("Test Error")) + ruleTarget, err = NewRuleTargetAxis("", t.mock, evdev.ABS_X, false, 0, 0) t.Nil(err) t.Equal(AxisValueMax-AxisValueMin, ruleTarget.axisSize) } @@ -92,6 +92,11 @@ func (t *RuleTargetAxisTests) TestNormalizeValue() { ruleTarget, _ = NewRuleTargetAxis("", t.mock, evdev.ABS_X, true, 0, 0) t.Equal(AxisValueMax, ruleTarget.NormalizeValue(int32(0))) t.Equal(AxisValueMin, ruleTarget.NormalizeValue(int32(10000))) + + // Normalization past the stated axis bounds should clamp + ruleTarget, _ = NewRuleTargetAxis("", t.mock, evdev.ABS_X, false, 0, 0) + t.Equal(AxisValueMin, ruleTarget.NormalizeValue(int32(-30000))) + t.Equal(AxisValueMax, ruleTarget.NormalizeValue(int32(30000))) } func (t *RuleTargetAxisTests) TestMatchEvent() {