| 1 | # Allow mouse modes to work with mouse on Acer or Sony 3D displays.
|
|---|
| 2 | # Both these displays create a fullscreen window. This mouse mode support
|
|---|
| 3 | # works by creating a backing full-screen Qt window which receives the
|
|---|
| 4 | # mouse events.
|
|---|
| 5 |
|
|---|
| 6 | def enable_xr_mouse_modes(session):
|
|---|
| 7 | screen = find_xr_screen(session)
|
|---|
| 8 | from Qt.QtWidgets import QWidget
|
|---|
| 9 | w = QWidget()
|
|---|
| 10 | session._xr_mouse_backing_window = w
|
|---|
| 11 | w.move(screen.geometry().topLeft())
|
|---|
| 12 | w.showFullScreen()
|
|---|
| 13 | w.mousePressEvent = lambda e: dispatch_mouse_event(e, "mouse_down", session)
|
|---|
| 14 | w.mouseMoveEvent = lambda e: dispatch_mouse_event(e, "mouse_drag", session)
|
|---|
| 15 | w.mouseReleaseEvent = lambda e: dispatch_mouse_event(e, "mouse_up", session)
|
|---|
| 16 | w.mouseDoubleClickEvent = lambda e: dispatch_mouse_event(e, "mouse_double_click", session)
|
|---|
| 17 | w.wheelEvent = lambda e: dispatch_wheel_event(e, session)
|
|---|
| 18 |
|
|---|
| 19 | def dispatch_mouse_event(event, action, session):
|
|---|
| 20 | '''
|
|---|
| 21 | Convert a mouse event from 3D screen coordinates to
|
|---|
| 22 | graphics pane coordinates and dispatch it.
|
|---|
| 23 | '''
|
|---|
| 24 | p = event.position()
|
|---|
| 25 | gx, gy = map_event_coordinates(p.x(), p.y(), session)
|
|---|
| 26 | e = repositioned_event(event, gx, gy)
|
|---|
| 27 | session.ui.mouse_modes._dispatch_mouse_event(e, action)
|
|---|
| 28 |
|
|---|
| 29 | def dispatch_wheel_event(event, session):
|
|---|
| 30 | '''
|
|---|
| 31 | Convert a wheel event from 3D screen coordinates to
|
|---|
| 32 | graphics pane coordinates and dispatch it.
|
|---|
| 33 | '''
|
|---|
| 34 | p = event.position()
|
|---|
| 35 | gx, gy = map_event_coordinates(p.x(), p.y(), session)
|
|---|
| 36 | e = repositioned_event(event, gx, gy)
|
|---|
| 37 | session.ui.mouse_modes._wheel_event(e)
|
|---|
| 38 |
|
|---|
| 39 | def map_event_coordinates(x, y, session):
|
|---|
| 40 | '''
|
|---|
| 41 | Handle different aspect ratio of 3D screen window and
|
|---|
| 42 | graphics window. Graphics window has cropped version
|
|---|
| 43 | of 3D window image.
|
|---|
| 44 | '''
|
|---|
| 45 | w3d = session._xr_mouse_backing_window
|
|---|
| 46 | w, h = w3d.width(), w3d.height()
|
|---|
| 47 | gw, gh = session.main_view.window_size
|
|---|
| 48 | if w == 0 or h == 0 or gw == 0 or gh == 0:
|
|---|
| 49 | return x, y
|
|---|
| 50 | fx,fy = x/w, y/h
|
|---|
| 51 | af = w*gh/(h*gw)
|
|---|
| 52 | if af > 1:
|
|---|
| 53 | afx = 0.5 + af * (fx - 0.5)
|
|---|
| 54 | afy = fy
|
|---|
| 55 | else:
|
|---|
| 56 | afx = fx
|
|---|
| 57 | afy = 0.5 + (1/af) * (fy - 0.5)
|
|---|
| 58 | gx, gy = afx * gw, afy * gh
|
|---|
| 59 | return gx, gy
|
|---|
| 60 |
|
|---|
| 61 | def repositioned_event(event, x, y):
|
|---|
| 62 | from Qt.QtGui import QMouseEvent, QWheelEvent
|
|---|
| 63 | from Qt.QtCore import QPointF
|
|---|
| 64 | pos = QPointF(x, y)
|
|---|
| 65 | if isinstance(event, QMouseEvent):
|
|---|
| 66 | e = QMouseEvent(event.type(), pos, event.globalPosition(), event.button(), event.buttons(), event.modifiers(), event.device())
|
|---|
| 67 | elif isinstance(event, QWheelEvent):
|
|---|
| 68 | e = QWheelEvent(pos, event.globalPosition(), event.pixelDelta(), event.angleDelta(), event.buttons(), event.modifiers(), event.phase(), event.inverted(), device = event.device())
|
|---|
| 69 | else:
|
|---|
| 70 | raise RuntimeError(f'Event type is not mouse or wheel event {event}')
|
|---|
| 71 | return e
|
|---|
| 72 |
|
|---|
| 73 | def find_xr_screen(session):
|
|---|
| 74 | known_screen_models = ['ASV27-2P']
|
|---|
| 75 | screens = session.ui.screens()
|
|---|
| 76 | for screen in screens:
|
|---|
| 77 | if screen.model() in known_screen_models:
|
|---|
| 78 | return screen
|
|---|
| 79 | mnames = [screen.model() for screen in screens]
|
|---|
| 80 | msg = f'Could not find Acer 3D screen model {", ".join(known_screen_models)} , only found {", ".join(mnames)}'
|
|---|
| 81 | raise RuntimeError(msg)
|
|---|
| 82 |
|
|---|
| 83 | enable_xr_mouse_modes(session)
|
|---|
| 84 |
|
|---|
| 85 | # When OpenXR turned off delete the backing window with
|
|---|
| 86 | # session._xr_mouse_backing_window.deleteLater()
|
|---|
| 87 | # session._xr_mouse_backing_window = None
|
|---|