vispy 0.9.5__cp38-cp38-win_amd64.whl → 0.14.0__cp38-cp38-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of vispy might be problematic. Click here for more details.

Files changed (103) hide show
  1. vispy/app/backends/_glfw.py +2 -2
  2. vispy/app/backends/_pyglet.py +8 -2
  3. vispy/app/backends/_qt.py +88 -63
  4. vispy/app/backends/_wx.py +6 -1
  5. vispy/app/canvas.py +4 -2
  6. vispy/app/tests/test_canvas.py +52 -1
  7. vispy/app/tests/test_context.py +5 -3
  8. vispy/color/color_array.py +8 -1
  9. vispy/color/colormap.py +5 -25
  10. vispy/geometry/meshdata.py +76 -38
  11. vispy/geometry/rect.py +6 -0
  12. vispy/geometry/tests/test_meshdata.py +72 -0
  13. vispy/gloo/buffer.py +12 -0
  14. vispy/gloo/gl/_constants.py +9 -5
  15. vispy/gloo/gl/_es2.py +8 -4
  16. vispy/gloo/gl/_gl2.py +2 -3
  17. vispy/gloo/gl/_proxy.py +1 -1
  18. vispy/gloo/gl/_pyopengl2.py +12 -7
  19. vispy/gloo/gl/tests/test_names.py +3 -0
  20. vispy/gloo/glir.py +26 -13
  21. vispy/gloo/program.py +39 -22
  22. vispy/gloo/tests/test_program.py +9 -2
  23. vispy/gloo/tests/test_texture.py +19 -2
  24. vispy/gloo/texture.py +46 -16
  25. vispy/gloo/wrappers.py +4 -2
  26. vispy/glsl/build_spatial_filters.py +241 -293
  27. vispy/glsl/misc/spatial-filters.frag +1299 -254
  28. vispy/io/_data/spatial-filters.npy +0 -0
  29. vispy/io/datasets.py +2 -2
  30. vispy/io/image.py +1 -1
  31. vispy/io/stl.py +3 -3
  32. vispy/scene/cameras/base_camera.py +6 -2
  33. vispy/scene/cameras/panzoom.py +10 -14
  34. vispy/scene/cameras/perspective.py +6 -0
  35. vispy/scene/cameras/tests/test_cameras.py +27 -0
  36. vispy/scene/cameras/tests/test_perspective.py +37 -0
  37. vispy/scene/cameras/turntable.py +39 -23
  38. vispy/scene/canvas.py +9 -5
  39. vispy/scene/events.py +9 -0
  40. vispy/scene/node.py +19 -2
  41. vispy/scene/tests/test_canvas.py +30 -1
  42. vispy/scene/tests/test_visuals.py +113 -0
  43. vispy/scene/visuals.py +6 -1
  44. vispy/scene/widgets/viewbox.py +3 -2
  45. vispy/testing/_runners.py +6 -12
  46. vispy/testing/_testing.py +3 -4
  47. vispy/util/check_environment.py +4 -4
  48. vispy/util/gallery_scraper.py +50 -32
  49. vispy/util/tests/test_gallery_scraper.py +2 -0
  50. vispy/util/transforms.py +1 -1
  51. vispy/util/wrappers.py +1 -1
  52. vispy/version.py +2 -3
  53. vispy/visuals/__init__.py +2 -0
  54. vispy/visuals/_scalable_textures.py +20 -17
  55. vispy/visuals/collections/array_list.py +3 -3
  56. vispy/visuals/collections/base_collection.py +1 -1
  57. vispy/visuals/ellipse.py +1 -1
  58. vispy/visuals/filters/__init__.py +3 -2
  59. vispy/visuals/filters/base_filter.py +120 -0
  60. vispy/visuals/filters/clipping_planes.py +24 -12
  61. vispy/visuals/filters/markers.py +28 -0
  62. vispy/visuals/filters/mesh.py +61 -6
  63. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  64. vispy/visuals/graphs/graph.py +1 -1
  65. vispy/visuals/image.py +114 -26
  66. vispy/visuals/image_complex.py +130 -0
  67. vispy/visuals/instanced_mesh.py +152 -0
  68. vispy/visuals/isocurve.py +1 -1
  69. vispy/visuals/line/dash_atlas.py +46 -41
  70. vispy/visuals/line/line.py +2 -5
  71. vispy/visuals/markers.py +310 -384
  72. vispy/visuals/mesh.py +2 -2
  73. vispy/visuals/shaders/function.py +3 -0
  74. vispy/visuals/shaders/tests/test_function.py +6 -0
  75. vispy/visuals/tests/test_axis.py +2 -2
  76. vispy/visuals/tests/test_image.py +92 -2
  77. vispy/visuals/tests/test_image_complex.py +36 -0
  78. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  79. vispy/visuals/tests/test_markers.py +6 -0
  80. vispy/visuals/tests/test_mesh.py +17 -0
  81. vispy/visuals/tests/test_text.py +11 -0
  82. vispy/visuals/tests/test_volume.py +218 -12
  83. vispy/visuals/text/_sdf_cpu.cp38-win_amd64.pyd +0 -0
  84. vispy/visuals/text/_sdf_cpu.pyx +21 -23
  85. vispy/visuals/text/text.py +9 -3
  86. vispy/visuals/tube.py +2 -2
  87. vispy/visuals/visual.py +144 -3
  88. vispy/visuals/volume.py +300 -131
  89. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/LICENSE.txt +1 -1
  90. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/METADATA +218 -198
  91. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/RECORD +93 -96
  92. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/WHEEL +1 -1
  93. vispy/glsl/antialias/__init__.py +0 -0
  94. vispy/glsl/arrowheads/__init__.py +0 -0
  95. vispy/glsl/arrows/__init__.py +0 -0
  96. vispy/glsl/collections/__init__.py +0 -0
  97. vispy/glsl/colormaps/__init__.py +0 -0
  98. vispy/glsl/lines/__init__.py +0 -0
  99. vispy/glsl/markers/__init__.py +0 -0
  100. vispy/glsl/math/__init__.py +0 -0
  101. vispy/glsl/misc/__init__.py +0 -0
  102. vispy/glsl/transforms/__init__.py +0 -0
  103. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/top_level.txt +0 -0
@@ -27,7 +27,7 @@ glfw = None
27
27
  try:
28
28
  import glfw
29
29
  except ImportError:
30
- why_not = "Could not import glwf, you may need to `pip install glfw` first."
30
+ why_not = "Could not import glfw, you may need to `pip install glfw` first."
31
31
  available, testable, why_not, which = False, False, why_not, None
32
32
  except Exception as err:
33
33
  why_not = "Error importing glfw: " + str(err)
@@ -250,7 +250,7 @@ class CanvasBackend(BaseCanvasBackend):
250
250
  raise ValueError('fullscreen must be <= %s'
251
251
  % len(monitor))
252
252
  monitor = monitor[p.fullscreen]
253
- use_size = glfw.get_video_mode(monitor)[:2]
253
+ use_size = glfw.get_video_mode(monitor)[0][:2]
254
254
  if use_size != tuple(p.size):
255
255
  logger.debug('Requested size %s, will be ignored to '
256
256
  'use fullscreen mode %s' % (p.size, use_size))
@@ -6,7 +6,7 @@
6
6
 
7
7
  from __future__ import division
8
8
 
9
- from distutils.version import LooseVersion
9
+ from packaging.version import Version
10
10
  from time import sleep
11
11
 
12
12
  from ..base import (BaseApplicationBackend, BaseCanvasBackend,
@@ -23,7 +23,7 @@ USE_EGL = config['gl_backend'].lower().startswith('es')
23
23
  try:
24
24
  import pyglet
25
25
  version = pyglet.version
26
- if LooseVersion(version) < LooseVersion('1.2'):
26
+ if Version(version) < Version('1.2'):
27
27
  help_ = ('You can install the latest pyglet using:\n '
28
28
  'pip install http://pyglet.googlecode.com/archive/tip.zip')
29
29
  raise ImportError('Pyglet version too old (%s), need >= 1.2\n%s'
@@ -271,6 +271,12 @@ class CanvasBackend(BaseCanvasBackend, _Window):
271
271
  w, h = self.get_size()
272
272
  return w, h
273
273
 
274
+ def _vispy_get_physical_size(self):
275
+ if self._vispy_canvas is None:
276
+ return
277
+ w, h = self.get_framebuffer_size()
278
+ return w, h
279
+
274
280
  def _vispy_get_position(self):
275
281
  x, y = self.get_location()
276
282
  return x, y
vispy/app/backends/_qt.py CHANGED
@@ -22,11 +22,12 @@ known to cause unpredictable behavior and segfaults.
22
22
  from __future__ import division
23
23
 
24
24
  from time import sleep, time
25
+ import math
25
26
  import os
26
27
  import sys
27
28
  import atexit
28
29
  import ctypes
29
- from distutils.version import LooseVersion
30
+ from packaging.version import Version
30
31
 
31
32
  from ...util import logger
32
33
  from ..base import (BaseApplicationBackend, BaseCanvasBackend,
@@ -90,19 +91,19 @@ elif qt_lib == 'pyqt5':
90
91
  _check_imports('PyQt5')
91
92
  if not USE_EGL:
92
93
  from PyQt5.QtCore import QT_VERSION_STR
93
- if LooseVersion(QT_VERSION_STR) >= '5.4.0':
94
+ if Version(QT_VERSION_STR) >= Version('5.4.0'):
94
95
  from PyQt5.QtWidgets import QOpenGLWidget as QGLWidget
95
96
  from PyQt5.QtGui import QSurfaceFormat as QGLFormat
96
97
  QT5_NEW_API = True
97
98
  else:
98
99
  from PyQt5.QtOpenGL import QGLWidget, QGLFormat
99
100
  from PyQt5 import QtGui, QtCore, QtWidgets, QtTest
100
- QWidget, QApplication = QtWidgets.QWidget, QtWidgets.QApplication #
101
+ QWidget, QApplication = QtWidgets.QWidget, QtWidgets.QApplication # Compat
101
102
  elif qt_lib == 'pyqt6':
102
103
  _check_imports('PyQt6')
103
104
  if not USE_EGL:
104
105
  from PyQt6.QtCore import QT_VERSION_STR
105
- if LooseVersion(QT_VERSION_STR) >= '6.0.0':
106
+ if Version(QT_VERSION_STR) >= Version('6.0.0'):
106
107
  from PyQt6.QtOpenGLWidgets import QOpenGLWidget as QGLWidget
107
108
  from PyQt6.QtGui import QSurfaceFormat as QGLFormat
108
109
  PYQT6_API = True
@@ -114,7 +115,7 @@ elif qt_lib == 'pyside6':
114
115
  _check_imports('PySide6')
115
116
  if not USE_EGL:
116
117
  from PySide6.QtCore import __version__ as QT_VERSION_STR
117
- if LooseVersion(QT_VERSION_STR) >= '6.0.0':
118
+ if Version(QT_VERSION_STR) >= Version('6.0.0'):
118
119
  from PySide6.QtOpenGLWidgets import QOpenGLWidget as QGLWidget
119
120
  from PySide6.QtGui import QSurfaceFormat as QGLFormat
120
121
  PYSIDE6_API = True
@@ -126,7 +127,7 @@ elif qt_lib == 'pyside2':
126
127
  _check_imports('PySide2')
127
128
  if not USE_EGL:
128
129
  from PySide2.QtCore import __version__ as QT_VERSION_STR
129
- if LooseVersion(QT_VERSION_STR) >= '5.4.0':
130
+ if Version(QT_VERSION_STR) >= Version('5.4.0'):
130
131
  from PySide2.QtWidgets import QOpenGLWidget as QGLWidget
131
132
  from PySide2.QtGui import QSurfaceFormat as QGLFormat
132
133
  QT5_NEW_API = True
@@ -191,7 +192,7 @@ KEYMAP = {
191
192
  qt_keys.Key_Return: keys.ENTER,
192
193
  qt_keys.Key_Tab: keys.TAB,
193
194
  }
194
- if PYQT6_API:
195
+ if PYQT6_API or PYSIDE6_API:
195
196
  BUTTONMAP = {
196
197
  QtCore.Qt.MouseButton.NoButton: 0,
197
198
  QtCore.Qt.MouseButton.LeftButton: 1,
@@ -278,11 +279,11 @@ def _set_config(c):
278
279
  glformat.setGreenBufferSize(c['green_size'])
279
280
  glformat.setBlueBufferSize(c['blue_size'])
280
281
  glformat.setAlphaBufferSize(c['alpha_size'])
281
- if QT5_NEW_API or PYSIDE6_API:
282
+ if QT5_NEW_API:
282
283
  # Qt5 >= 5.4.0 - below options automatically enabled if nonzero.
283
284
  glformat.setSwapBehavior(glformat.DoubleBuffer if c['double_buffer']
284
285
  else glformat.SingleBuffer)
285
- elif PYQT6_API:
286
+ elif PYQT6_API or PYSIDE6_API:
286
287
  glformat.setSwapBehavior(glformat.SwapBehavior.DoubleBuffer if c['double_buffer']
287
288
  else glformat.SwapBehavior.SingleBuffer)
288
289
  else:
@@ -410,17 +411,10 @@ class QtBaseCanvasBackend(BaseCanvasBackend):
410
411
  # either not PyQt5 backend or no parent window available
411
412
  pass
412
413
 
413
- # Activate touch and gesture.
414
- # NOTE: we only activate touch on OS X because there seems to be
415
- # problems on Ubuntu computers with touchscreen.
416
- # See https://github.com/vispy/vispy/pull/1143
417
- if sys.platform == 'darwin':
418
- if PYQT6_API:
419
- self.setAttribute(QtCore.Qt.WidgetAttribute.WA_AcceptTouchEvents)
420
- self.grabGesture(QtCore.Qt.GestureType.PinchGesture)
421
- else:
422
- self.setAttribute(QtCore.Qt.WA_AcceptTouchEvents)
423
- self.grabGesture(QtCore.Qt.PinchGesture)
414
+ # QNativeGestureEvent does not keep track of last or total
415
+ # values like QGestureEvent does
416
+ self._native_gesture_scale_values = []
417
+ self._native_gesture_rotation_values = []
424
418
 
425
419
  def screen_changed(self, new_screen):
426
420
  """Window moved from one display to another, resize canvas.
@@ -563,50 +557,81 @@ class QtBaseCanvasBackend(BaseCanvasBackend):
563
557
  def keyReleaseEvent(self, ev):
564
558
  self._keyEvent(self._vispy_canvas.events.key_release, ev)
565
559
 
560
+ def _handle_native_gesture_event(self, ev):
561
+ if self._vispy_canvas is None:
562
+ return
563
+ t = ev.gestureType()
564
+ # this is a workaround for what looks like a Qt bug where
565
+ # QNativeGestureEvent gives the wrong local position.
566
+ # See: https://bugreports.qt.io/browse/QTBUG-59595
567
+ try:
568
+ pos = self.mapFromGlobal(ev.globalPosition().toPoint())
569
+ except AttributeError:
570
+ # globalPos is deprecated in Qt6
571
+ pos = self.mapFromGlobal(ev.globalPos())
572
+ pos = pos.x(), pos.y()
573
+
574
+ if t == QtCore.Qt.NativeGestureType.BeginNativeGesture:
575
+ self._vispy_canvas.events.touch(
576
+ type='gesture_begin',
577
+ pos=_get_event_xy(ev),
578
+ )
579
+ elif t == QtCore.Qt.NativeGestureType.EndNativeGesture:
580
+ self._native_touch_total_rotation = []
581
+ self._native_touch_total_scale = []
582
+ self._vispy_canvas.events.touch(
583
+ type='gesture_end',
584
+ pos=_get_event_xy(ev),
585
+ )
586
+ elif t == QtCore.Qt.NativeGestureType.RotateNativeGesture:
587
+ angle = ev.value()
588
+ last_angle = (
589
+ self._native_gesture_rotation_values[-1]
590
+ if self._native_gesture_rotation_values
591
+ else None
592
+ )
593
+ self._native_gesture_rotation_values.append(angle)
594
+ total_rotation_angle = math.fsum(self._native_gesture_rotation_values)
595
+ self._vispy_canvas.events.touch(
596
+ type="gesture_rotate",
597
+ pos=pos,
598
+ rotation=angle,
599
+ last_rotation=last_angle,
600
+ total_rotation_angle=total_rotation_angle,
601
+ )
602
+ elif t == QtCore.Qt.NativeGestureType.ZoomNativeGesture:
603
+ scale = ev.value()
604
+ last_scale = (
605
+ self._native_gesture_scale_values[-1]
606
+ if self._native_gesture_scale_values
607
+ else None
608
+ )
609
+ self._native_gesture_scale_values.append(scale)
610
+ total_scale_factor = math.fsum(self._native_gesture_scale_values)
611
+ self._vispy_canvas.events.touch(
612
+ type="gesture_zoom",
613
+ pos=pos,
614
+ last_scale=last_scale,
615
+ scale=scale,
616
+ total_scale_factor=total_scale_factor,
617
+ )
618
+ # QtCore.Qt.NativeGestureType.PanNativeGesture
619
+ # Qt6 docs seem to imply this is only supported on Wayland but I have
620
+ # not been able to test it.
621
+ # Two finger pan events are anyway converted to scroll/wheel events.
622
+ # On macOS, more fingers are usually swallowed by the OS (by spaces,
623
+ # mission control, etc.).
624
+
566
625
  def event(self, ev):
567
626
  out = super(QtBaseCanvasBackend, self).event(ev)
568
- t = ev.type()
569
-
570
- qt_event_types = QtCore.QEvent.Type if PYQT6_API else QtCore.QEvent
571
- # Two-finger pinch.
572
- if t == qt_event_types.TouchBegin:
573
- self._vispy_canvas.events.touch(type='begin')
574
- if t == qt_event_types.TouchEnd:
575
- self._vispy_canvas.events.touch(type='end')
576
- if t == qt_event_types.Gesture:
577
- pinch_gesture = QtCore.Qt.GestureType.PinchGesture if PYQT6_API else QtCore.Qt.PinchGesture
578
- gesture = ev.gesture(pinch_gesture)
579
- if gesture:
580
- (x, y) = _get_qpoint_pos(gesture.centerPoint())
581
- scale = gesture.scaleFactor()
582
- last_scale = gesture.lastScaleFactor()
583
- rotation = gesture.rotationAngle()
584
- self._vispy_canvas.events.touch(
585
- type="pinch",
586
- pos=(x, y),
587
- last_pos=None,
588
- scale=scale,
589
- last_scale=last_scale,
590
- rotation=rotation,
591
- total_rotation_angle=gesture.totalRotationAngle(),
592
- total_scale_factor=gesture.totalScaleFactor(),
593
- )
594
- # General touch event.
595
- elif t == qt_event_types.TouchUpdate:
596
- if qt_lib == 'pyqt6' or qt_lib == 'pyside6':
597
- points = ev.points()
598
- # These variables are lists of (x, y) coordinates.
599
- pos = [_get_qpoint_pos(p.position()) for p in points]
600
- lpos = [_get_qpoint_pos(p.lastPosition()) for p in points]
601
- else:
602
- points = ev.touchPoints()
603
- # These variables are lists of (x, y) coordinates.
604
- pos = [_get_qpoint_pos(p.pos()) for p in points]
605
- lpos = [_get_qpoint_pos(p.lastPos()) for p in points]
606
- self._vispy_canvas.events.touch(type='touch',
607
- pos=pos,
608
- last_pos=lpos,
609
- )
627
+
628
+ # QNativeGestureEvent is Qt 5+
629
+ if (
630
+ (QT5_NEW_API or PYSIDE6_API or PYQT6_API)
631
+ and isinstance(ev, QtGui.QNativeGestureEvent)
632
+ ):
633
+ self._handle_native_gesture_event(ev)
634
+
610
635
  return out
611
636
 
612
637
  def _keyEvent(self, func, ev):
@@ -630,7 +655,7 @@ class QtBaseCanvasBackend(BaseCanvasBackend):
630
655
  [qt_keyboard_modifiers.ControlModifier, keys.CONTROL],
631
656
  [qt_keyboard_modifiers.AltModifier, keys.ALT],
632
657
  [qt_keyboard_modifiers.MetaModifier, keys.META]):
633
- if q & qtmod:
658
+ if qtmod & q:
634
659
  mod += (v,)
635
660
  return mod
636
661
 
vispy/app/backends/_wx.py CHANGED
@@ -376,6 +376,11 @@ class CanvasBackend(GLCanvas, BaseCanvasBackend):
376
376
  w, h = self.GetClientSize()
377
377
  return w, h
378
378
 
379
+ def _vispy_get_physical_size(self):
380
+ w, h = self.GetClientSize()
381
+ ratio = self.GetContentScaleFactor()
382
+ return int(w * ratio), int(h * ratio)
383
+
379
384
  def _vispy_get_position(self):
380
385
  if self._vispy_canvas is None:
381
386
  return
@@ -461,7 +466,7 @@ class TimerBackend(BaseTimerBackend):
461
466
  parent.Bind(wx.EVT_TIMER, self._vispy_timeout, self._timer)
462
467
 
463
468
  def _vispy_start(self, interval):
464
- self._timer.Start(interval * 1000., False)
469
+ self._timer.Start(int(interval * 1000.), False)
465
470
 
466
471
  def _vispy_stop(self):
467
472
  self._timer.Stop()
vispy/app/canvas.py CHANGED
@@ -606,7 +606,7 @@ class MouseEvent(Event):
606
606
  will return the button that started the drag (same thing as
607
607
  ``event.press_event.button``).
608
608
  buttons : [int, ...]
609
- The list of buttons depressed during this event.
609
+ The list of buttons pressed during this event.
610
610
  modifiers : tuple of Key instances
611
611
  Tuple that specifies which modifier keys were pressed down at the
612
612
  time of the event (shift, control, alt, meta).
@@ -632,7 +632,9 @@ class MouseEvent(Event):
632
632
  Event.__init__(self, type, **kwargs)
633
633
  self._pos = np.array([0, 0]) if (pos is None) else np.array(pos)
634
634
  self._button = int(button) if (button is not None) else None
635
- self._buttons = [] if (buttons is None) else buttons
635
+ # Explicitly add button to buttons if newly pressed, check #2344 for more reference
636
+ newly_pressed_buttons = [button] if button is not None and type == 'mouse_press' else []
637
+ self._buttons = [] if (buttons is None) else buttons + newly_pressed_buttons
636
638
  self._modifiers = tuple(modifiers or ())
637
639
  self._delta = np.zeros(2) if (delta is None) else np.array(delta)
638
640
  self._last_event = last_event
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) Vispy Development Team. All Rights Reserved.
3
3
  # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
4
 
5
- from vispy.app import Canvas
5
+ from vispy.app import Canvas, MouseEvent
6
6
  from vispy.visuals import ImageVisual
7
7
  from vispy.testing import requires_application
8
8
  from vispy.visuals.transforms import STTransform
@@ -68,4 +68,55 @@ def test_canvas_render(blend_func):
68
68
  np.testing.assert_allclose(rgba_result[..., 3], 255)
69
69
  else:
70
70
  # the alpha should have some transparency
71
+ # this part of this test fails on macOS 12 at the moment
72
+ # see https://github.com/vispy/vispy/pull/2324#issuecomment-1163350672
71
73
  assert (rgba_result[..., 3] != 255).any()
74
+
75
+
76
+ @requires_application()
77
+ @pytest.mark.parametrize(
78
+ 'preset',
79
+ [
80
+ 'opaque', 'additive', 'translucent',
81
+ ])
82
+ def test_blend_presets(preset):
83
+ """Test blending presets a canvas to an array.
84
+
85
+ Different blending presets are used to test that they properly set
86
+ blend equations.
87
+
88
+ """
89
+ with Canvas(size=(125, 125), show=True, title='run') as c:
90
+ im1 = np.zeros((100, 100, 4)).astype(np.float32)
91
+ im1[:, :, 1] = 1
92
+ im1[:, :, 3] = .4
93
+ # Create the image
94
+ image1 = ImageVisual(im1)
95
+ image1.transform = STTransform(translate=(20, 20, -1))
96
+ image1.transforms.configure(canvas=c, viewport=(0, 0, 125, 125))
97
+
98
+ gloo.set_state(blend_equation='min')
99
+ image1.set_gl_state(preset)
100
+
101
+ @c.events.draw.connect
102
+ def on_draw(ev):
103
+ gloo.clear('black')
104
+ gloo.set_viewport(0, 0, *c.physical_size)
105
+ image1.draw()
106
+
107
+ rgba_result = c.render()
108
+ assert not np.allclose(rgba_result[..., :3], 0)
109
+
110
+
111
+ @requires_application()
112
+ @pytest.mark.parametrize("mouse_event_type, button, buttons, expected_button, expected_buttons", [
113
+ ('mouse_press', 1, [], 1, [1]),
114
+ ('mouse_release', 1, [1], 1, [1]),
115
+ # left click pressed and held, followed by a right click
116
+ ('mouse_press', 2, [1], 2, [1, 2]),
117
+ ('mouse_release', 2, [1, 2], 2, [1, 2]),
118
+ ])
119
+ def test_mouse_event(mouse_event_type, button, buttons, expected_button, expected_buttons):
120
+ mev = MouseEvent(type=mouse_event_type, button=button, buttons=buttons)
121
+ assert mev.buttons == expected_buttons
122
+ assert mev.button == expected_button
@@ -17,6 +17,8 @@ def test_context_properties():
17
17
  return # cannot set more than once on Pyglet
18
18
  if a.backend_name.lower() == 'osmesa':
19
19
  return # cannot set config on OSMesa
20
+ if 'pyqt5' in a.backend_name.lower() or 'pyqt6' in a.backend_name.lower() or 'pyside2' in a.backend_name.lower() or 'pyside6' in a.backend_name.lower():
21
+ pytest.xfail("Context sharing is not supported in PyQt5, PyQt6, PySide2, or PySide6 at this time.")
20
22
 
21
23
  # stereo, double buffer won't work on every sys
22
24
  configs = [dict(samples=4), dict(stencil_size=8),
@@ -68,9 +70,9 @@ def test_context_sharing():
68
70
  # Check while c1 is active
69
71
  check()
70
72
 
71
- # pyqt5 does not currently support context sharing
72
- if 'pyqt5' in c1.app.backend_name.lower() or 'pyqt6' in c1.app.backend_name.lower():
73
- pytest.xfail("Context sharing is not supported in PyQt5 at this time.")
73
+ # pyqt5 does not currently support context sharing, pyside6 seg faults on app tests
74
+ if 'pyqt5' in c1.app.backend_name.lower() or 'pyqt6' in c1.app.backend_name.lower() or 'pyside2' in c1.app.backend_name.lower() or 'pyside6' in c1.app.backend_name.lower():
75
+ pytest.xfail("Context sharing is not supported in PyQt5, PyQt6, PySide2, or PySide6 at this time.")
74
76
 
75
77
  # Tkinter does not currently support context sharing
76
78
  if 'tk' in c1.app.backend_name.lower():
@@ -21,7 +21,7 @@ def _string_to_rgb(color):
21
21
  if not color.startswith('#'):
22
22
  if color.lower() not in _color_dict:
23
23
  raise ValueError('Color "%s" unknown' % color)
24
- color = _color_dict[color]
24
+ color = _color_dict[color.lower()]
25
25
  assert color[0] == '#'
26
26
  # hex color
27
27
  color = color[1:]
@@ -163,6 +163,13 @@ class ColorArray(object):
163
163
  """Helper to get the class name once it's been created"""
164
164
  return cls.__name__
165
165
 
166
+ def __array__(self, dtype=None):
167
+ """Get a standard numpy array representing RGBA."""
168
+ rgba = self.rgba
169
+ if dtype is not None:
170
+ rgba = rgba.astype(dtype)
171
+ return rgba
172
+
166
173
  def __len__(self):
167
174
  return self._rgba.shape[0]
168
175
 
vispy/color/colormap.py CHANGED
@@ -435,7 +435,7 @@ class Colormap(BaseColormap):
435
435
  if self.texture_map_data is None:
436
436
  return None
437
437
  interp = 'linear' if self.interpolation == 'linear' else 'nearest'
438
- texture_LUT = vispy.gloo.Texture2D(np.zeros(self.texture_map_data.shape),
438
+ texture_LUT = vispy.gloo.Texture2D(np.zeros(self.texture_map_data.shape, dtype=np.float32),
439
439
  interpolation=interp)
440
440
  texture_LUT.set_data(self.texture_map_data, offset=None, copy=True)
441
441
  return texture_LUT
@@ -1092,17 +1092,13 @@ _colormaps = dict(
1092
1092
  )
1093
1093
 
1094
1094
 
1095
- def get_colormap(name, *args, **kwargs):
1096
- """Obtain a colormap.
1095
+ def get_colormap(name):
1096
+ """Obtain a colormap by name.
1097
1097
 
1098
1098
  Parameters
1099
1099
  ----------
1100
1100
  name : str | Colormap
1101
1101
  Colormap name. Can also be a Colormap for pass-through.
1102
- *args:
1103
- Deprecated.
1104
- **kwargs
1105
- Deprecated.
1106
1102
 
1107
1103
  Examples
1108
1104
  --------
@@ -1111,18 +1107,10 @@ def get_colormap(name, *args, **kwargs):
1111
1107
 
1112
1108
  .. versionchanged: 0.7
1113
1109
 
1114
- Additional args/kwargs are no longer accepted. Colormap classes are
1115
- no longer created on the fly. To create a ``cubehelix``
1116
- (``CubeHelixColormap``), ``single_hue`` (``SingleHue``), ``hsl``
1117
- (``HSL``), ``husl`` (``HSLuv``), ``diverging`` (``Diverging``), or
1118
- ``RdYeBuCy`` (``RedYellowBlueCyan``) colormap you must import and
1119
- instantiate it directly from the ``vispy.color.colormap`` module.
1110
+ Additional args/kwargs are no longer accepted. Colormap instances are
1111
+ no longer created on the fly.
1120
1112
 
1121
1113
  """
1122
- if args or kwargs:
1123
- warnings.warn("Creating a Colormap instance with 'get_colormap' is "
1124
- "no longer supported. No additional arguments or "
1125
- "keyword arguments should be passed.", DeprecationWarning)
1126
1114
  if isinstance(name, BaseColormap):
1127
1115
  return name
1128
1116
 
@@ -1130,14 +1118,6 @@ def get_colormap(name, *args, **kwargs):
1130
1118
  raise TypeError('colormap must be a Colormap or string name')
1131
1119
  if name in _colormaps: # vispy cmap
1132
1120
  cmap = _colormaps[name]
1133
- if name in ("cubehelix", "single_hue", "hsl", "husl", "diverging", "RdYeBuCy"):
1134
- warnings.warn(
1135
- f"Colormap '{name}' has been deprecated since vispy 0.7. "
1136
- f"Please import and create 'vispy.color.colormap.{cmap.__class__.__name__}' "
1137
- "directly instead.",
1138
- DeprecationWarning,
1139
- stacklevel=2,
1140
- )
1141
1121
 
1142
1122
  elif has_matplotlib(): # matplotlib cmap
1143
1123
  try: