#[Solved] ViGEm Client in Rust

10 messages · Page 1 of 1 (latest)

ancient viper
#

Hi all! So, I'm quite new to rust and I'm a bit confused on how to implement something.

I'm currently using this cargo in my project:
https://crates.io/crates/vigem-client

With it I've successfully managed to create virtual controllers and store them in a vector, however now I need to implement a function for pressing buttons on said controllers and I'm getting very stuck.

Ideally I'd like something like this:

lazy_static! {
    static ref XBOX_PADS: Mutex<Vec<Option<Arc<Mutex<Xbox360Wired<CL>>>>>> = Mutex::new(vec![None, None, None, None]);
}

fn vigem_xbox_btn(index: i32, buttons: Vec<u16>) {
    // Press buttons on pad at index
}

...where I could specify the pad index and give a vector of the buttons I want being pressed. However, everything I've tried hasn't worked, and ChatGPT and GitHub Copilot keeps giving me code filled with errors. I'm lost!

Has anybody used this cargo before, or if anybody could take a look at the cargo and give me some pointers?

Thanks!

rocky whale
#
pub trait ControllerExt {
    fn method1(&self);

    ...
}

impl ControllerExt for Xbox360Wired<Whatever> {
      fn method1(&self) { ... }
}
ancient viper
#

I'm not quite sure how I would apply that to my problem (sorry, I'm still quite new with Rust!). Let me explain a little bit better on what I'm trying to do.

So, in the cargo's example, it shows how to press buttons on a gamepad:

let mut gamepad = vigem_client::XGamepad {
    buttons: vigem_client::XButtons!(UP | RIGHT | LB | A | X),
    ..Default::default()
};

From what I understand, "buttons" is being passed a set of "macro_rules", with these translating to hex codes. As I fiddled with the code, I found I could also give it a single "raw" hex value:

#
#[macro_export]
macro_rules! XButtons {
    (UP) => { $crate::XButtons { raw: $crate::XButtons::UP } };
    (DOWN) => { $crate::XButtons { raw: $crate::XButtons::DOWN } };
    (LEFT) => { $crate::XButtons { raw: $crate::XButtons::LEFT } };
    (RIGHT) => { $crate::XButtons { raw: $crate::XButtons::RIGHT } };
    (START) => { $crate::XButtons { raw: $crate::XButtons::START } };
    (BACK) => { $crate::XButtons { raw: $crate::XButtons::BACK } };
    (LTHUMB) => { $crate::XButtons { raw: $crate::XButtons::LTHUMB } };
    (RTHUMB) => { $crate::XButtons { raw: $crate::XButtons::RTHUMB } };
    (LB) => { $crate::XButtons { raw: $crate::XButtons::LB } };
    (RB) => { $crate::XButtons { raw: $crate::XButtons::RB } };
    (GUIDE) => { $crate::XButtons { raw: $crate::XButtons::GUIDE } };
    (A) => { $crate::XButtons { raw: $crate::XButtons::A } };
    (B) => { $crate::XButtons { raw: $crate::XButtons::B } };
    (X) => { $crate::XButtons { raw: $crate::XButtons::X } };
    (Y) => { $crate::XButtons { raw: $crate::XButtons::Y } };

    ($($face:ident)|*) => {
        $crate::XButtons { raw: 0 $(| $crate::XButtons!($face).raw)* }
    };
}
#
impl XButtons {
    /// Dpad up button.
    pub const UP: u16     = 0x0001;
    /// Dpad down button.
    pub const DOWN: u16   = 0x0002;
    /// Dpad left button.
    pub const LEFT: u16   = 0x0004;
    /// Dpad right button.
    pub const RIGHT: u16  = 0x0008;
    /// Start button.
    pub const START: u16  = 0x0010;
    /// Back button.
    pub const BACK: u16   = 0x0020;
    /// Left thumb button.
    pub const LTHUMB: u16 = 0x0040;
    /// Right thumb button.
    pub const RTHUMB: u16 = 0x0080;
    /// Left shoulder button.
    pub const LB: u16     = 0x0100;
    /// Right shoulder button.
    pub const RB: u16     = 0x0200;
    /// Xbox guide button.
    pub const GUIDE: u16  = 0x0400;
    /// A button.
    pub const A: u16      = 0x1000;
    /// B button.
    pub const B: u16      = 0x2000;
    /// X button.
    pub const X: u16      = 0x4000;
    /// Y button.
    pub const Y: u16      = 0x8000;
}
#
let mut gamepad = vigem_client::XGamepad {
  buttons: vigem_client::XButtons(0x0001),
  ..Default::default()
};

However the problem with this is I want to be able to press several buttons at once, and I don't see a way to give it multiple values

#

Taking a look at this

vigem_client::XButtons!(UP | RIGHT | LB | A | X)

...I thought maybe there was a way I could give a string of buttons as an argument, and "evaluate" it to this pipe seperated format XButtons accepts...GitHub Copilot too seemed to think I could possibly do something like this, and gave me code examples that looked like it was attempting to do this...but the rust compiler had issues with every code snippet it gave me

#

So I'm at a loss as to how I can just give a gamepad a dynamic set of buttons 😅

ancient viper
#

Okay, I've finally got what I wanted...I explained what I was trying to fully to ChatGPT and it finally gave me a working function...posting it here to help others:

fn press_buttons(buttons: &[&str]) -> XButtons {
    let mut xbuttons = XButtons { raw: 0 };

    for button in buttons {
        match *button {
            "UP" => xbuttons.raw |= XButtons::UP,
            "DOWN" => xbuttons.raw |= XButtons::DOWN,
            "LEFT" => xbuttons.raw |= XButtons::LEFT,
            "RIGHT" => xbuttons.raw |= XButtons::RIGHT,
            "START" => xbuttons.raw |= XButtons::START,
            "BACK" => xbuttons.raw |= XButtons::BACK,
            "LTHUMB" => xbuttons.raw |= XButtons::LTHUMB,
            "RTHUMB" => xbuttons.raw |= XButtons::RTHUMB,
            "LB" => xbuttons.raw |= XButtons::LB,
            "RB" => xbuttons.raw |= XButtons::RB,
            "GUIDE" => xbuttons.raw |= XButtons::GUIDE,
            "A" => xbuttons.raw |= XButtons::A,
            "B" => xbuttons.raw |= XButtons::B,
            "X" => xbuttons.raw |= XButtons::X,
            "Y" => xbuttons.raw |= XButtons::Y,
            _ => (),
        }
    }

    xbuttons
}
#

Example:

let buttons = press_buttons(&["UP", "RIGHT", "LB", "A", "X"]);
let mut gamepad = vigem_client::XGamepad {
    buttons: buttons,
    ..Default::default()
};