Skip to content

Commit

Permalink
[GUI] Support mouse wheel event on Win32 (taichi-dev#1382)
Browse files Browse the repository at this point in the history
* [GUI] Support mouse wheel event on Win32
[doc] Update document about GUI event.
[Example] Update keyboard.py example , to show wheel event processing

* [GUI] Simplify implementation of events

* [Example][doc] Update example and doc

* [skip ci] enforce code format

* [skip ci] Word modifications

* [skip ci] change 'WHEEL' to 'Wheel'

* [GUI] fix up KeyEvent position value problem

* [skip ci] Using ScreenToClient instead

* [skip ci] rename to canvas_untransform

Co-authored-by: Taichi Gardener <[email protected]>
  • Loading branch information
JYLeeLYJ and Taichi Gardener authored Jul 5, 2020
1 parent 0af2351 commit b709fb6
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 29 deletions.
8 changes: 4 additions & 4 deletions docs/gui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ Every event have a key and type.
...
ti.GUI.LMB # Left Mouse Button
ti.GUI.RMB # Right Mouse Button
ti.GUI.WHEEL # Mouse Wheel Scrolling

*Event type* is the type of event, for now, there are just three type of event:

::

ti.GUI.RELEASE # key up
ti.GUI.PRESS # key down
ti.GUI.MOTION # mouse moved

ti.GUI.RELEASE # key up or mouse button up
ti.GUI.PRESS # key down or mouse button down
ti.GUI.MOTION # mouse motion or mouse wheel

A *event filter* is a list combined of *key*, *type* and *(type, key)* tuple, e.g.:

Expand Down
14 changes: 12 additions & 2 deletions examples/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@

x, y = 0.5, 0.5
delta = 0.01
radius = 8

gui = ti.GUI("Keyboard", res=(400, 400))

while gui.running:
while gui.get_event(ti.GUI.PRESS):
while gui.get_event(ti.GUI.PRESS, ti.GUI.MOTION):
if gui.event.key == ti.GUI.ESCAPE:
gui.running = False
elif gui.event.key == ti.GUI.RMB:
x, y = gui.event.pos
elif gui.event.key == ti.GUI.WHEEL:
x, y = gui.event.pos
dt = gui.event.delta
# delta is 2-dim vector (dx,dy)
# dx(dt[0]) denotes the horizontal direction , and dy(dt[1]) denotes the vertical direction
if dt[1] > 0:
radius += 10
elif dt[1] < 0:
radius = max(8, radius - 10)

if gui.is_pressed(ti.GUI.LEFT, 'a'):
x -= delta
Expand All @@ -25,5 +35,5 @@

gui.text(f'({x:.3}, {y:.3})', (x, y))

gui.circle((x, y), 0xffffff, 8)
gui.circle((x, y), 0xffffff, radius)
gui.show()
25 changes: 19 additions & 6 deletions python/taichi/misc/gui.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import numbers
import numpy as np

from taichi import ti_core


class GUI:
class Event:
pass

# Event keys
SHIFT = 'Shift'
ALT = 'Alt'
CTRL = 'Control'
Expand All @@ -19,13 +22,16 @@ class Event:
LEFT = 'Left'
RIGHT = 'Right'
CAPSLOCK = 'Caps_Lock'
MOTION = 'Motion'
LMB = 'LMB'
MMB = 'MMB'
RMB = 'RMB'
EXIT = 'WMClose'
RELEASE = False
PRESS = True
WHEEL = 'Wheel'

# Event types
MOTION = ti_core.KeyEvent.EType.Move
PRESS = ti_core.KeyEvent.EType.Press
RELEASE = ti_core.KeyEvent.EType.Release

def __init__(self, name, res=512, background_color=0x0):
import taichi as ti
Expand Down Expand Up @@ -230,12 +236,19 @@ def get_events(self, *filter):

def get_key_event(self):
self.core.wait_key_event()

e = GUI.Event()
e.key = self.core.get_key_event_head_key()
e.type = self.core.get_key_event_head_type()
e.pos = self.core.get_key_event_head_pos()
event = self.core.get_key_event_head()

e.type = event.type
e.key = event.key
e.pos = self.core.canvas_untransform(event.pos)
e.pos = (e.pos[0], e.pos[1])
e.modifier = []

if e.key == GUI.WHEEL:
e.delta = event.delta

for mod in ['Shift', 'Alt', 'Control']:
if self.is_pressed(mod):
e.modifier.append(mod)
Expand Down
17 changes: 7 additions & 10 deletions taichi/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ class GUI : public GUIBase {
Type type;
std::string key;
Vector2i pos;
Vector2i delta;
};

std::vector<KeyEvent> key_events;
Expand Down Expand Up @@ -829,16 +830,8 @@ class GUI : public GUIBase {
}
}

std::string get_key_event_head_key() {
return key_events[0].key;
}

bool get_key_event_head_type() {
return key_events[0].type == KeyEvent::Type::press;
}

Vector2 get_key_event_head_pos() {
return canvas->untransform(Vector2(key_events[0].pos));
KeyEvent get_key_event_head() {
return key_events[0];
}

Vector2 get_cursor_pos() {
Expand All @@ -859,6 +852,10 @@ class GUI : public GUIBase {
}
}

Vector2 canvas_untransform(Vector2i pos) {
return canvas->untransform(Vector2(pos));
}

void draw_log() {
for (int i = 0; i < (int)log_entries.size(); i++) {
canvas->text(log_entries[i], Vector2(0.0, -0.02_f * i), 15, Vector4(0));
Expand Down
23 changes: 19 additions & 4 deletions taichi/gui/win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd,
auto dc = GetDC(hwnd);
auto gui = gui_from_hwnd[hwnd];
using namespace taichi;
int x, y;
POINT p{};
switch (uMsg) {
case WM_LBUTTONDOWN:
gui->mouse_event(
Expand Down Expand Up @@ -98,12 +98,27 @@ LRESULT CALLBACK WindowProc(HWND hwnd,
GUI::KeyEvent{GUI::KeyEvent::Type::release, "RMB", gui->cursor_pos});
break;
case WM_MOUSEMOVE:
x = GET_X_LPARAM(lParam);
y = GET_Y_LPARAM(lParam);
gui->set_mouse_pos(x, gui->height - 1 - y);
p = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
gui->set_mouse_pos(p.x, gui->height - 1 - p.y);
gui->mouse_event(
GUI::MouseEvent{GUI::MouseEvent::Type::move, gui->cursor_pos});
break;
case WM_MOUSEWHEEL:
p = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
ScreenToClient(hwnd, &p);
gui->set_mouse_pos(p.x, gui->height - 1 - p.y);
gui->key_events.push_back(
GUI::KeyEvent{GUI::KeyEvent::Type::move, "Wheel", gui->cursor_pos,
Vector2i{0, GET_WHEEL_DELTA_WPARAM(wParam)}});
break;
case WM_MOUSEHWHEEL:
p = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
ScreenToClient(hwnd, &p);
gui->set_mouse_pos(p.x, gui->height - 1 - p.y);
gui->key_events.push_back(
GUI::KeyEvent{GUI::KeyEvent::Type::move, "Wheel", gui->cursor_pos,
Vector2i{GET_WHEEL_DELTA_WPARAM(wParam), 0}});
break;
case WM_PAINT:
break;
case WM_KEYDOWN:
Expand Down
16 changes: 13 additions & 3 deletions taichi/python/export_visual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ void export_visual(py::module &m) {
// GUI
using Line = Canvas::Line;
using Circle = Canvas::Circle;
using Type = GUI::KeyEvent::Type;

auto key_event = py::class_<GUI::KeyEvent>(m, "KeyEvent");
key_event.def_readonly("type", &GUI::KeyEvent::type)
.def_readonly("key", &GUI::KeyEvent::key)
.def_readonly("pos", &GUI::KeyEvent::pos)
.def_readonly("delta", &GUI::KeyEvent::delta);
py::enum_<GUI::KeyEvent::Type>(key_event, "EType")
.value("Move", Type::move)
.value("Press", Type::press)
.value("Release", Type::release);
py::class_<GUI>(m, "GUI")
.def(py::init<std::string, Vector2i>())
.def_readwrite("should_close", &GUI::should_close)
Expand All @@ -24,11 +35,10 @@ void export_visual(py::module &m) {
img.get_data_size());
})
.def("screenshot", &GUI::screenshot)
.def("canvas_untransform", &GUI::canvas_untransform)
.def("has_key_event", &GUI::has_key_event)
.def("wait_key_event", &GUI::wait_key_event)
.def("get_key_event_head_key", &GUI::get_key_event_head_key)
.def("get_key_event_head_type", &GUI::get_key_event_head_type)
.def("get_key_event_head_pos", &GUI::get_key_event_head_pos)
.def("get_key_event_head", &GUI::get_key_event_head)
.def("pop_key_event_head", &GUI::pop_key_event_head)
.def("get_cursor_pos", &GUI::get_cursor_pos)
.def_readwrite("title", &GUI::window_name)
Expand Down

0 comments on commit b709fb6

Please sign in to comment.