@@ -132,7 +132,25 @@ static void load_binding_from_data(JoypadBinding &binding, obs_data_t *data)
132132 binding.axis_threshold = obs_data_get_double (data, " axis_threshold" );
133133 bool axis_threshold_set = obs_data_get_bool (data, " axis_threshold_set" );
134134 if (!axis_threshold_set) {
135- binding.axis_threshold = 0.5 ;
135+ binding.axis_threshold = 0.10 ;
136+ }
137+ binding.axis_min_per_second = obs_data_get_double (data, " axis_min_per_second" );
138+ if (!obs_data_has_user_value (data, " axis_min_per_second" )) {
139+ // Backward compatibility with older configs.
140+ double legacy_min = obs_data_get_double (data, " axis_activation_min" );
141+ binding.axis_min_per_second = legacy_min > 0.0 ? legacy_min * 10.0 : 2.5 ;
142+ }
143+ binding.axis_max_per_second = obs_data_get_double (data, " axis_max_per_second" );
144+ if (!obs_data_has_user_value (data, " axis_max_per_second" )) {
145+ // Backward compatibility with older configs.
146+ double legacy_max = obs_data_get_double (data, " axis_activation_max" );
147+ binding.axis_max_per_second = legacy_max > 0.0 ? legacy_max * 10.0 : 20.0 ;
148+ }
149+ binding.axis_threshold = std::clamp (binding.axis_threshold , 0.0 , 0.95 );
150+ binding.axis_min_per_second = std::clamp (binding.axis_min_per_second , 1.0 , 60.0 );
151+ binding.axis_max_per_second = std::clamp (binding.axis_max_per_second , 1.0 , 60.0 );
152+ if (binding.axis_max_per_second < binding.axis_min_per_second ) {
153+ binding.axis_max_per_second = binding.axis_min_per_second ;
136154 }
137155 binding.axis_interval_ms = (int )obs_data_get_int (data, " axis_interval_ms" );
138156 if (binding.axis_interval_ms <= 0 ) {
@@ -187,6 +205,8 @@ static void save_binding_to_data(const JoypadBinding &binding, obs_data_t *data)
187205 obs_data_set_bool (data, " axis_inverted" , binding.axis_inverted );
188206 obs_data_set_double (data, " axis_threshold" , binding.axis_threshold );
189207 obs_data_set_bool (data, " axis_threshold_set" , true );
208+ obs_data_set_double (data, " axis_min_per_second" , binding.axis_min_per_second );
209+ obs_data_set_double (data, " axis_max_per_second" , binding.axis_max_per_second );
190210 obs_data_set_int (data, " axis_interval_ms" , binding.axis_interval_ms );
191211 obs_data_set_double (data, " axis_min_value" , binding.axis_min_value );
192212 obs_data_set_double (data, " axis_max_value" , binding.axis_max_value );
@@ -903,8 +923,8 @@ std::vector<JoypadBinding> JoypadConfigStore::FindMatchingBindings(const JoypadE
903923 }
904924 }
905925
906- const double threshold_on = binding.axis_threshold ;
907- const double threshold_off = binding. axis_threshold * 0.4 ;
926+ const double threshold_on = std::clamp ( binding.axis_threshold , 0.0 , 0.95 ) ;
927+ const double threshold_off = threshold_on * 0.4 ;
908928 std::string axis_key = event.device_id + " :" + std::to_string (binding.axis_index ) + " :" +
909929 std::to_string ((int )binding.axis_direction ) + " :" +
910930 (binding.axis_inverted ? " 1" : " 0" );
@@ -924,13 +944,18 @@ std::vector<JoypadBinding> JoypadConfigStore::FindMatchingBindings(const JoypadE
924944 }
925945 if (binding.action == JoypadActionType::AdjustSourceVolume) {
926946 double sign = value >= 0.0 ? 1.0 : -1.0 ;
927- double intensity = std::clamp (abs_value, 0.0 , 1.0 );
928- binding.volume_value = std::fabs (binding.volume_value ) * intensity * sign;
947+ binding.volume_value = std::fabs (binding.volume_value ) * sign;
929948 }
930949 const bool is_continuous_axis_action =
931- (binding.action == JoypadActionType::SetSourceVolumePercent) ||
932- (binding.action == JoypadActionType::AdjustSourceVolume);
933- if (!is_continuous_axis_action && binding.axis_interval_ms > 0 ) {
950+ (binding.action == JoypadActionType::SetSourceVolumePercent);
951+ if (!is_continuous_axis_action) {
952+ const double min_rate = std::clamp (binding.axis_min_per_second , 1.0 , 60.0 );
953+ const double max_rate = std::clamp (binding.axis_max_per_second , min_rate, 60.0 );
954+ double intensity =
955+ std::clamp ((abs_value - threshold_on) / (1.0 - threshold_on), 0.0 , 1.0 );
956+ double rate = min_rate + (max_rate - min_rate) * intensity;
957+ int dynamic_interval_ms = (int )std::round (1000.0 / std::max (rate, 0.001 ));
958+ dynamic_interval_ms = std::max (dynamic_interval_ms, 1 );
934959 std::string interval_key;
935960 if (binding.uid > 0 ) {
936961 interval_key = std::to_string ((long long )binding.uid );
@@ -944,7 +969,7 @@ std::vector<JoypadBinding> JoypadConfigStore::FindMatchingBindings(const JoypadE
944969 const auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
945970 now - it_last->second )
946971 .count ();
947- if (elapsed < binding. axis_interval_ms ) {
972+ if (elapsed < dynamic_interval_ms ) {
948973 continue ;
949974 }
950975 }
0 commit comments