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

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

Closed
markdude247 opened this issue Sep 20, 2021 · 18 comments
Closed

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

markdude247 opened this issue Sep 20, 2021 · 18 comments

Comments

@markdude247
Copy link

markdude247 commented Sep 20, 2021

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
Copy link
Contributor

dlech commented Sep 20, 2021

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

@markdude247
Copy link
Author

markdude247 commented Sep 20, 2021 via email

@dlech
Copy link
Contributor

dlech commented Sep 20, 2021

each parameter is a list

@markdude247
Copy link
Author

markdude247 commented Sep 20, 2021 via email

@markdude247
Copy link
Author

markdude247 commented Sep 20, 2021 via email

@dlech
Copy link
Contributor

dlech commented Sep 20, 2021

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

```python
# code goes here
```

@markdude247
Copy link
Author

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
Copy link
Contributor

dlech commented Sep 20, 2021

[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
Copy link
Author

I'll give it a go once the remote charges

@markdude247
Copy link
Author

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

@markdude247
Copy link
Author

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
Copy link
Contributor

dlech commented Sep 20, 2021

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
Copy link
Author

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

@dlech
Copy link
Contributor

dlech commented Sep 20, 2021

you have to generate it yourself using this repository

@markdude247
Copy link
Author

No luck. Must be something with translation.

@dlech
Copy link
Contributor

dlech commented Sep 21, 2021

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
Copy link
Contributor

dlech commented Sep 21, 2021

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
Copy link
Author

markdude247 commented Sep 21, 2021

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants