microsoft/xlang

winrt.windows.gaming.input.RawGameController.get_current_reading

markdude247 opened this issue · 18 comments

Python 3.9

Method Expects 3 Arrays. First array consists of X(button_count) Bools, Second array consists of X(switch_count) GameControllerSwitchPosition, Third consists of X(axis_count) floats. When running RawGameController.get_current_reading(array1, array2, array3), The function is rejected and you receive errror: "RuntimeError: The parameter is incorrect.". This method works perfectly fine with C#

dlech commented

Can you share your full code? The bindings expect these parameters to be a Python list object.

dlech commented

each parameter is a list

dlech commented

Tip: wrap the code like this so we can read it

```python
# code goes here
```
from winrt.windows.gaming import input as winInput
import time

class __dualshock4_remote__:

    def __init__(self, winRT_RawController:winInput.RawGameController):
        self.type = "dualshock4"
        self.rawAPI = winRT_RawController
        self.button_count = winRT_RawController.button_count
        self.axis_count = winRT_RawController.axis_count
        self.switch_count = winRT_RawController.switch_count
        self.wireless = winRT_RawController.is_wireless
        self.headset = winRT_RawController.headset
        self.ID = winRT_RawController.non_roamable_id


        self.button_states = []
        for i in range(self.button_count):
            self.button_states.append(False)

        self.axis_states = []
        for i in range(self.axis_count):
            self.axis_states.append(0.0)

        self.switch_states = []
        for i in range(self.switch_count):
            self.switch_states.append(winInput.GameControllerSwitchPosition)


        print(self.button_states, self.switch_states, self.axis_states)
        # [False, False, False, False,.... (14x)], [GameControllerSwitchPosition], [0, 0, 0, 0 ,0 ,0]
        print(winRT_RawController.get_current_reading)
        # Code will not function past this
        self.refresh = winRT_RawController.get_current_reading(
            self.button_states,
            self.switch_states,
            self.axis_states
        )



    def __repr__(self) -> str:
        return "< Dual Shock Remote >"

class __controllers__(list):
    def __init_subclass__(cls) -> None:
        return super().__init_subclass__()

    def get_dualshock(self) -> __dualshock4_remote__:
        # Get the first Dualshock remote
        for item in self:
            if item.type == "dualshock4":
                return item

def get_controllers(timeout=5):
    troller = timeout
    while troller > 0:
        raw_controllers = []
        gamePads = winInput.RawGameController.get_raw_game_controllers()
        for i in range(gamePads.size):
            controller = gamePads.get_at(i)
            raw_controllers.append(controller)
        time.sleep(0.25)
        if len(raw_controllers) > 0:
            break
        troller -= 0.25

    controllers = __controllers__()
    # Create a list item
    for controller in raw_controllers:
        #Parse through the found controllers and match them to their class.
        if controller.axis_count == 6 and controller.button_count == 14 and controller.hardware_vendor_id == 1356:
            #These parameters match the dual shock remote.
            controllers.append(__dualshock4_remote__(controller))

    return controllers

ps4_remote = get_controllers().get_dualshock()
dlech commented

[GameControllerSwitchPosition]

GameControllerSwitchPosition is a Python type, so this is a list of type rather than a list of GameControllerSwitchPosition. So maybe [GameControllerSwitchPosition.CENTER] works?

I'll give it a go once the remote charges

No success, Still the same response. Invalid parameter. It there an option to know exactly which parameter?

The corresponding code that works in C# is as follows:

bool[] buttons = new bool[remote.ButtonCount];
GameControllerSwitchPosition[] switches = new GameControllerSwitchPosition[remote.SwitchCount];
double[] axis = new double[remote.AxisCount];
remote.GetCurrentReading(buttons, switches, axis);
dlech commented

Invalid parameter. It there an option to know exactly which parameter?

No.

The corresponding code that works in C# is as follows:

FWIW, the Python equivalent should be this. (your code does the same thing, this is just fewer lines)

        self.button_states = [False] * self.button_count
        self.axis_states = [0.0] * self.axis_count
        self.switch_states = [winInput.GameControllerSwitchPosition.CENTER] * self.switch_count
        self.refresh = winRT_RawController.get_current_reading(
            self.button_states,
            self.switch_states,
            self.axis_states
        )

Not sure what else to suggest other than looking at the generated PyWinRT code for the get_current_reading() to see if it doesn't something unusual.

where can I find that file and it's contents?

dlech commented

you have to generate it yourself using this repository

No luck. Must be something with translation.

dlech commented

Here is the generated code:

    static PyObject* RawGameController_GetCurrentReading(py::wrapper::Windows::Gaming::Input::RawGameController* self, PyObject* args) noexcept
    {
        Py_ssize_t arg_count = PyTuple_Size(args);

        if (arg_count == 3)
        {
            try
            {
                auto param0_count = py::convert_to<winrt::com_array<bool>::size_type>(args, 0);
                winrt::com_array<bool> param0 ( param0_count, py::empty_instance<bool>::get() );
                auto param1_count = py::convert_to<winrt::com_array<winrt::Windows::Gaming::Input::GameControllerSwitchPosition>::size_type>(args, 1);
                winrt::com_array<winrt::Windows::Gaming::Input::GameControllerSwitchPosition> param1 ( param1_count, py::empty_instance<winrt::Windows::Gaming::Input::GameControllerSwitchPosition>::get() );
                auto param2_count = py::convert_to<winrt::com_array<double>::size_type>(args, 2);
                winrt::com_array<double> param2 ( param2_count, py::empty_instance<double>::get() );

                auto return_value = self->obj.GetCurrentReading(param0, param1, param2);

                py::pyobj_handle out_return_value{ py::convert(return_value) };
                if (!out_return_value) 
                { 
                    return nullptr;
                }
                py::pyobj_handle out0{ py::convert(param0) };
                if (!out0) 
                {
                    return nullptr;
                }
                py::pyobj_handle out1{ py::convert(param1) };
                if (!out1) 
                {
                    return nullptr;
                }
                py::pyobj_handle out2{ py::convert(param2) };
                if (!out2) 
                {
                    return nullptr;
                }
                return PyTuple_Pack(4, out_return_value.get(), out0.get(), out1.get(), out2.get());
            }
            catch (...)
            {
                py::to_PyErr();
                return nullptr;
            }
        }
        else
        {
            py::set_invalid_arg_count_error(arg_count);
            return nullptr;
        }
    }
dlech commented

It looks like it takes sizes for arguments, so...

        self.refresh, self.button_states, self.axis_states, self.switch_states = winRT_RawController.get_current_reading(
            self.button_count,
            self.switch_count,
            self.axis_count
        )

Here is the generated code

Thanks. I am very new to how source code works. It seems like this is it. It's odd how much it changed vs. C# and Microsoft API Docs. No errors and it is refreshing.

self.refresh, self.button_states, self.switch_states, self.axis_states,

This IS in fact what is being return. Thank you sir!

(12442722443, [False, False, False, False, False, False, False, False, False, False, False, False, False, False], [0], [0.5019607843137255, 0.5019607843137255, 0.5137254901960784,
0.0, 0.0, 0.5019607843137255])

(Timestamp, [Button States], [Switch (Directional Pad) State], [Axis States])

You were a great help. I really do appreciate it!