microsoft / xlang

MIT License
875 stars 103 forks source link

winrt.windows.gaming.input.RawGameController.get_current_reading #758

Closed markdude247 closed 2 years ago

markdude247 commented 2 years ago

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 2 years ago

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

markdude247 commented 2 years ago

Is the perimeter one list with three lists inside of it? Or each list into each parameter?

On Mon, Sep 20, 2021, 2:39 PM David Lechner @.***> wrote:

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

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/microsoft/xlang/issues/758#issuecomment-923180885, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGHK7MOCAUDGQDAQFCAXYT3UC55UXANCNFSM5EMQ7DOQ .

dlech commented 2 years ago

each parameter is a list

markdude247 commented 2 years ago

([[buttons], [switches], [axis]]) Or ([buttons], [switches], [axis])

On Mon, Sep 20, 2021, 2:44 PM Mark Cartagena @.***> wrote:

Is the perimeter one list with three lists inside of it? Or each list into each parameter?

On Mon, Sep 20, 2021, 2:39 PM David Lechner @.***> wrote:

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

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/microsoft/xlang/issues/758#issuecomment-923180885, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGHK7MOCAUDGQDAQFCAXYT3UC55UXANCNFSM5EMQ7DOQ .

markdude247 commented 2 years ago

I will upload my code now, one second

On Mon, Sep 20, 2021, 2:45 PM Mark Cartagena @.***> wrote:

([[buttons], [switches], [axis]]) Or ([buttons], [switches], [axis])

On Mon, Sep 20, 2021, 2:44 PM Mark Cartagena @.***> wrote:

Is the perimeter one list with three lists inside of it? Or each list into each parameter?

On Mon, Sep 20, 2021, 2:39 PM David Lechner @.***> wrote:

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

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/microsoft/xlang/issues/758#issuecomment-923180885, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGHK7MOCAUDGQDAQFCAXYT3UC55UXANCNFSM5EMQ7DOQ .

dlech commented 2 years ago

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

```python
# code goes here
markdude247 commented 2 years ago
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 2 years ago

[GameControllerSwitchPosition]

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

markdude247 commented 2 years ago

I'll give it a go once the remote charges

markdude247 commented 2 years ago

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

markdude247 commented 2 years ago

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 2 years ago

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.

markdude247 commented 2 years ago

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

dlech commented 2 years ago

you have to generate it yourself using this repository

markdude247 commented 2 years ago

No luck. Must be something with translation.

dlech commented 2 years ago

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 2 years ago

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
        )
markdude247 commented 2 years ago

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!