diff --git a/src/python/magnum/platform/application.h b/src/python/magnum/platform/application.h index 42af527..54ee2a4 100644 --- a/src/python/magnum/platform/application.h +++ b/src/python/magnum/platform/application.h @@ -25,6 +25,7 @@ #include +#include "corrade/EnumOperators.h" #include "magnum/bootstrap.h" namespace magnum { namespace platform { @@ -62,11 +63,42 @@ template void application(py::class_& .def("swap_buffers", &T::swapBuffers, "Swap buffers") /** @todo setMinimalLoopPeriod, needs a getter */ .def("redraw", &T::redraw, "Redraw immediately") + .def("window_size", &T::windowSize, "Window size") + .def("framebuffer_size", &T::framebufferSize, "Framebuffer size") /* Event handlers */ .def("draw_event", &T::drawEvent, "Draw event") + .def("mouse_press_event", &T::mousePressEvent, "Mouse press event") + .def("mouse_release_event", &T::mouseReleaseEvent, "Mouse release event") + .def("mouse_move_event", &T::mouseMoveEvent, "Mouse move event") /** @todo more */ ; } +template void mouseEvent(py::class_& c) { + py::enum_{c, "Button", "Mouse button"} + .value("LEFT", T::Button::Left) + .value("MIDDLE", T::Button::Middle) + .value("RIGHT", T::Button::Right); + + c + .def_property_readonly("button", &T::button, "Button") + .def_property_readonly("position", &T::position, "Position"); +} + +template void mouseMoveEvent(py::class_& c) { + py::enum_ buttons{c, "Buttons", "Set of mouse buttons"}; + buttons + .value("LEFT", T::Button::Left) + .value("MIDDLE", T::Button::Middle) + .value("RIGHT", T::Button::Right); + corrade::enumOperators(buttons); + + c + .def_property_readonly("position", &T::position, "Position") + .def_property_readonly("buttons", [](T& self) { + return typename T::Button(typename std::underlying_type::type(self.buttons())); + }, "Mouse buttons"); +} + }} diff --git a/src/python/magnum/platform/glfw.cpp b/src/python/magnum/platform/glfw.cpp index 876de6c..cda5611 100644 --- a/src/python/magnum/platform/glfw.cpp +++ b/src/python/magnum/platform/glfw.cpp @@ -38,6 +38,9 @@ void glfw(py::module& m) { explicit PublicizedApplication(const Configuration& configuration, const GLConfiguration& glConfiguration): Platform::Application{Arguments{argc, nullptr}, configuration, glConfiguration} {} void drawEvent() override = 0; + void mousePressEvent(MouseEvent&) override {} + void mouseReleaseEvent(MouseEvent&) override {} + void mouseMoveEvent(MouseMoveEvent&) override {} }; struct PyApplication: PublicizedApplication { @@ -51,12 +54,53 @@ void glfw(py::module& m) { drawEvent ); } + + void mousePressEvent(MouseEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "mouse_press_event", + mousePressEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + + void mouseReleaseEvent(MouseEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "mouse_release_event", + mouseReleaseEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + + void mouseMoveEvent(MouseMoveEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "mouse_move_event", + mouseMoveEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } }; py::class_ glfwApplication{m, "Application", "GLFW application"}; /** @todo def_property_writeonly for swap_interval */ + py::class_ mouseEvent_{glfwApplication, "MouseEvent", "Mouse event"}; + py::class_ mouseMoveEvent_{glfwApplication, "MouseMoveEvent", "Mouse move event"}; + application(glfwApplication); + mouseEvent(mouseEvent_); + mouseMoveEvent(mouseMoveEvent_); } }}} diff --git a/src/python/magnum/platform/sdl2.cpp b/src/python/magnum/platform/sdl2.cpp index 219322c..26d83dd 100644 --- a/src/python/magnum/platform/sdl2.cpp +++ b/src/python/magnum/platform/sdl2.cpp @@ -38,6 +38,9 @@ void sdl2(py::module& m) { explicit PublicizedApplication(const Configuration& configuration, const GLConfiguration& glConfiguration): Platform::Application{Arguments{argc, nullptr}, configuration, glConfiguration} {} void drawEvent() override = 0; + void mousePressEvent(MouseEvent&) override {} + void mouseReleaseEvent(MouseEvent&) override {} + void mouseMoveEvent(MouseMoveEvent&) override {} }; struct PyApplication: PublicizedApplication { @@ -51,6 +54,46 @@ void sdl2(py::module& m) { drawEvent ); } + + /* PYBIND11_OVERLOAD_NAME() calls object_api::operator() with implicit + template param, which is return_value_policy::automatic_reference. + That later gets changed to return_value_policy::copy in + type_caster_base::cast() and there's no way to override that */ + void mousePressEvent(MouseEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "mouse_press_event", + mousePressEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + + void mouseReleaseEvent(MouseEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "mouse_release_event", + mouseReleaseEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } + + void mouseMoveEvent(MouseMoveEvent& event) override { + PYBIND11_OVERLOAD_NAME( + void, + PublicizedApplication, + "mouse_move_event", + mouseMoveEvent, + /* Have to use std::ref() otherwise pybind tries to copy + it and fails */ + std::ref(event) + ); + } }; py::class_ sdl2application{m, "Application", "SDL2 application"}; @@ -60,7 +103,12 @@ void sdl2(py::module& m) { self.setSwapInterval(interval); }, "Swap interval"); + py::class_ mouseEvent_{sdl2application, "MouseEvent", "Mouse event"}; + py::class_ mouseMoveEvent_{sdl2application, "MouseMoveEvent", "Mouse move event"}; + application(sdl2application); + mouseEvent(mouseEvent_); + mouseMoveEvent(mouseMoveEvent_); } }}}