vispy 0.14.0__cp311-cp311-macosx_11_0_arm64.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 (519) hide show
  1. vispy/__init__.py +33 -0
  2. vispy/app/__init__.py +15 -0
  3. vispy/app/_default_app.py +76 -0
  4. vispy/app/_detect_eventloop.py +148 -0
  5. vispy/app/application.py +263 -0
  6. vispy/app/backends/__init__.py +52 -0
  7. vispy/app/backends/_egl.py +264 -0
  8. vispy/app/backends/_glfw.py +513 -0
  9. vispy/app/backends/_jupyter_rfb.py +278 -0
  10. vispy/app/backends/_offscreen_util.py +121 -0
  11. vispy/app/backends/_osmesa.py +235 -0
  12. vispy/app/backends/_pyglet.py +451 -0
  13. vispy/app/backends/_pyqt4.py +36 -0
  14. vispy/app/backends/_pyqt5.py +36 -0
  15. vispy/app/backends/_pyqt6.py +40 -0
  16. vispy/app/backends/_pyside.py +37 -0
  17. vispy/app/backends/_pyside2.py +52 -0
  18. vispy/app/backends/_pyside6.py +53 -0
  19. vispy/app/backends/_qt.py +968 -0
  20. vispy/app/backends/_sdl2.py +444 -0
  21. vispy/app/backends/_template.py +244 -0
  22. vispy/app/backends/_test.py +8 -0
  23. vispy/app/backends/_tk.py +800 -0
  24. vispy/app/backends/_wx.py +476 -0
  25. vispy/app/backends/tests/__init__.py +0 -0
  26. vispy/app/backends/tests/test_offscreen_util.py +52 -0
  27. vispy/app/backends/tests/test_rfb.py +77 -0
  28. vispy/app/base.py +294 -0
  29. vispy/app/canvas.py +828 -0
  30. vispy/app/qt.py +92 -0
  31. vispy/app/tests/__init__.py +0 -0
  32. vispy/app/tests/qt-designer.ui +58 -0
  33. vispy/app/tests/test_app.py +442 -0
  34. vispy/app/tests/test_backends.py +164 -0
  35. vispy/app/tests/test_canvas.py +122 -0
  36. vispy/app/tests/test_context.py +92 -0
  37. vispy/app/tests/test_qt.py +47 -0
  38. vispy/app/tests/test_simultaneous.py +134 -0
  39. vispy/app/timer.py +174 -0
  40. vispy/color/__init__.py +17 -0
  41. vispy/color/_color_dict.py +193 -0
  42. vispy/color/color_array.py +447 -0
  43. vispy/color/color_space.py +181 -0
  44. vispy/color/colormap.py +1134 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +352 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1542 -0
  50. vispy/ext/cubehelix.py +138 -0
  51. vispy/ext/egl.py +375 -0
  52. vispy/ext/fontconfig.py +118 -0
  53. vispy/ext/gdi32plus.py +206 -0
  54. vispy/ext/osmesa.py +105 -0
  55. vispy/geometry/__init__.py +23 -0
  56. vispy/geometry/_triangulation_debugger.py +171 -0
  57. vispy/geometry/calculations.py +134 -0
  58. vispy/geometry/curves.py +399 -0
  59. vispy/geometry/generation.py +643 -0
  60. vispy/geometry/isocurve.py +175 -0
  61. vispy/geometry/isosurface.py +465 -0
  62. vispy/geometry/meshdata.py +698 -0
  63. vispy/geometry/normals.py +78 -0
  64. vispy/geometry/parametric.py +56 -0
  65. vispy/geometry/polygon.py +137 -0
  66. vispy/geometry/rect.py +210 -0
  67. vispy/geometry/tests/__init__.py +0 -0
  68. vispy/geometry/tests/test_calculations.py +23 -0
  69. vispy/geometry/tests/test_generation.py +56 -0
  70. vispy/geometry/tests/test_meshdata.py +106 -0
  71. vispy/geometry/tests/test_triangulation.py +506 -0
  72. vispy/geometry/torusknot.py +142 -0
  73. vispy/geometry/triangulation.py +876 -0
  74. vispy/gloo/__init__.py +56 -0
  75. vispy/gloo/buffer.py +505 -0
  76. vispy/gloo/context.py +272 -0
  77. vispy/gloo/framebuffer.py +257 -0
  78. vispy/gloo/gl/__init__.py +234 -0
  79. vispy/gloo/gl/_constants.py +332 -0
  80. vispy/gloo/gl/_es2.py +986 -0
  81. vispy/gloo/gl/_gl2.py +1365 -0
  82. vispy/gloo/gl/_proxy.py +499 -0
  83. vispy/gloo/gl/_pyopengl2.py +362 -0
  84. vispy/gloo/gl/dummy.py +24 -0
  85. vispy/gloo/gl/es2.py +62 -0
  86. vispy/gloo/gl/gl2.py +98 -0
  87. vispy/gloo/gl/glplus.py +168 -0
  88. vispy/gloo/gl/pyopengl2.py +97 -0
  89. vispy/gloo/gl/tests/__init__.py +0 -0
  90. vispy/gloo/gl/tests/test_basics.py +282 -0
  91. vispy/gloo/gl/tests/test_functionality.py +566 -0
  92. vispy/gloo/gl/tests/test_names.py +246 -0
  93. vispy/gloo/gl/tests/test_use.py +71 -0
  94. vispy/gloo/glir.py +1816 -0
  95. vispy/gloo/globject.py +101 -0
  96. vispy/gloo/preprocessor.py +67 -0
  97. vispy/gloo/program.py +543 -0
  98. vispy/gloo/tests/__init__.py +0 -0
  99. vispy/gloo/tests/test_buffer.py +558 -0
  100. vispy/gloo/tests/test_context.py +119 -0
  101. vispy/gloo/tests/test_framebuffer.py +195 -0
  102. vispy/gloo/tests/test_glir.py +307 -0
  103. vispy/gloo/tests/test_globject.py +35 -0
  104. vispy/gloo/tests/test_program.py +302 -0
  105. vispy/gloo/tests/test_texture.py +732 -0
  106. vispy/gloo/tests/test_use_gloo.py +187 -0
  107. vispy/gloo/tests/test_util.py +60 -0
  108. vispy/gloo/tests/test_wrappers.py +261 -0
  109. vispy/gloo/texture.py +1045 -0
  110. vispy/gloo/util.py +129 -0
  111. vispy/gloo/wrappers.py +762 -0
  112. vispy/glsl/__init__.py +42 -0
  113. vispy/glsl/antialias/antialias.glsl +7 -0
  114. vispy/glsl/antialias/cap-butt.glsl +31 -0
  115. vispy/glsl/antialias/cap-round.glsl +29 -0
  116. vispy/glsl/antialias/cap-square.glsl +30 -0
  117. vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
  118. vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
  119. vispy/glsl/antialias/cap.glsl +67 -0
  120. vispy/glsl/antialias/caps.glsl +67 -0
  121. vispy/glsl/antialias/filled.glsl +50 -0
  122. vispy/glsl/antialias/outline.glsl +40 -0
  123. vispy/glsl/antialias/stroke.glsl +43 -0
  124. vispy/glsl/arrowheads/angle.glsl +99 -0
  125. vispy/glsl/arrowheads/arrowheads.frag +60 -0
  126. vispy/glsl/arrowheads/arrowheads.glsl +12 -0
  127. vispy/glsl/arrowheads/arrowheads.vert +83 -0
  128. vispy/glsl/arrowheads/curved.glsl +48 -0
  129. vispy/glsl/arrowheads/inhibitor.glsl +26 -0
  130. vispy/glsl/arrowheads/stealth.glsl +46 -0
  131. vispy/glsl/arrowheads/triangle.glsl +97 -0
  132. vispy/glsl/arrowheads/util.glsl +13 -0
  133. vispy/glsl/arrows/angle-30.glsl +12 -0
  134. vispy/glsl/arrows/angle-60.glsl +12 -0
  135. vispy/glsl/arrows/angle-90.glsl +12 -0
  136. vispy/glsl/arrows/arrow.frag +39 -0
  137. vispy/glsl/arrows/arrow.vert +49 -0
  138. vispy/glsl/arrows/arrows.glsl +17 -0
  139. vispy/glsl/arrows/common.glsl +187 -0
  140. vispy/glsl/arrows/curved.glsl +63 -0
  141. vispy/glsl/arrows/stealth.glsl +50 -0
  142. vispy/glsl/arrows/triangle-30.glsl +12 -0
  143. vispy/glsl/arrows/triangle-60.glsl +12 -0
  144. vispy/glsl/arrows/triangle-90.glsl +12 -0
  145. vispy/glsl/arrows/util.glsl +98 -0
  146. vispy/glsl/build_spatial_filters.py +660 -0
  147. vispy/glsl/collections/agg-fast-path.frag +20 -0
  148. vispy/glsl/collections/agg-fast-path.vert +78 -0
  149. vispy/glsl/collections/agg-glyph.frag +60 -0
  150. vispy/glsl/collections/agg-glyph.vert +33 -0
  151. vispy/glsl/collections/agg-marker.frag +35 -0
  152. vispy/glsl/collections/agg-marker.vert +48 -0
  153. vispy/glsl/collections/agg-path.frag +55 -0
  154. vispy/glsl/collections/agg-path.vert +166 -0
  155. vispy/glsl/collections/agg-point.frag +21 -0
  156. vispy/glsl/collections/agg-point.vert +35 -0
  157. vispy/glsl/collections/agg-segment.frag +32 -0
  158. vispy/glsl/collections/agg-segment.vert +75 -0
  159. vispy/glsl/collections/marker.frag +38 -0
  160. vispy/glsl/collections/marker.vert +48 -0
  161. vispy/glsl/collections/raw-path.frag +15 -0
  162. vispy/glsl/collections/raw-path.vert +24 -0
  163. vispy/glsl/collections/raw-point.frag +14 -0
  164. vispy/glsl/collections/raw-point.vert +31 -0
  165. vispy/glsl/collections/raw-segment.frag +18 -0
  166. vispy/glsl/collections/raw-segment.vert +26 -0
  167. vispy/glsl/collections/raw-triangle.frag +13 -0
  168. vispy/glsl/collections/raw-triangle.vert +26 -0
  169. vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
  170. vispy/glsl/collections/sdf-glyph.frag +80 -0
  171. vispy/glsl/collections/sdf-glyph.vert +59 -0
  172. vispy/glsl/collections/tick-labels.vert +71 -0
  173. vispy/glsl/colormaps/autumn.glsl +20 -0
  174. vispy/glsl/colormaps/blues.glsl +20 -0
  175. vispy/glsl/colormaps/color-space.glsl +17 -0
  176. vispy/glsl/colormaps/colormaps.glsl +24 -0
  177. vispy/glsl/colormaps/cool.glsl +20 -0
  178. vispy/glsl/colormaps/fire.glsl +21 -0
  179. vispy/glsl/colormaps/gray.glsl +20 -0
  180. vispy/glsl/colormaps/greens.glsl +20 -0
  181. vispy/glsl/colormaps/hot.glsl +22 -0
  182. vispy/glsl/colormaps/ice.glsl +20 -0
  183. vispy/glsl/colormaps/icefire.glsl +23 -0
  184. vispy/glsl/colormaps/parse.py +40 -0
  185. vispy/glsl/colormaps/reds.glsl +20 -0
  186. vispy/glsl/colormaps/spring.glsl +20 -0
  187. vispy/glsl/colormaps/summer.glsl +20 -0
  188. vispy/glsl/colormaps/user.glsl +22 -0
  189. vispy/glsl/colormaps/util.glsl +41 -0
  190. vispy/glsl/colormaps/wheel.glsl +21 -0
  191. vispy/glsl/colormaps/winter.glsl +20 -0
  192. vispy/glsl/lines/agg.frag +320 -0
  193. vispy/glsl/lines/agg.vert +241 -0
  194. vispy/glsl/markers/arrow.glsl +12 -0
  195. vispy/glsl/markers/asterisk.glsl +16 -0
  196. vispy/glsl/markers/chevron.glsl +14 -0
  197. vispy/glsl/markers/clover.glsl +20 -0
  198. vispy/glsl/markers/club.glsl +31 -0
  199. vispy/glsl/markers/cross.glsl +17 -0
  200. vispy/glsl/markers/diamond.glsl +12 -0
  201. vispy/glsl/markers/disc.glsl +9 -0
  202. vispy/glsl/markers/ellipse.glsl +67 -0
  203. vispy/glsl/markers/hbar.glsl +9 -0
  204. vispy/glsl/markers/heart.glsl +15 -0
  205. vispy/glsl/markers/infinity.glsl +15 -0
  206. vispy/glsl/markers/marker-sdf.frag +74 -0
  207. vispy/glsl/markers/marker-sdf.vert +41 -0
  208. vispy/glsl/markers/marker.frag +36 -0
  209. vispy/glsl/markers/marker.vert +46 -0
  210. vispy/glsl/markers/markers.glsl +24 -0
  211. vispy/glsl/markers/pin.glsl +18 -0
  212. vispy/glsl/markers/ring.glsl +11 -0
  213. vispy/glsl/markers/spade.glsl +28 -0
  214. vispy/glsl/markers/square.glsl +10 -0
  215. vispy/glsl/markers/tag.glsl +11 -0
  216. vispy/glsl/markers/triangle.glsl +14 -0
  217. vispy/glsl/markers/vbar.glsl +9 -0
  218. vispy/glsl/math/circle-through-2-points.glsl +30 -0
  219. vispy/glsl/math/constants.glsl +48 -0
  220. vispy/glsl/math/double.glsl +114 -0
  221. vispy/glsl/math/functions.glsl +20 -0
  222. vispy/glsl/math/point-to-line-distance.glsl +31 -0
  223. vispy/glsl/math/point-to-line-projection.glsl +29 -0
  224. vispy/glsl/math/signed-line-distance.glsl +27 -0
  225. vispy/glsl/math/signed-segment-distance.glsl +30 -0
  226. vispy/glsl/misc/regular-grid.frag +244 -0
  227. vispy/glsl/misc/spatial-filters.frag +1407 -0
  228. vispy/glsl/misc/viewport-NDC.glsl +20 -0
  229. vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
  230. vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
  231. vispy/glsl/transforms/hammer.glsl +44 -0
  232. vispy/glsl/transforms/identity.glsl +6 -0
  233. vispy/glsl/transforms/identity_forward.glsl +23 -0
  234. vispy/glsl/transforms/identity_inverse.glsl +23 -0
  235. vispy/glsl/transforms/linear-scale.glsl +127 -0
  236. vispy/glsl/transforms/log-scale.glsl +126 -0
  237. vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
  238. vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
  239. vispy/glsl/transforms/panzoom.glsl +10 -0
  240. vispy/glsl/transforms/polar.glsl +41 -0
  241. vispy/glsl/transforms/position.glsl +44 -0
  242. vispy/glsl/transforms/power-scale.glsl +139 -0
  243. vispy/glsl/transforms/projection.glsl +7 -0
  244. vispy/glsl/transforms/pvm.glsl +13 -0
  245. vispy/glsl/transforms/rotate.glsl +45 -0
  246. vispy/glsl/transforms/trackball.glsl +15 -0
  247. vispy/glsl/transforms/translate.glsl +35 -0
  248. vispy/glsl/transforms/transverse_mercator.glsl +38 -0
  249. vispy/glsl/transforms/viewport-clipping.glsl +14 -0
  250. vispy/glsl/transforms/viewport-transform.glsl +16 -0
  251. vispy/glsl/transforms/viewport.glsl +50 -0
  252. vispy/glsl/transforms/x.glsl +24 -0
  253. vispy/glsl/transforms/y.glsl +19 -0
  254. vispy/glsl/transforms/z.glsl +14 -0
  255. vispy/io/__init__.py +20 -0
  256. vispy/io/_data/spatial-filters.npy +0 -0
  257. vispy/io/datasets.py +94 -0
  258. vispy/io/image.py +231 -0
  259. vispy/io/mesh.py +122 -0
  260. vispy/io/stl.py +167 -0
  261. vispy/io/tests/__init__.py +0 -0
  262. vispy/io/tests/test_image.py +47 -0
  263. vispy/io/tests/test_io.py +121 -0
  264. vispy/io/wavefront.py +350 -0
  265. vispy/plot/__init__.py +36 -0
  266. vispy/plot/fig.py +58 -0
  267. vispy/plot/plotwidget.py +522 -0
  268. vispy/plot/tests/__init__.py +0 -0
  269. vispy/plot/tests/test_plot.py +46 -0
  270. vispy/scene/__init__.py +43 -0
  271. vispy/scene/cameras/__init__.py +27 -0
  272. vispy/scene/cameras/_base.py +38 -0
  273. vispy/scene/cameras/arcball.py +106 -0
  274. vispy/scene/cameras/base_camera.py +538 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +308 -0
  278. vispy/scene/cameras/perspective.py +333 -0
  279. vispy/scene/cameras/tests/__init__.py +0 -0
  280. vispy/scene/cameras/tests/test_cameras.py +27 -0
  281. vispy/scene/cameras/tests/test_link.py +53 -0
  282. vispy/scene/cameras/tests/test_perspective.py +122 -0
  283. vispy/scene/cameras/turntable.py +173 -0
  284. vispy/scene/canvas.py +639 -0
  285. vispy/scene/events.py +85 -0
  286. vispy/scene/node.py +644 -0
  287. vispy/scene/subscene.py +20 -0
  288. vispy/scene/tests/__init__.py +0 -0
  289. vispy/scene/tests/test_canvas.py +119 -0
  290. vispy/scene/tests/test_node.py +142 -0
  291. vispy/scene/tests/test_visuals.py +141 -0
  292. vispy/scene/visuals.py +276 -0
  293. vispy/scene/widgets/__init__.py +18 -0
  294. vispy/scene/widgets/anchor.py +25 -0
  295. vispy/scene/widgets/axis.py +88 -0
  296. vispy/scene/widgets/colorbar.py +176 -0
  297. vispy/scene/widgets/console.py +351 -0
  298. vispy/scene/widgets/grid.py +509 -0
  299. vispy/scene/widgets/label.py +50 -0
  300. vispy/scene/widgets/tests/__init__.py +0 -0
  301. vispy/scene/widgets/tests/test_colorbar.py +47 -0
  302. vispy/scene/widgets/viewbox.py +199 -0
  303. vispy/scene/widgets/widget.py +478 -0
  304. vispy/testing/__init__.py +51 -0
  305. vispy/testing/_runners.py +446 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +473 -0
  308. vispy/testing/rendered_array_tester.py +85 -0
  309. vispy/testing/tests/__init__.py +0 -0
  310. vispy/testing/tests/test_testing.py +20 -0
  311. vispy/util/__init__.py +17 -0
  312. vispy/util/bunch.py +15 -0
  313. vispy/util/check_environment.py +57 -0
  314. vispy/util/config.py +490 -0
  315. vispy/util/dpi/__init__.py +19 -0
  316. vispy/util/dpi/_linux.py +69 -0
  317. vispy/util/dpi/_quartz.py +26 -0
  318. vispy/util/dpi/_win32.py +34 -0
  319. vispy/util/dpi/tests/__init__.py +0 -0
  320. vispy/util/dpi/tests/test_dpi.py +16 -0
  321. vispy/util/eq.py +41 -0
  322. vispy/util/event.py +774 -0
  323. vispy/util/fetching.py +276 -0
  324. vispy/util/filter.py +44 -0
  325. vispy/util/fonts/__init__.py +14 -0
  326. vispy/util/fonts/_freetype.py +73 -0
  327. vispy/util/fonts/_quartz.py +192 -0
  328. vispy/util/fonts/_triage.py +36 -0
  329. vispy/util/fonts/_vispy_fonts.py +20 -0
  330. vispy/util/fonts/_win32.py +105 -0
  331. vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
  332. vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
  333. vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
  334. vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
  335. vispy/util/fonts/tests/__init__.py +0 -0
  336. vispy/util/fonts/tests/test_font.py +45 -0
  337. vispy/util/fourier.py +69 -0
  338. vispy/util/frozen.py +25 -0
  339. vispy/util/gallery_scraper.py +268 -0
  340. vispy/util/keys.py +91 -0
  341. vispy/util/logs.py +358 -0
  342. vispy/util/osmesa_gl.py +17 -0
  343. vispy/util/profiler.py +135 -0
  344. vispy/util/ptime.py +16 -0
  345. vispy/util/quaternion.py +229 -0
  346. vispy/util/svg/__init__.py +18 -0
  347. vispy/util/svg/base.py +20 -0
  348. vispy/util/svg/color.py +219 -0
  349. vispy/util/svg/element.py +51 -0
  350. vispy/util/svg/geometry.py +478 -0
  351. vispy/util/svg/group.py +66 -0
  352. vispy/util/svg/length.py +81 -0
  353. vispy/util/svg/number.py +25 -0
  354. vispy/util/svg/path.py +332 -0
  355. vispy/util/svg/shapes.py +57 -0
  356. vispy/util/svg/style.py +59 -0
  357. vispy/util/svg/svg.py +40 -0
  358. vispy/util/svg/transform.py +223 -0
  359. vispy/util/svg/transformable.py +28 -0
  360. vispy/util/svg/viewport.py +73 -0
  361. vispy/util/tests/__init__.py +0 -0
  362. vispy/util/tests/test_config.py +58 -0
  363. vispy/util/tests/test_docstring_parameters.py +123 -0
  364. vispy/util/tests/test_emitter_group.py +262 -0
  365. vispy/util/tests/test_event_emitter.py +743 -0
  366. vispy/util/tests/test_fourier.py +35 -0
  367. vispy/util/tests/test_gallery_scraper.py +112 -0
  368. vispy/util/tests/test_import.py +127 -0
  369. vispy/util/tests/test_key.py +22 -0
  370. vispy/util/tests/test_logging.py +45 -0
  371. vispy/util/tests/test_run.py +14 -0
  372. vispy/util/tests/test_transforms.py +42 -0
  373. vispy/util/tests/test_vispy.py +48 -0
  374. vispy/util/transforms.py +201 -0
  375. vispy/util/wrappers.py +155 -0
  376. vispy/version.py +4 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +485 -0
  379. vispy/visuals/axis.py +678 -0
  380. vispy/visuals/border.py +208 -0
  381. vispy/visuals/box.py +79 -0
  382. vispy/visuals/collections/__init__.py +30 -0
  383. vispy/visuals/collections/agg_fast_path_collection.py +219 -0
  384. vispy/visuals/collections/agg_path_collection.py +197 -0
  385. vispy/visuals/collections/agg_point_collection.py +52 -0
  386. vispy/visuals/collections/agg_segment_collection.py +142 -0
  387. vispy/visuals/collections/array_list.py +401 -0
  388. vispy/visuals/collections/base_collection.py +482 -0
  389. vispy/visuals/collections/collection.py +253 -0
  390. vispy/visuals/collections/path_collection.py +23 -0
  391. vispy/visuals/collections/point_collection.py +19 -0
  392. vispy/visuals/collections/polygon_collection.py +25 -0
  393. vispy/visuals/collections/raw_path_collection.py +119 -0
  394. vispy/visuals/collections/raw_point_collection.py +113 -0
  395. vispy/visuals/collections/raw_polygon_collection.py +77 -0
  396. vispy/visuals/collections/raw_segment_collection.py +112 -0
  397. vispy/visuals/collections/raw_triangle_collection.py +78 -0
  398. vispy/visuals/collections/segment_collection.py +19 -0
  399. vispy/visuals/collections/triangle_collection.py +16 -0
  400. vispy/visuals/collections/util.py +168 -0
  401. vispy/visuals/colorbar.py +699 -0
  402. vispy/visuals/cube.py +41 -0
  403. vispy/visuals/ellipse.py +163 -0
  404. vispy/visuals/filters/__init__.py +10 -0
  405. vispy/visuals/filters/base_filter.py +242 -0
  406. vispy/visuals/filters/clipper.py +60 -0
  407. vispy/visuals/filters/clipping_planes.py +122 -0
  408. vispy/visuals/filters/color.py +181 -0
  409. vispy/visuals/filters/markers.py +28 -0
  410. vispy/visuals/filters/mesh.py +796 -0
  411. vispy/visuals/filters/picking.py +60 -0
  412. vispy/visuals/filters/tests/__init__.py +3 -0
  413. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  414. vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
  415. vispy/visuals/glsl/__init__.py +1 -0
  416. vispy/visuals/glsl/antialiasing.py +133 -0
  417. vispy/visuals/glsl/color.py +63 -0
  418. vispy/visuals/graphs/__init__.py +1 -0
  419. vispy/visuals/graphs/graph.py +240 -0
  420. vispy/visuals/graphs/layouts/__init__.py +55 -0
  421. vispy/visuals/graphs/layouts/circular.py +49 -0
  422. vispy/visuals/graphs/layouts/force_directed.py +211 -0
  423. vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
  424. vispy/visuals/graphs/layouts/random.py +52 -0
  425. vispy/visuals/graphs/tests/__init__.py +1 -0
  426. vispy/visuals/graphs/tests/test_layouts.py +139 -0
  427. vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
  428. vispy/visuals/graphs/util.py +120 -0
  429. vispy/visuals/gridlines.py +105 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +688 -0
  433. vispy/visuals/image_complex.py +130 -0
  434. vispy/visuals/infinite_line.py +199 -0
  435. vispy/visuals/instanced_mesh.py +152 -0
  436. vispy/visuals/isocurve.py +213 -0
  437. vispy/visuals/isoline.py +241 -0
  438. vispy/visuals/isosurface.py +113 -0
  439. vispy/visuals/line/__init__.py +6 -0
  440. vispy/visuals/line/arrow.py +289 -0
  441. vispy/visuals/line/dash_atlas.py +90 -0
  442. vispy/visuals/line/line.py +545 -0
  443. vispy/visuals/line_plot.py +135 -0
  444. vispy/visuals/linear_region.py +199 -0
  445. vispy/visuals/markers.py +810 -0
  446. vispy/visuals/mesh.py +373 -0
  447. vispy/visuals/mesh_normals.py +159 -0
  448. vispy/visuals/plane.py +54 -0
  449. vispy/visuals/polygon.py +145 -0
  450. vispy/visuals/rectangle.py +196 -0
  451. vispy/visuals/regular_polygon.py +56 -0
  452. vispy/visuals/scrolling_lines.py +197 -0
  453. vispy/visuals/shaders/__init__.py +17 -0
  454. vispy/visuals/shaders/compiler.py +206 -0
  455. vispy/visuals/shaders/expression.py +99 -0
  456. vispy/visuals/shaders/function.py +788 -0
  457. vispy/visuals/shaders/multiprogram.py +145 -0
  458. vispy/visuals/shaders/parsing.py +140 -0
  459. vispy/visuals/shaders/program.py +161 -0
  460. vispy/visuals/shaders/shader_object.py +162 -0
  461. vispy/visuals/shaders/tests/__init__.py +0 -0
  462. vispy/visuals/shaders/tests/test_function.py +486 -0
  463. vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
  464. vispy/visuals/shaders/tests/test_parsing.py +57 -0
  465. vispy/visuals/shaders/variable.py +272 -0
  466. vispy/visuals/spectrogram.py +169 -0
  467. vispy/visuals/sphere.py +80 -0
  468. vispy/visuals/surface_plot.py +192 -0
  469. vispy/visuals/tests/__init__.py +0 -0
  470. vispy/visuals/tests/test_arrows.py +109 -0
  471. vispy/visuals/tests/test_axis.py +120 -0
  472. vispy/visuals/tests/test_collections.py +15 -0
  473. vispy/visuals/tests/test_colorbar.py +179 -0
  474. vispy/visuals/tests/test_colormap.py +97 -0
  475. vispy/visuals/tests/test_ellipse.py +122 -0
  476. vispy/visuals/tests/test_histogram.py +24 -0
  477. vispy/visuals/tests/test_image.py +390 -0
  478. vispy/visuals/tests/test_image_complex.py +36 -0
  479. vispy/visuals/tests/test_infinite_line.py +53 -0
  480. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  481. vispy/visuals/tests/test_isosurface.py +22 -0
  482. vispy/visuals/tests/test_linear_region.py +152 -0
  483. vispy/visuals/tests/test_markers.py +54 -0
  484. vispy/visuals/tests/test_mesh.py +261 -0
  485. vispy/visuals/tests/test_mesh_normals.py +218 -0
  486. vispy/visuals/tests/test_polygon.py +112 -0
  487. vispy/visuals/tests/test_rectangle.py +163 -0
  488. vispy/visuals/tests/test_regular_polygon.py +111 -0
  489. vispy/visuals/tests/test_scalable_textures.py +180 -0
  490. vispy/visuals/tests/test_sdf.py +73 -0
  491. vispy/visuals/tests/test_spectrogram.py +42 -0
  492. vispy/visuals/tests/test_text.py +95 -0
  493. vispy/visuals/tests/test_volume.py +542 -0
  494. vispy/visuals/tests/test_windbarb.py +33 -0
  495. vispy/visuals/text/__init__.py +7 -0
  496. vispy/visuals/text/_sdf_cpu.cpython-311-darwin.so +0 -0
  497. vispy/visuals/text/_sdf_cpu.pyx +110 -0
  498. vispy/visuals/text/_sdf_gpu.py +316 -0
  499. vispy/visuals/text/text.py +675 -0
  500. vispy/visuals/transforms/__init__.py +34 -0
  501. vispy/visuals/transforms/_util.py +191 -0
  502. vispy/visuals/transforms/base_transform.py +233 -0
  503. vispy/visuals/transforms/chain.py +300 -0
  504. vispy/visuals/transforms/interactive.py +98 -0
  505. vispy/visuals/transforms/linear.py +564 -0
  506. vispy/visuals/transforms/nonlinear.py +398 -0
  507. vispy/visuals/transforms/tests/__init__.py +0 -0
  508. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  509. vispy/visuals/transforms/transform_system.py +339 -0
  510. vispy/visuals/tube.py +173 -0
  511. vispy/visuals/visual.py +923 -0
  512. vispy/visuals/volume.py +1335 -0
  513. vispy/visuals/windbarb.py +291 -0
  514. vispy/visuals/xyz_axis.py +34 -0
  515. vispy-0.14.0.dist-info/LICENSE.txt +36 -0
  516. vispy-0.14.0.dist-info/METADATA +218 -0
  517. vispy-0.14.0.dist-info/RECORD +519 -0
  518. vispy-0.14.0.dist-info/WHEEL +5 -0
  519. vispy-0.14.0.dist-info/top_level.txt +1 -0
vispy/scene/canvas.py ADDED
@@ -0,0 +1,639 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+
5
+ from __future__ import division
6
+
7
+ import weakref
8
+ import numpy as np
9
+
10
+ from .. import gloo
11
+ from .. import app
12
+ from .visuals import VisualNode
13
+ from ..visuals.transforms import TransformSystem
14
+ from ..color import Color
15
+ from ..util import logger, Frozen
16
+ from ..util.profiler import Profiler
17
+ from .subscene import SubScene
18
+ from .events import SceneMouseEvent
19
+ from .widgets import Widget
20
+
21
+
22
+ class SceneCanvas(app.Canvas, Frozen):
23
+ """A Canvas that automatically draws the contents of a scene
24
+
25
+ Parameters
26
+ ----------
27
+ title : str
28
+ The widget title
29
+ size : (width, height)
30
+ The size of the window.
31
+ position : (x, y)
32
+ The position of the window in screen coordinates.
33
+ show : bool
34
+ Whether to show the widget immediately. Default False.
35
+ autoswap : bool
36
+ Whether to swap the buffers automatically after a draw event.
37
+ Default True. If True, the ``swap_buffers`` Canvas method will
38
+ be called last (by default) by the ``canvas.draw`` event handler.
39
+ app : Application | str
40
+ Give vispy Application instance to use as a backend.
41
+ (vispy.app is used by default.) If str, then an application
42
+ using the chosen backend (e.g., 'pyglet') will be created.
43
+ Note the canvas application can be accessed at ``canvas.app``.
44
+ create_native : bool
45
+ Whether to create the widget immediately. Default True.
46
+ vsync : bool
47
+ Enable vertical synchronization.
48
+ resizable : bool
49
+ Allow the window to be resized.
50
+ decorate : bool
51
+ Decorate the window. Default True.
52
+ fullscreen : bool | int
53
+ If False, windowed mode is used (default). If True, the default
54
+ monitor is used. If int, the given monitor number is used.
55
+ config : dict
56
+ A dict with OpenGL configuration options, which is combined
57
+ with the default configuration options and used to initialize
58
+ the context. See ``canvas.context.config`` for possible
59
+ options.
60
+ shared : Canvas | GLContext | None
61
+ An existing canvas or context to share OpenGL objects with.
62
+ keys : str | dict | None
63
+ Default key mapping to use. If 'interactive', escape and F11 will
64
+ close the canvas and toggle full-screen mode, respectively.
65
+ If dict, maps keys to functions. If dict values are strings,
66
+ they are assumed to be ``Canvas`` methods, otherwise they should
67
+ be callable.
68
+ parent : widget-object
69
+ The parent widget if this makes sense for the used backend.
70
+ dpi : float | None
71
+ Resolution in dots-per-inch to use for the canvas. If dpi is None,
72
+ then the value will be determined by querying the global config first,
73
+ and then the operating system.
74
+ always_on_top : bool
75
+ If True, try to create the window in always-on-top mode.
76
+ px_scale : int > 0
77
+ A scale factor to apply between logical and physical pixels in addition
78
+ to the actual scale factor determined by the backend. This option
79
+ allows the scale factor to be adjusted for testing.
80
+ bgcolor : Color
81
+ The background color to use.
82
+
83
+ See also
84
+ --------
85
+ vispy.app.Canvas
86
+
87
+ Notes
88
+ -----
89
+ Receives the following events:
90
+
91
+ * initialize
92
+ * resize
93
+ * draw
94
+ * mouse_press
95
+ * mouse_release
96
+ * mouse_double_click
97
+ * mouse_move
98
+ * mouse_wheel
99
+ * key_press
100
+ * key_release
101
+ * stylus
102
+ * touch
103
+ * close
104
+
105
+ The ordering of the mouse_double_click, mouse_press, and mouse_release
106
+ events are not guaranteed to be consistent between backends. Only certain
107
+ backends natively support double-clicking (currently Qt and WX); on other
108
+ backends, they are detected manually with a fixed time delay.
109
+ This can cause problems with accessibility, as increasing the OS detection
110
+ time or using a dedicated double-click button will not be respected.
111
+ """
112
+
113
+ def __init__(self, title='VisPy canvas', size=(800, 600), position=None,
114
+ show=False, autoswap=True, app=None, create_native=True,
115
+ vsync=False, resizable=True, decorate=True, fullscreen=False,
116
+ config=None, shared=None, keys=None, parent=None, dpi=None,
117
+ always_on_top=False, px_scale=1, bgcolor='black'):
118
+ self._scene = None
119
+ # A default widget that follows the shape of the canvas
120
+ self._central_widget = None
121
+ self._draw_order = weakref.WeakKeyDictionary()
122
+ self._drawing = False
123
+ self._update_pending = False
124
+ self._fb_stack = []
125
+ self._vp_stack = []
126
+ self._mouse_handler = None
127
+ self.transforms = TransformSystem(canvas=self)
128
+ self._bgcolor = Color(bgcolor).rgba
129
+
130
+ # Set to True to enable sending mouse events even when no button is
131
+ # pressed. Disabled by default because it is very expensive. Also
132
+ # private for now because this behavior / API needs more thought.
133
+ self._send_hover_events = False
134
+
135
+ super(SceneCanvas, self).__init__(
136
+ title, size, position, show, autoswap, app, create_native, vsync,
137
+ resizable, decorate, fullscreen, config, shared, keys, parent, dpi,
138
+ always_on_top, px_scale)
139
+ self.events.mouse_press.connect(self._process_mouse_event)
140
+ self.events.mouse_move.connect(self._process_mouse_event)
141
+ self.events.mouse_release.connect(self._process_mouse_event)
142
+ self.events.mouse_wheel.connect(self._process_mouse_event)
143
+ self.events.touch.connect(self._process_mouse_event)
144
+
145
+ self.scene = SubScene()
146
+ self.freeze()
147
+
148
+ @property
149
+ def scene(self):
150
+ """The SubScene object that represents the root node of the
151
+ scene graph to be displayed.
152
+ """
153
+ return self._scene
154
+
155
+ @scene.setter
156
+ def scene(self, node):
157
+ oldscene = self._scene
158
+ self._scene = node
159
+ if oldscene is not None:
160
+ oldscene._set_canvas(None)
161
+ oldscene.events.children_change.disconnect(self._update_scenegraph)
162
+ if node is not None:
163
+ node._set_canvas(self)
164
+ node.events.children_change.connect(self._update_scenegraph)
165
+
166
+ @property
167
+ def central_widget(self):
168
+ """Returns the default widget that occupies the entire area of the
169
+ canvas.
170
+ """
171
+ if self._central_widget is None:
172
+ self._central_widget = Widget(size=self.size, parent=self.scene)
173
+ return self._central_widget
174
+
175
+ @property
176
+ def bgcolor(self):
177
+ return Color(self._bgcolor)
178
+
179
+ @bgcolor.setter
180
+ def bgcolor(self, color):
181
+ self._bgcolor = Color(color).rgba
182
+ if hasattr(self, '_backend'):
183
+ self.update()
184
+
185
+ def update(self, node=None):
186
+ """Update the scene
187
+
188
+ Parameters
189
+ ----------
190
+ node : instance of Node
191
+ Not used.
192
+ """
193
+ # TODO: use node bounds to keep track of minimum drawable area
194
+ if self._drawing:
195
+ return
196
+
197
+ # Keep things civil in the node update system. Once an update
198
+ # has been scheduled, there is no need to flood the event queue
199
+ # of the backend with additional updates.
200
+ if not self._update_pending:
201
+ self._update_pending = True
202
+ super(SceneCanvas, self).update()
203
+
204
+ def on_draw(self, event):
205
+ """Draw handler
206
+
207
+ Parameters
208
+ ----------
209
+ event : instance of Event
210
+ The draw event.
211
+ """
212
+ if self._scene is None:
213
+ return # Can happen on initialization
214
+ logger.debug('Canvas draw')
215
+
216
+ # Now that a draw event is going to be handled, open up the
217
+ # scheduling of further updates
218
+ self._update_pending = False
219
+ self._draw_scene()
220
+
221
+ def render(self, region=None, size=None, bgcolor=None, crop=None, alpha=True):
222
+ """Render the scene to an offscreen buffer and return the image array.
223
+
224
+ Parameters
225
+ ----------
226
+ region : tuple | None
227
+ Specifies the region of the canvas to render. Format is
228
+ (x, y, w, h). By default, the entire canvas is rendered.
229
+ size : tuple | None
230
+ Specifies the size of the image array to return. If no size is
231
+ given, then the size of the *region* is used, multiplied by the
232
+ pixel scaling factor of the canvas (see `pixel_scale`). This
233
+ argument allows the scene to be rendered at resolutions different
234
+ from the native canvas resolution.
235
+ bgcolor : instance of Color | None
236
+ The background color to use.
237
+ crop : array-like | None
238
+ If specified it determines the pixels read from the framebuffer.
239
+ In the format (x, y, w, h), relative to the region being rendered.
240
+ alpha : bool
241
+ If True (default) produce an RGBA array (h, w, 4). If False,
242
+ remove the Alpha channel and return the RGB array (h, w, 3).
243
+ This may be useful if blending of various elements requires a
244
+ solid background to produce the expected visualization.
245
+
246
+ Returns
247
+ -------
248
+ image : array
249
+ Numpy array of type ubyte and shape (h, w, 4). Index [0, 0] is the
250
+ upper-left corner of the rendered region. If ``alpha`` is ``False``,
251
+ then only 3 channels will be returned (RGB).
252
+
253
+ """
254
+ self.set_current()
255
+ # Set up a framebuffer to render to
256
+ offset = (0, 0) if region is None else region[:2]
257
+ csize = self.size if region is None else region[2:]
258
+ s = self.pixel_scale
259
+ size = tuple([int(x * s) for x in csize]) if size is None else size
260
+ fbo = gloo.FrameBuffer(color=gloo.RenderBuffer(size[::-1]),
261
+ depth=gloo.RenderBuffer(size[::-1]))
262
+
263
+ self.push_fbo(fbo, offset, csize)
264
+ try:
265
+ self._draw_scene(bgcolor=bgcolor)
266
+ result = fbo.read(crop=crop)
267
+ finally:
268
+ self.pop_fbo()
269
+
270
+ if not alpha:
271
+ result = result[..., :3]
272
+ return result
273
+
274
+ def _draw_scene(self, bgcolor=None):
275
+ if bgcolor is None:
276
+ bgcolor = self._bgcolor
277
+ self.context.clear(color=bgcolor, depth=True)
278
+ self.draw_visual(self.scene)
279
+
280
+ def draw_visual(self, visual, event=None):
281
+ """Draw a visual and its children to the canvas or currently active
282
+ framebuffer.
283
+
284
+ Parameters
285
+ ----------
286
+ visual : Visual
287
+ The visual to draw
288
+ event : None or DrawEvent
289
+ Optionally specifies the original canvas draw event that initiated
290
+ this draw.
291
+ """
292
+ prof = Profiler()
293
+
294
+ # make sure this canvas's context is active
295
+ self.set_current()
296
+
297
+ try:
298
+ self._drawing = True
299
+ # get order to draw visuals
300
+ if visual not in self._draw_order:
301
+ self._draw_order[visual] = self._generate_draw_order()
302
+ order = self._draw_order[visual]
303
+
304
+ # draw (while avoiding branches with visible=False)
305
+ stack = []
306
+ invisible_node = None
307
+ for node, start in order:
308
+ if start:
309
+ stack.append(node)
310
+ if invisible_node is None:
311
+ if not node.visible:
312
+ # disable drawing until we exit this node's subtree
313
+ invisible_node = node
314
+ else:
315
+ if hasattr(node, 'draw'):
316
+ node.draw()
317
+ prof.mark(str(node))
318
+ else:
319
+ if node is invisible_node:
320
+ invisible_node = None
321
+ stack.pop()
322
+ finally:
323
+ self._drawing = False
324
+
325
+ def _generate_draw_order(self, node=None):
326
+ """Return a list giving the order to draw visuals.
327
+
328
+ Each node appears twice in the list--(node, True) appears before the
329
+ node's children are drawn, and (node, False) appears after.
330
+ """
331
+ if node is None:
332
+ node = self._scene
333
+ order = [(node, True)]
334
+ children = node.children
335
+ children.sort(key=lambda ch: ch.order)
336
+ for ch in children:
337
+ order.extend(self._generate_draw_order(ch))
338
+ order.append((node, False))
339
+ return order
340
+
341
+ def _update_scenegraph(self, event):
342
+ """Called when topology of scenegraph has changed."""
343
+ self._draw_order.clear()
344
+ self.update()
345
+
346
+ def _process_mouse_event(self, event):
347
+ prof = Profiler() # noqa
348
+ deliver_types = [
349
+ 'mouse_press',
350
+ 'mouse_wheel',
351
+ 'gesture_zoom',
352
+ 'gesture_rotate',
353
+ ]
354
+ if self._send_hover_events:
355
+ deliver_types += ['mouse_move']
356
+
357
+ picked = self._mouse_handler
358
+ if picked is None:
359
+ if event.type in deliver_types:
360
+ picked = self.visual_at(event.pos)
361
+
362
+ # No visual to handle this event; bail out now
363
+ if picked is None:
364
+ return
365
+
366
+ # Create an event to pass to the picked visual
367
+ scene_event = SceneMouseEvent(event=event, visual=picked)
368
+
369
+ # Deliver the event
370
+ if picked == self._mouse_handler:
371
+ # If we already have a mouse handler, then no other node may
372
+ # receive the event
373
+ if event.type == 'mouse_release':
374
+ self._mouse_handler = None
375
+ getattr(picked.events, event.type)(scene_event)
376
+ else:
377
+ # If we don't have a mouse handler, then pass the event through
378
+ # the chain of parents until a node accepts the event.
379
+ while picked is not None:
380
+ getattr(picked.events, event.type)(scene_event)
381
+ if scene_event.handled:
382
+ if event.type == 'mouse_press':
383
+ self._mouse_handler = picked
384
+ break
385
+ if event.type in deliver_types:
386
+ # events that are not handled get passed to parent
387
+ picked = picked.parent
388
+ scene_event.visual = picked
389
+ else:
390
+ picked = None
391
+
392
+ # If something in the scene handled the scene_event, then we mark
393
+ # the original event accordingly.
394
+ event.handled = scene_event.handled
395
+
396
+ def visual_at(self, pos):
397
+ """Return the visual at a given position
398
+
399
+ Parameters
400
+ ----------
401
+ pos : tuple
402
+ The position in logical coordinates to query.
403
+
404
+ Returns
405
+ -------
406
+ visual : instance of Visual | None
407
+ The visual at the position, if it exists.
408
+ """
409
+ tr = self.transforms.get_transform('canvas', 'framebuffer')
410
+ fbpos = tr.map(pos)[:2]
411
+
412
+ try:
413
+ id_ = self._render_picking((fbpos[0], fbpos[1], 1, 1))
414
+ vis = VisualNode._visual_ids.get(id_[0, 0], None)
415
+ except RuntimeError:
416
+ # Don't have read_pixels() support for IPython. Fall back to
417
+ # bounds checking.
418
+ return self._visual_bounds_at(pos)
419
+ return vis
420
+
421
+ def _visual_bounds_at(self, pos, node=None):
422
+ """Find a visual whose bounding rect encompasses *pos*."""
423
+ if node is None:
424
+ node = self.scene
425
+
426
+ for ch in node.children:
427
+ hit = self._visual_bounds_at(pos, ch)
428
+ if hit is not None:
429
+ return hit
430
+
431
+ if (not isinstance(node, VisualNode) or not node.visible or
432
+ not node.interactive):
433
+ return None
434
+
435
+ # let nodes know we are picking to handle any special cases (picking meshes)
436
+ # we can't do this before this or child nodes may be considered visible
437
+ # which would cause the above 'if' statement to pass when it shouldn't
438
+ node.picking = True
439
+ bounds = [node.bounds(axis=i) for i in range(2)]
440
+ node.picking = False
441
+
442
+ if None in bounds:
443
+ return None
444
+
445
+ tr = self.scene.node_transform(node).inverse
446
+ corners = np.array([
447
+ [bounds[0][0], bounds[1][0]],
448
+ [bounds[0][0], bounds[1][1]],
449
+ [bounds[0][1], bounds[1][0]],
450
+ [bounds[0][1], bounds[1][1]]])
451
+ bounds = tr.map(corners)
452
+ xhit = bounds[:, 0].min() < pos[0] < bounds[:, 0].max()
453
+ yhit = bounds[:, 1].min() < pos[1] < bounds[:, 1].max()
454
+ if xhit and yhit:
455
+ return node
456
+
457
+ def visuals_at(self, pos, radius=10):
458
+ """Return a list of visuals within *radius* pixels of *pos*.
459
+
460
+ Visuals are sorted by their proximity to *pos*.
461
+
462
+ Parameters
463
+ ----------
464
+ pos : tuple
465
+ (x, y) position at which to find visuals.
466
+ radius : int
467
+ Distance away from *pos* to search for visuals.
468
+ """
469
+ tr = self.transforms.get_transform('canvas', 'framebuffer')
470
+ pos = tr.map(pos)[:2]
471
+
472
+ id = self._render_picking((pos[0]-radius, pos[1]-radius,
473
+ radius * 2 + 1, radius * 2 + 1))
474
+ ids = []
475
+ seen = set()
476
+ for i in range(radius):
477
+ subr = id[radius-i:radius+i+1, radius-i:radius+i+1]
478
+ subr_ids = set(list(np.unique(subr)))
479
+ ids.extend(list(subr_ids - seen))
480
+ seen |= subr_ids
481
+ visuals = [VisualNode._visual_ids.get(x, None) for x in ids]
482
+ return [v for v in visuals if v is not None]
483
+
484
+ def _render_picking(self, crop):
485
+ """Render the scene in picking mode, returning a 2D array of visual
486
+ IDs in the area specified by crop.
487
+
488
+ Parameters
489
+ ----------
490
+ crop : array-like
491
+ The crop (x, y, w, h) of the framebuffer to read. For picking the
492
+ full canvas is rendered and cropped on read as it is much faster
493
+ than triggering transform updates across the scene with every
494
+ click.
495
+ """
496
+ with self._scene.set_picking():
497
+ img = self.render(bgcolor=(0, 0, 0, 0), crop=crop)
498
+ img = img.astype('int32') * [2**0, 2**8, 2**16, 2**24]
499
+ id_ = img.sum(axis=2).astype('int32')
500
+ return id_
501
+
502
+ def on_resize(self, event):
503
+ """Resize handler
504
+
505
+ Parameters
506
+ ----------
507
+ event : instance of Event
508
+ The resize event.
509
+ """
510
+ self._update_transforms()
511
+
512
+ if self._central_widget is not None:
513
+ self._central_widget.size = self.size
514
+
515
+ if len(self._vp_stack) == 0:
516
+ self.context.set_viewport(0, 0, *self.physical_size)
517
+
518
+ def on_close(self, event):
519
+ """Close event handler
520
+
521
+ Parameters
522
+ ----------
523
+ event : instance of Event
524
+ The event.
525
+ """
526
+ self.events.mouse_press.disconnect(self._process_mouse_event)
527
+ self.events.mouse_move.disconnect(self._process_mouse_event)
528
+ self.events.mouse_release.disconnect(self._process_mouse_event)
529
+ self.events.mouse_wheel.disconnect(self._process_mouse_event)
530
+ self.events.touch.disconnect(self._process_mouse_event)
531
+
532
+ # -------------------------------------------------- transform handling ---
533
+ def push_viewport(self, viewport):
534
+ """Push a viewport (x, y, w, h) on the stack. Values must be integers
535
+ relative to the active framebuffer.
536
+
537
+ Parameters
538
+ ----------
539
+ viewport : tuple
540
+ The viewport as (x, y, w, h).
541
+ """
542
+ vp = list(viewport)
543
+ # Normalize viewport before setting;
544
+ if vp[2] < 0:
545
+ vp[0] += vp[2]
546
+ vp[2] *= -1
547
+ if vp[3] < 0:
548
+ vp[1] += vp[3]
549
+ vp[3] *= -1
550
+
551
+ self._vp_stack.append(vp)
552
+ try:
553
+ self.context.set_viewport(*vp)
554
+ except Exception:
555
+ self._vp_stack.pop()
556
+ raise
557
+
558
+ self._update_transforms()
559
+
560
+ def pop_viewport(self):
561
+ """Pop a viewport from the stack."""
562
+ vp = self._vp_stack.pop()
563
+ # Activate latest
564
+ if len(self._vp_stack) > 0:
565
+ self.context.set_viewport(*self._vp_stack[-1])
566
+ else:
567
+ self.context.set_viewport(0, 0, *self.physical_size)
568
+
569
+ self._update_transforms()
570
+ return vp
571
+
572
+ def push_fbo(self, fbo, offset, csize):
573
+ """Push an FBO on the stack.
574
+
575
+ This activates the framebuffer and causes subsequent rendering to be
576
+ written to the framebuffer rather than the canvas's back buffer. This
577
+ will also set the canvas viewport to cover the boundaries of the
578
+ framebuffer.
579
+
580
+ Parameters
581
+ ----------
582
+ fbo : instance of FrameBuffer
583
+ The framebuffer object .
584
+ offset : tuple
585
+ The location of the fbo origin relative to the canvas's framebuffer
586
+ origin.
587
+ csize : tuple
588
+ The size of the region in the canvas's framebuffer that should be
589
+ covered by this framebuffer object.
590
+ """
591
+ self._fb_stack.append((fbo, offset, csize))
592
+ try:
593
+ fbo.activate()
594
+ h, w = fbo.color_buffer.shape[:2]
595
+ self.push_viewport((0, 0, w, h))
596
+ except Exception:
597
+ self._fb_stack.pop()
598
+ raise
599
+
600
+ self._update_transforms()
601
+
602
+ def pop_fbo(self):
603
+ """Pop an FBO from the stack."""
604
+ fbo = self._fb_stack.pop()
605
+ fbo[0].deactivate()
606
+ self.pop_viewport()
607
+ if len(self._fb_stack) > 0:
608
+ old_fbo = self._fb_stack[-1]
609
+ old_fbo[0].activate()
610
+
611
+ self._update_transforms()
612
+ return fbo
613
+
614
+ def _current_framebuffer(self):
615
+ """Return (fbo, origin, canvas_size) for the current
616
+ FBO on the stack, or for the canvas if there is no FBO.
617
+ """
618
+ if len(self._fb_stack) == 0:
619
+ return None, (0, 0), self.size
620
+ else:
621
+ return self._fb_stack[-1]
622
+
623
+ def _update_transforms(self):
624
+ """Update the canvas's TransformSystem to correct for the current
625
+ canvas size, framebuffer, and viewport.
626
+ """
627
+ if len(self._fb_stack) == 0:
628
+ fb_size = fb_rect = None
629
+ else:
630
+ fb, origin, fb_size = self._fb_stack[-1]
631
+ fb_rect = origin + fb_size
632
+
633
+ if len(self._vp_stack) == 0:
634
+ viewport = None
635
+ else:
636
+ viewport = self._vp_stack[-1]
637
+
638
+ self.transforms.configure(viewport=viewport, fbo_size=fb_size,
639
+ fbo_rect=fb_rect)