Browse Source

python: implement basic mouse events for SDL2 and GLFW apps.

This took a while because I wasn't able to convince pybind to do what I
want.
pull/1/head
Vladimír Vondruš 7 years ago
parent
commit
670537d664
  1. 32
      src/python/magnum/platform/application.h
  2. 44
      src/python/magnum/platform/glfw.cpp
  3. 48
      src/python/magnum/platform/sdl2.cpp

32
src/python/magnum/platform/application.h

@ -25,6 +25,7 @@
#include <pybind11/pybind11.h>
#include "corrade/EnumOperators.h"
#include "magnum/bootstrap.h"
namespace magnum { namespace platform {
@ -62,11 +63,42 @@ template<class T, class Trampoline> void application(py::class_<T, Trampoline>&
.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<class T> void mouseEvent(py::class_<T>& c) {
py::enum_<typename T::Button>{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<class T> void mouseMoveEvent(py::class_<T>& c) {
py::enum_<typename T::Button> 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<typename T::Button>::type(self.buttons()));
}, "Mouse buttons");
}
}}

44
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_<PublicizedApplication, PyApplication> glfwApplication{m, "Application", "GLFW application"};
/** @todo def_property_writeonly for swap_interval */
py::class_<PyApplication::MouseEvent> mouseEvent_{glfwApplication, "MouseEvent", "Mouse event"};
py::class_<PyApplication::MouseMoveEvent> mouseMoveEvent_{glfwApplication, "MouseMoveEvent", "Mouse move event"};
application(glfwApplication);
mouseEvent(mouseEvent_);
mouseMoveEvent(mouseMoveEvent_);
}
}}}

48
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_<PublicizedApplication, PyApplication> sdl2application{m, "Application", "SDL2 application"};
@ -60,7 +103,12 @@ void sdl2(py::module& m) {
self.setSwapInterval(interval);
}, "Swap interval");
py::class_<PublicizedApplication::MouseEvent> mouseEvent_{sdl2application, "MouseEvent", "Mouse event"};
py::class_<PublicizedApplication::MouseMoveEvent> mouseMoveEvent_{sdl2application, "MouseMoveEvent", "Mouse move event"};
application(sdl2application);
mouseEvent(mouseEvent_);
mouseMoveEvent(mouseMoveEvent_);
}
}}}

Loading…
Cancel
Save