Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to change pedal axis behavior #110

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion oversteer/device.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from evdev import ecodes, InputDevice
from evdev import ecodes, InputDevice, UInput
import grp
import logging
import os
Expand All @@ -7,6 +7,7 @@
import select
import time
from . import wheel_ids as wid
from .pedal_mode import AxisMode, get_modified_value

logging.basicConfig(level=logging.DEBUG)

Expand All @@ -22,6 +23,9 @@ class Device:
def __init__(self, device_manager, data):
self.device_manager = device_manager
self.input_device = None
self.injector_device = None
self.injector_active = False
self.pedal_mode = None
self.seat_id = None
self.vendor_id = None
self.product_id = None
Expand Down Expand Up @@ -142,6 +146,15 @@ def set_mode(self, emulation_mode):
time.sleep(5)
return True

def get_pedal_mode(self):
if self.pedal_mode is None:
self.set_pedal_mode(AxisMode.NORMAL.value.id)
return self.pedal_mode

def set_pedal_mode(self, mode):
self.pedal_mode = list(AxisMode)[mode]
self.set_active_event_device()

def get_range(self):
path = self.checked_device_file("range")
if not path:
Expand Down Expand Up @@ -368,6 +381,16 @@ def get_input_device(self):
self.input_device = InputDevice(self.dev_name)
return self.input_device

def set_active_event_device(self):
if self.pedal_mode != AxisMode.NORMAL and not self.injector_active:
self.injector_device = UInput.from_device(self.input_device, name="Custom pedal mode wheel")
self.input_device.grab()
self.injector_active = True
elif self.pedal_mode == AxisMode.NORMAL and self.input_device is not None and self.injector_active:
self.injector_device = None
self.input_device.ungrab()
self.injector_active = False

def get_capabilities(self):
return self.get_input_device().capabilities()

Expand All @@ -380,6 +403,10 @@ def read_events(self, timeout):
event = self.normalize_event(event)
if event.type == ecodes.EV_ABS:
self.last_axis_value[ecodes.ABS_X] = event.value

if self.pedal_mode != AxisMode.NORMAL and self.injector_device is not None:
self.injector_device.write_event(event)

yield event

def normalize_event(self, event):
Expand Down Expand Up @@ -408,4 +435,6 @@ def normalize_event(self, event):
event.code = ecodes.ABS_RZ
elif event.code == ecodes.ABS_THROTTLE:
event.code = ecodes.ABS_Y
elif self.pedal_mode != AxisMode.NORMAL and event.code in [ecodes.ABS_RZ, ecodes.ABS_Y, ecodes.ABS_Z]:
event.value = get_modified_value(self.pedal_mode, event.value)
return event
15 changes: 12 additions & 3 deletions oversteer/gtk_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import traceback
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
from .pedal_mode import CombinedPedals

class GtkHandlers:

Expand Down Expand Up @@ -81,13 +82,16 @@ def on_overlay_incrange_clicked(self, widget):
self.ui.overlay_wheel_range.set_label(str(wrange))

def on_combine_none_clicked(self, widget):
self.model.set_combine_pedals(0)
self.model.set_combine_pedals(CombinedPedals.NONE)
self.ui.set_pedal_levels()

def on_combine_brakes_clicked(self, widget):
self.model.set_combine_pedals(1)
self.model.set_combine_pedals(CombinedPedals.COMBINE_BRAKES)
self.ui.set_pedal_levels()

def on_combine_clutch_clicked(self, widget):
self.model.set_combine_pedals(2)
self.model.set_combine_pedals(CombinedPedals.COMBINE_CLUTCH)
self.ui.set_pedal_levels()

def on_ff_gain_value_changed(self, widget):
ff_gain = int(widget.get_value())
Expand Down Expand Up @@ -286,3 +290,8 @@ def on_start_app_manually_state_set(self, widget, state):

def on_start_app_clicked(self, widget):
self.controller.start_app()

def on_pedal_mode_changed(self, widget):
mode = self.ui.pedal_mode_combobox.get_active()
self.model.set_pedal_mode(mode)
self.model.flush_ui()
52 changes: 50 additions & 2 deletions oversteer/gtk_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .gtk_handlers import GtkHandlers
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib
from . import pedal_mode

class GtkUi:

Expand Down Expand Up @@ -47,6 +48,11 @@ def __init__(self, controller, argv):
self.emulation_mode_combobox.add_attribute(cell_renderer, 'text', 1)
self.emulation_mode_combobox.set_id_column(0)

cell_renderer = Gtk.CellRendererText()
self.pedal_mode_combobox.pack_start(cell_renderer, True)
self.pedal_mode_combobox.add_attribute(cell_renderer, 'text', 1)
self.pedal_mode_combobox.set_id_column(0)

self.set_range_overlay('never')
self.disable_save_profile()

Expand Down Expand Up @@ -256,6 +262,47 @@ def set_mode(self, mode):
self.change_emulation_mode_button.set_sensitive(True)
self.emulation_mode_combobox.set_active_id(mode)

def set_pedal_modes(self):
model = self.pedal_mode_combobox.get_model()
if model is None:
model = Gtk.ListStore(int, str)

for mode in pedal_mode.AxisMode:
model.append(mode.value)
self.pedal_mode_combobox.set_model(model)
self.set_pedal_mode(pedal_mode.AxisMode.NORMAL.value.id)

def set_pedal_mode(self, mode):
if self.pedal_mode_combobox.get_model() is None:
return

set_mode = list(pedal_mode.AxisMode)[mode]
self.pedal_mode_combobox.set_active(set_mode.value.id)
self.set_pedal_levels()

def set_pedal_levels(self):
combine_mode = self.controller.device.get_combine_pedals()
axis_mode = self.controller.device.get_pedal_mode()

acceleration_out = pedal_mode.get_modified_value(axis_mode, 255)
acceleration_in = pedal_mode.get_modified_value(axis_mode, 0)
brakes_out = pedal_mode.get_modified_value(axis_mode, 255)
clutch_out = pedal_mode.get_modified_value(axis_mode, 255)

accel = acceleration_out

if combine_mode == pedal_mode.CombinedPedals.COMBINE_BRAKES:
accel = acceleration_in + (acceleration_out - acceleration_in) / 2
brakes_out = 255
elif combine_mode == pedal_mode.CombinedPedals.COMBINE_CLUTCH:
accel = acceleration_in + (acceleration_out - acceleration_in) / 2
clutch_out = 255

self.safe_call(self.set_accelerator_input, int(accel))
self.safe_call(self.set_brakes_input, int(brakes_out))
self.safe_call(self.set_clutch_input, int(clutch_out))


def set_range(self, wrange):
if wrange is None:
self.wheel_range.set_sensitive(False)
Expand All @@ -277,9 +324,9 @@ def set_combine_pedals(self, combine_pedals):
else:
self.combine_brakes.set_sensitive(True)
self.combine_clutch.set_sensitive(True)
if combine_pedals == 1:
if combine_pedals == pedal_mode.CombinedPedals.COMBINE_BRAKES:
self.combine_brakes.set_active(True)
elif combine_pedals == 2:
elif combine_pedals == pedal_mode.CombinedPedals.COMBINE_CLUTCH:
self.combine_clutch.set_active(True)
else:
self.combine_none.set_active(True)
Expand Down Expand Up @@ -611,6 +658,7 @@ def _set_builder_objects(self):
self.clutch_input = self.builder.get_object('clutch_input')
self.accelerator_input = self.builder.get_object('accelerator_input')
self.brakes_input = self.builder.get_object('brakes_input')
self.pedal_mode_combobox = self.builder.get_object('pedal_mode')
self.hat_up_input = self.builder.get_object('hat_up_input')
self.hat_down_input = self.builder.get_object('hat_down_input')
self.hat_left_input = self.builder.get_object('hat_left_input')
Expand Down
4 changes: 4 additions & 0 deletions oversteer/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,13 @@ def populate_profiles(self):
profiles.append(profile_name)
self.ui.set_profiles(profiles)

def populate_pedal_modes(self):
self.ui.set_pedal_modes()

def populate_window(self):
self.populate_devices()
self.populate_profiles()
self.populate_pedal_modes()

def change_device(self, device_id):
self.device = self.device_manager.get_device(device_id)
Expand Down
72 changes: 70 additions & 2 deletions oversteer/main.ui
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="autocenter_adjustment">
Expand Down Expand Up @@ -768,6 +768,19 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="opacity">0</property>
<property name="orientation">vertical</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
Expand All @@ -776,7 +789,7 @@
</packing>
</child>
<child>
<!-- n-columns=3 n-rows=3 -->
<!-- n-columns=3 n-rows=5 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
Expand Down Expand Up @@ -864,6 +877,48 @@
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="margin-start">27</property>
<property name="label" translatable="yes">Pedal mode</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="pedal_mode">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Change pedal axis behavior</property>
<signal name="changed" handler="on_pedal_mode_changed" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">The settings other than normal are only available by selecting the device called: "Custom pedal mode wheel" in-game. You may therefore need to rebind your keys in-game to use this feature.

Oversteer must also be open while in-game in order for custom pedal modes to work</property>
<property name="halign">start</property>
<property name="stock">gtk-dialog-question</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
Expand Down Expand Up @@ -995,6 +1050,19 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="opacity">0</property>
<property name="orientation">vertical</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
Expand Down
15 changes: 15 additions & 0 deletions oversteer/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Model:
'use_buttons': None,
'center_wheel': None,
'start_app_manually': None,
'pedal_mode': None,
}

types = {
Expand All @@ -35,6 +36,7 @@ class Model:
'use_buttons': 'boolean',
'center_wheel': 'boolean',
'start_app_manually': 'boolean',
'pedal_mode': 'integer',
}

def __init__(self, device = None, ui = None):
Expand Down Expand Up @@ -78,6 +80,7 @@ def read_device_settings(self):
'use_buttons': False if self.device.get_range() is not None else None,
'center_wheel': False,
'start_app_manually': False,
'pedal_mode': self.device.get_pedal_mode().value.id
}

def update_from_device_settings(self):
Expand Down Expand Up @@ -165,6 +168,14 @@ def set_mode(self, value):
def get_mode(self):
return self.data['mode']

def get_pedal_mode(self):
return self.data['pedal_mode']

def set_pedal_mode(self, value):
value = int(value)
if self.set_if_changed('pedal_mode', value):
self.device.set_pedal_mode(value)

def set_range(self, value):
value = int(value)
if self.set_if_changed('range', value):
Expand Down Expand Up @@ -278,6 +289,8 @@ def flush_device(self):
self.device.set_friction_level(self.data['friction_level'])
if self.data['ffb_leds'] is not None:
self.device.set_ffb_leds(self.data['ffb_leds'])
if self.data['pedal_mode'] is not None:
self.device.set_pedal_mode(self.data['pedal_mode'])

def flush_ui(self, data = None):
if data is None:
Expand All @@ -296,4 +309,6 @@ def flush_ui(self, data = None):
self.ui.set_use_buttons(data['use_buttons'])
self.ui.set_center_wheel(data['center_wheel'])
self.ui.set_start_app_manually(data['start_app_manually'])
self.ui.set_pedal_mode(data['pedal_mode'])
self.ui.set_pedal_levels()

Loading