Browse Source

python: expose key and scroll events.

pull/8/head
Vladimír Vondruš 7 years ago
parent
commit
9afe7ebe50
  1. 8
      src/python/magnum/platform/CMakeLists.txt
  2. 158
      src/python/magnum/platform/application.h
  3. 55
      src/python/magnum/platform/glfw.cpp
  4. 51
      src/python/magnum/platform/sdl2.cpp

8
src/python/magnum/platform/CMakeLists.txt

@ -27,7 +27,9 @@ if(NOT MAGNUM_BUILD_STATIC)
if(Magnum_GlfwApplication_FOUND)
pybind11_add_module(magnum_platform_glfw SYSTEM glfw.cpp)
target_link_libraries(magnum_platform_glfw PRIVATE Magnum::GlfwApplication)
target_include_directories(magnum_platform_glfw PRIVATE ${CMAKE_SOURCE_DIR}/src/python)
target_include_directories(magnum_platform_glfw PRIVATE
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/src/python)
set_target_properties(magnum_platform_glfw PROPERTIES
FOLDER "python/platform"
OUTPUT_NAME "glfw"
@ -37,7 +39,9 @@ if(NOT MAGNUM_BUILD_STATIC)
if(Magnum_Sdl2Application_FOUND)
pybind11_add_module(magnum_platform_sdl2 SYSTEM sdl2.cpp)
target_link_libraries(magnum_platform_sdl2 PRIVATE Magnum::Sdl2Application)
target_include_directories(magnum_platform_sdl2 PRIVATE ${CMAKE_SOURCE_DIR}/src/python)
target_include_directories(magnum_platform_sdl2 PRIVATE
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/src/python)
set_target_properties(magnum_platform_sdl2 PROPERTIES
FOLDER "python/platform"
OUTPUT_NAME "sdl2"

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

@ -1,3 +1,5 @@
#ifndef magnum_platform_application_h
#define magnum_platform_application_h
/*
This file is part of Magnum.
@ -68,14 +70,144 @@ template<class T, class Trampoline> void application(py::class_<T, Trampoline>&
/* Event handlers */
.def("draw_event", &T::drawEvent, "Draw event")
.def("key_press_event", &T::keyPressEvent, "Key press event")
.def("key_release_event", &T::keyReleaseEvent, "Key release 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")
.def("mouse_scroll_event", &T::mouseScrollEvent, "Mouse scroll event")
/** @todo more */
;
}
template<class T> void mouseEvent(py::class_<T>& c) {
template<class T, class ...Args> void inputEvent(py::class_<T, Args...>& c) {
py::enum_<typename T::Modifier>{c, "Modifier", "Modifier"}
.value("SHIFT", T::Modifier::Shift)
.value("CTRL", T::Modifier::Ctrl)
.value("ALT", T::Modifier::Alt)
.value("SUPER", T::Modifier::Super);
c.def_property("accepted", &T::isAccepted, &T::setAccepted, "Accepted status of the event");
}
template<class T, class ...Args> void keyEvent(py::class_<T, Args...>& c) {
py::enum_<typename T::Key>{c, "Key", "Key"}
.value("UNKNOWN", T::Key::Unknown)
.value("LEFT_SHIFT", T::Key::LeftShift)
.value("RIGHT_SHIFT", T::Key::RightShift)
.value("LEFT_CTRL", T::Key::LeftCtrl)
.value("RIGHT_CTRL", T::Key::RightCtrl)
.value("LEFT_ALT", T::Key::LeftAlt)
.value("RIGHT_ALT", T::Key::RightAlt)
.value("LEFT_SUPER", T::Key::LeftSuper)
.value("RIGHT_SUPER", T::Key::RightSuper)
.value("ENTER", T::Key::Enter)
.value("ESC", T::Key::Esc)
.value("UP", T::Key::Up)
.value("DOWN", T::Key::Down)
.value("LEFT", T::Key::Left)
.value("RIGHT", T::Key::Right)
.value("HOME", T::Key::Home)
.value("END", T::Key::End)
.value("PAGE_UP", T::Key::PageUp)
.value("PAGE_DOWN", T::Key::PageDown)
.value("BACKSPACE", T::Key::Backspace)
.value("INSERT", T::Key::Insert)
.value("DELETE", T::Key::Delete)
.value("F1", T::Key::F1)
.value("F2", T::Key::F2)
.value("F3", T::Key::F3)
.value("F4", T::Key::F4)
.value("F5", T::Key::F5)
.value("F6", T::Key::F6)
.value("F7", T::Key::F7)
.value("F8", T::Key::F8)
.value("F9", T::Key::F9)
.value("F10", T::Key::F10)
.value("F11", T::Key::F11)
.value("F12", T::Key::F12)
.value("SPACE", T::Key::Space)
.value("TAB", T::Key::Tab)
.value("COMMA", T::Key::Comma)
.value("PERIOD", T::Key::Period)
.value("MINUS", T::Key::Minus)
.value("PLUS", T::Key::Plus)
.value("SLASH", T::Key::Slash)
.value("PERCENT", T::Key::Percent)
.value("SEMICOLON", T::Key::Semicolon)
.value("EQUAL", T::Key::Equal)
.value("ZERO", T::Key::Zero)
.value("ONE", T::Key::One)
.value("TWO", T::Key::Two)
.value("THREE", T::Key::Three)
.value("FOUR", T::Key::Four)
.value("FIVE", T::Key::Five)
.value("SIX", T::Key::Six)
.value("SEVEN", T::Key::Seven)
.value("EIGHT", T::Key::Eight)
.value("NINE", T::Key::Nine)
.value("A", T::Key::A)
.value("B", T::Key::B)
.value("C", T::Key::C)
.value("D", T::Key::D)
.value("E", T::Key::E)
.value("F", T::Key::F)
.value("G", T::Key::G)
.value("H", T::Key::H)
.value("I", T::Key::I)
.value("J", T::Key::J)
.value("K", T::Key::K)
.value("L", T::Key::L)
.value("M", T::Key::M)
.value("N", T::Key::N)
.value("O", T::Key::O)
.value("P", T::Key::P)
.value("Q", T::Key::Q)
.value("R", T::Key::R)
.value("S", T::Key::S)
.value("T", T::Key::T)
.value("U", T::Key::U)
.value("V", T::Key::V)
.value("W", T::Key::W)
.value("X", T::Key::X)
.value("Y", T::Key::Y)
.value("Z", T::Key::Z)
.value("NUM_ZERO", T::Key::NumZero)
.value("NUM_ONE", T::Key::NumOne)
.value("NUM_TWO", T::Key::NumTwo)
.value("NUM_THREE", T::Key::NumThree)
.value("NUM_FOUR", T::Key::NumFour)
.value("NUM_FIVE", T::Key::NumFive)
.value("NUM_SIX", T::Key::NumSix)
.value("NUM_SEVEN", T::Key::NumSeven)
.value("NUM_EIGHT", T::Key::NumEight)
.value("NUM_NINE", T::Key::NumNine)
.value("NUM_DECIMAL", T::Key::NumDecimal)
.value("NUM_DIVIDE", T::Key::NumDivide)
.value("NUM_MULTIPLY", T::Key::NumMultiply)
.value("NUM_SUBTRACT", T::Key::NumSubtract)
.value("NUM_ADD", T::Key::NumAdd)
.value("NUM_ENTER", T::Key::NumEnter)
.value("NUM_EQUAL", T::Key::NumEqual);
c
.def_property_readonly("key", &T::key, "Key")
/** @todo key name? useful? useles?? */
.def_property_readonly("modifiers", [](T& self) {
return typename T::Modifier(typename std::underlying_type<typename T::Modifier>::type(self.modifiers()));
}, "Modifiers")
.def_property_readonly("is_repeated", &T::isRepeated, "Whether the key press is repeated");
}
template<class T, class ...Args> void mouseEvent(py::class_<T, Args...>& c) {
py::enum_<typename T::Button>{c, "Button", "Mouse button"}
.value("LEFT", T::Button::Left)
.value("MIDDLE", T::Button::Middle)
@ -83,10 +215,13 @@ template<class T> void mouseEvent(py::class_<T>& c) {
c
.def_property_readonly("button", &T::button, "Button")
.def_property_readonly("position", &T::position, "Position");
.def_property_readonly("position", &T::position, "Position")
.def_property_readonly("modifiers", [](T& self) {
return typename T::Modifier(typename std::underlying_type<typename T::Modifier>::type(self.modifiers()));
}, "Modifiers");
}
template<class T> void mouseMoveEvent(py::class_<T>& c) {
template<class T, class ...Args> void mouseMoveEvent(py::class_<T, Args...>& c) {
py::enum_<typename T::Button> buttons{c, "Buttons", "Set of mouse buttons"};
buttons
.value("LEFT", T::Button::Left)
@ -96,9 +231,24 @@ template<class T> void mouseMoveEvent(py::class_<T>& c) {
c
.def_property_readonly("position", &T::position, "Position")
.def_property_readonly("relative_position", &T::position, "Relative position")
.def_property_readonly("buttons", [](T& self) {
return typename T::Button(typename std::underlying_type<typename T::Button>::type(self.buttons()));
}, "Mouse buttons");
}, "Mouse buttons")
.def_property_readonly("modifiers", [](T& self) {
return typename T::Modifier(typename std::underlying_type<typename T::Modifier>::type(self.modifiers()));
}, "Modifiers");
}
template<class T, class ...Args> void mouseScrollEvent(py::class_<T, Args...>& c) {
c
.def_property_readonly("offset", &T::offset, "Offset")
.def_property_readonly("position", &T::position, "Position")
.def_property_readonly("modifiers", [](T& self) {
return typename T::Modifier(typename std::underlying_type<typename T::Modifier>::type(self.modifiers()));
}, "Modifiers");
}
}}
#endif

55
src/python/magnum/platform/glfw.cpp

@ -26,6 +26,8 @@
#include <pybind11/pybind11.h>
#include <Magnum/Platform/GlfwApplication.h>
#include "Corrade/Python.h"
#include "magnum/bootstrap.h"
#include "magnum/platform/application.h"
@ -51,9 +53,12 @@ void glfw(py::module& m) {
void drawEvent() override = 0;
#endif
void keyPressEvent(KeyEvent&) override {}
void keyReleaseEvent(KeyEvent&) override {}
void mousePressEvent(MouseEvent&) override {}
void mouseReleaseEvent(MouseEvent&) override {}
void mouseMoveEvent(MouseMoveEvent&) override {}
void mouseScrollEvent(MouseScrollEvent&) override {}
/* The base doesn't have a virtual destructor because in C++ it's never
deleted through a pointer to the base. Here we need it, though. */
@ -82,6 +87,33 @@ void glfw(py::module& m) {
#endif
}
/* 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 keyPressEvent(KeyEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
PublicizedApplication,
"key_press_event",
keyPressEvent,
/* Have to use std::ref() otherwise pybind tries to copy
it and fails */
std::ref(event)
);
}
void keyReleaseEvent(KeyEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
PublicizedApplication,
"key_release_event",
keyReleaseEvent,
/* Have to use std::ref() otherwise pybind tries to copy
it and fails */
std::ref(event)
);
}
void mousePressEvent(MouseEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
@ -93,7 +125,6 @@ void glfw(py::module& m) {
std::ref(event)
);
}
void mouseReleaseEvent(MouseEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
@ -105,7 +136,6 @@ void glfw(py::module& m) {
std::ref(event)
);
}
void mouseMoveEvent(MouseMoveEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
@ -117,17 +147,34 @@ void glfw(py::module& m) {
std::ref(event)
);
}
void mouseScrollEvent(MouseScrollEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
PublicizedApplication,
"mouse_scroll_event",
mouseScrollEvent,
/* 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"};
PyNonDestructibleClass<PublicizedApplication::InputEvent> inputEvent_{glfwApplication, "InputEvent", "Base for input events"};
py::class_<PublicizedApplication::KeyEvent, PublicizedApplication::InputEvent> keyEvent_{glfwApplication, "KeyEvent", "Key event"};
py::class_<PublicizedApplication::MouseEvent, PublicizedApplication::InputEvent> mouseEvent_{glfwApplication, "MouseEvent", "Mouse event"};
py::class_<PublicizedApplication::MouseMoveEvent, PublicizedApplication::InputEvent> mouseMoveEvent_{glfwApplication, "MouseMoveEvent", "Mouse move event"};
py::class_<PublicizedApplication::MouseScrollEvent, PublicizedApplication::InputEvent> mouseScrollEvent_{glfwApplication, "MouseScrollEvent", "Mouse scroll event"};
application(glfwApplication);
inputEvent(inputEvent_);
keyEvent(keyEvent_);
mouseEvent(mouseEvent_);
mouseMoveEvent(mouseMoveEvent_);
mouseScrollEvent(mouseScrollEvent_);
}
}}

51
src/python/magnum/platform/sdl2.cpp

@ -26,6 +26,8 @@
#include <pybind11/pybind11.h>
#include <Magnum/Platform/Sdl2Application.h>
#include "Corrade/Python.h"
#include "magnum/bootstrap.h"
#include "magnum/platform/application.h"
@ -51,9 +53,12 @@ void sdl2(py::module& m) {
void drawEvent() override = 0;
#endif
void keyPressEvent(KeyEvent&) override {}
void keyReleaseEvent(KeyEvent&) override {}
void mousePressEvent(MouseEvent&) override {}
void mouseReleaseEvent(MouseEvent&) override {}
void mouseMoveEvent(MouseMoveEvent&) override {}
void mouseScrollEvent(MouseScrollEvent&) override {}
/* The base doesn't have a virtual destructor because in C++ it's never
deleted through a pointer to the base. Here we need it, though. */
@ -86,6 +91,29 @@ void sdl2(py::module& m) {
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 keyPressEvent(KeyEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
PublicizedApplication,
"key_press_event",
keyPressEvent,
/* Have to use std::ref() otherwise pybind tries to copy
it and fails */
std::ref(event)
);
}
void keyReleaseEvent(KeyEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
PublicizedApplication,
"key_release_event",
keyReleaseEvent,
/* Have to use std::ref() otherwise pybind tries to copy
it and fails */
std::ref(event)
);
}
void mousePressEvent(MouseEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
@ -97,7 +125,6 @@ void sdl2(py::module& m) {
std::ref(event)
);
}
void mouseReleaseEvent(MouseEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
@ -109,7 +136,6 @@ void sdl2(py::module& m) {
std::ref(event)
);
}
void mouseMoveEvent(MouseMoveEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
@ -121,6 +147,17 @@ void sdl2(py::module& m) {
std::ref(event)
);
}
void mouseScrollEvent(MouseScrollEvent& event) override {
PYBIND11_OVERLOAD_NAME(
void,
PublicizedApplication,
"mouse_scroll_event",
mouseScrollEvent,
/* 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"};
@ -130,12 +167,18 @@ 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"};
PyNonDestructibleClass<PublicizedApplication::InputEvent> inputEvent_{sdl2application, "InputEvent", "Base for input events"};
py::class_<PublicizedApplication::KeyEvent, PublicizedApplication::InputEvent> keyEvent_{sdl2application, "KeyEvent", "Key event"};
py::class_<PublicizedApplication::MouseEvent, PublicizedApplication::InputEvent> mouseEvent_{sdl2application, "MouseEvent", "Mouse event"};
py::class_<PublicizedApplication::MouseMoveEvent, PublicizedApplication::InputEvent> mouseMoveEvent_{sdl2application, "MouseMoveEvent", "Mouse move event"};
py::class_<PublicizedApplication::MouseScrollEvent, PublicizedApplication::InputEvent> mouseScrollEvent_{sdl2application, "MouseScrollEvent", "Mouse scroll event"};
application(sdl2application);
inputEvent(inputEvent_);
keyEvent(keyEvent_);
mouseEvent(mouseEvent_);
mouseMoveEvent(mouseMoveEvent_);
mouseScrollEvent(mouseScrollEvent_);
}
}}

Loading…
Cancel
Save