vispy 0.14.0__cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.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-312-aarch64-linux-gnu.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 +6 -0
  519. vispy-0.14.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,788 @@
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
+ Classses representing GLSL objects (functions, variables, etc) that may be
6
+ composed together to create complete shaders.
7
+ See the docstring of Function for details.
8
+
9
+ Details
10
+ -------
11
+
12
+ A complete GLSL program is composed of ShaderObjects, each of which may be used
13
+ inline as an expression, and some of which include a definition that must be
14
+ included on the final code. ShaderObjects keep track of a hierarchy of
15
+ dependencies so that all necessary code is included at compile time, and
16
+ changes made to any object may be propagated to the root of the hierarchy to
17
+ trigger a recompile.
18
+ """
19
+
20
+ from collections import OrderedDict
21
+ import logging
22
+ import re
23
+
24
+ import numpy as np
25
+
26
+ from ...util.eq import eq
27
+ from ...util import logger
28
+ from . import parsing
29
+ from .shader_object import ShaderObject
30
+ from .variable import Variable, Varying
31
+ from .expression import TextExpression, FunctionCall
32
+
33
+
34
+ class Function(ShaderObject):
35
+ """Representation of a GLSL function
36
+
37
+ Objects of this class can be used for re-using and composing GLSL
38
+ snippets. Each Function consists of a GLSL snippet in the form of
39
+ a function. The code may have template variables that start with
40
+ the dollar sign. These stubs can be replaced with expressions using
41
+ the index operation. Expressions can be:
42
+
43
+ * plain text that is inserted verbatim in the code
44
+ * a Function object or a call to a funcion
45
+ * a Variable (or Varying) object
46
+ * float, int, tuple are automatically turned into a uniform Variable
47
+ * a VertexBuffer is automatically turned into an attribute Variable
48
+
49
+ All functions have implicit "$pre" and "$post" placeholders that may be
50
+ used to insert code at the beginning and end of the function.
51
+
52
+ Examples
53
+ --------
54
+ This example shows the basic usage of the Function class::
55
+
56
+ vert_code_template = Function('''
57
+ void main() {
58
+ gl_Position = $pos;
59
+ gl_Position.x += $xoffset;
60
+ gl_Position.y += $yoffset;
61
+ }''')
62
+
63
+ scale_transform = Function('''
64
+ vec4 transform_scale(vec4 pos){
65
+ return pos * $scale;
66
+ }''')
67
+
68
+ # If you get the function from a snippet collection, always
69
+ # create new Function objects to ensure they are 'fresh'.
70
+ vert_code = Function(vert_code_template)
71
+ trans1 = Function(scale_transform)
72
+ trans2 = Function(scale_transform) # trans2 != trans1
73
+
74
+ # Three ways to assign to template variables:
75
+ #
76
+ # 1) Assign verbatim code
77
+ vert_code['xoffset'] = '(3.0 / 3.1415)'
78
+
79
+ # 2) Assign a value (this creates a new uniform or attribute)
80
+ vert_code['yoffset'] = 5.0
81
+
82
+ # 3) Assign a function call expression
83
+ pos_var = Variable('attribute vec4 a_position')
84
+ vert_code['pos'] = trans1(trans2(pos_var))
85
+
86
+ # Transforms also need their variables set
87
+ trans1['scale'] = 0.5
88
+ trans2['scale'] = (1.0, 0.5, 1.0, 1.0)
89
+
90
+ # You can actually change any code you want, but use this with care!
91
+ vert_code.replace('gl_Position.y', 'gl_Position.z')
92
+
93
+ # Finally, you can set special variables explicitly. This generates
94
+ # a new statement at the end of the vert_code function.
95
+ vert_code['gl_PointSize'] = '10.'
96
+
97
+
98
+ If we use ``vert_code.compile()`` we get::
99
+
100
+ attribute vec4 a_position;
101
+ uniform float u_yoffset;
102
+ uniform float u_scale_1;
103
+ uniform vec4 u_scale_2;
104
+ uniform float u_pointsize;
105
+
106
+ vec4 transform_scale_1(vec4 pos){
107
+ return pos * u_scale_1;
108
+ }
109
+
110
+ vec4 transform_scale_2(vec4 pos){
111
+ return pos * u_scale_2;
112
+ }
113
+
114
+ void main() {
115
+ gl_Position = transform_scale_1(transform_scale_2(a_position));
116
+ gl_Position.x += (3.0 / 3.1415);
117
+ gl_Position.z += u_yoffset;
118
+
119
+ gl_PointSize = u_pointsize;
120
+ }
121
+
122
+ Note how the two scale function resulted in two different functions
123
+ and two uniforms for the scale factors.
124
+
125
+ Notes
126
+ -----
127
+
128
+ Function calls:
129
+
130
+ As can be seen above, the arguments with which a function is to be
131
+ called must be specified by calling the Function object. The
132
+ arguments can be any of the expressions mentioned earlier. If the
133
+ signature is already specified in the template code, that function
134
+ itself must be given.
135
+
136
+ ::
137
+
138
+ code = Function('''
139
+ void main() {
140
+ vec4 position = $pos;
141
+ gl_Position = $scale(position)
142
+ }
143
+ ''')
144
+
145
+ # Example of a function call with all possible three expressions
146
+ vert_code['pos'] = func1('3.0', 'uniform float u_param', func2())
147
+
148
+ # For scale, the sigfnature is already specified
149
+ code['scale'] = scale_func # Must not specify args
150
+
151
+ Data for uniform and attribute variables:
152
+
153
+ To each variable a value can be associated. In fact, in most cases
154
+ the Function class is smart enough to be able to create a Variable
155
+ object if only the data is given.
156
+
157
+ ::
158
+
159
+ code['offset'] = Variable('uniform float offset') # No data
160
+ code['offset'] = Variable('uniform float offset', 3.0) # With data
161
+ code['offset'] = 3.0 # -> Uniform Variable
162
+ position['position'] = VertexBuffer() # -> attribute Variable
163
+
164
+ # Updating variables
165
+ code['offset'].value = 4.0
166
+ position['position'].value.set_data(...)
167
+
168
+ """
169
+
170
+ def __init__(self, code, dependencies=None):
171
+ super(Function, self).__init__()
172
+
173
+ # Add depencencies is given. This is to allow people to
174
+ # manually define deps for a function that they use.
175
+ if dependencies is not None:
176
+ for dep in dependencies:
177
+ self._add_dep(dep)
178
+
179
+ self.code = code
180
+
181
+ # Expressions replace template variables (also our dependencies)
182
+ self._expressions = OrderedDict()
183
+
184
+ # Verbatim string replacements
185
+ self._replacements = OrderedDict()
186
+
187
+ # Stuff to do at the end
188
+ self._assignments = OrderedDict()
189
+
190
+ def __setitem__(self, key, val):
191
+ """Setting of replacements through a dict-like syntax.
192
+
193
+ Each replacement can be:
194
+ * verbatim code: ``fun1['foo'] = '3.14159'``
195
+ * a FunctionCall: ``fun1['foo'] = fun2()``
196
+ * a Variable: ``fun1['foo'] = Variable(...)`` (can be auto-generated)
197
+ """
198
+ # Check the key. Must be Varying, 'gl_X' or a known template variable
199
+ if isinstance(key, Variable):
200
+ if key.vtype == 'varying':
201
+ if self.name != 'main':
202
+ raise Exception("Varying assignment only alowed in 'main' "
203
+ "function.")
204
+ storage = self._assignments
205
+ else:
206
+ raise TypeError("Variable assignment only allowed for "
207
+ "varyings, not %s (in %s)"
208
+ % (key.vtype, self.name))
209
+ elif isinstance(key, str):
210
+ if any(map(key.startswith,
211
+ ('gl_PointSize', 'gl_Position', 'gl_FragColor'))):
212
+ storage = self._assignments
213
+ elif key in self.template_vars or key in ('pre', 'post'):
214
+ storage = self._expressions
215
+ else:
216
+ raise KeyError('Invalid template variable %r' % key)
217
+ else:
218
+ raise TypeError('In `function[key]` key must be a string or '
219
+ 'varying.')
220
+
221
+ # If values already match, bail out now
222
+ if eq(storage.get(key), val):
223
+ return
224
+
225
+ # If we are only changing the value (and not the dtype) of a uniform,
226
+ # we can set that value and return immediately to avoid triggering a
227
+ # recompile.
228
+ if val is not None and not isinstance(val, Variable):
229
+ # We are setting a value. If there is already a variable set here,
230
+ # try just updating its value.
231
+ variable = storage.get(key, None)
232
+ if isinstance(variable, Variable):
233
+ if np.any(variable.value != val):
234
+ variable.value = val
235
+ self.changed(value_changed=True)
236
+ return
237
+
238
+ # Could not set variable.value directly; instead we will need
239
+ # to create a new ShaderObject
240
+ val = ShaderObject.create(val, ref=key)
241
+ if variable is val:
242
+ # This can happen if ShaderObject.create returns the same
243
+ # object (such as when setting a Transform).
244
+ return
245
+
246
+ # Remove old references, if any
247
+ oldval = storage.pop(key, None)
248
+ if oldval is not None:
249
+ for obj in (key, oldval):
250
+ if isinstance(obj, ShaderObject):
251
+ self._remove_dep(obj)
252
+
253
+ # Add new references
254
+ if val is not None:
255
+ if isinstance(key, Varying):
256
+ # tell this varying to inherit properties from
257
+ # its source attribute / expression.
258
+ key.link(val)
259
+
260
+ # Store value and dependencies
261
+ storage[key] = val
262
+ for obj in (key, val):
263
+ if isinstance(obj, ShaderObject):
264
+ self._add_dep(obj)
265
+
266
+ # In case of verbatim text, we might have added new template vars
267
+ if isinstance(val, TextExpression):
268
+ for var in parsing.find_template_variables(val.expression()):
269
+ if var not in self.template_vars:
270
+ self.template_vars.add(var.lstrip('$'))
271
+
272
+ self.changed(code_changed=True, value_changed=True)
273
+ if logger.level <= logging.DEBUG:
274
+ import traceback
275
+ last = traceback.format_list(traceback.extract_stack()[-2:-1])
276
+ logger.debug("Assignment would trigger shader recompile:\n"
277
+ "Original: %r\nReplacement: %r\nSource: %s",
278
+ oldval, val, ''.join(last))
279
+
280
+ def __getitem__(self, key):
281
+ """Return a reference to a program variable from this function.
282
+
283
+ This allows variables between functions to be linked together::
284
+
285
+ func1['var_name'] = func2['other_var_name']
286
+
287
+ In the example above, the two local variables would be assigned to the
288
+ same program variable whenever func1 and func2 are attached to the same
289
+ program.
290
+ """
291
+ try:
292
+ return self._expressions[key]
293
+ except KeyError:
294
+ pass
295
+
296
+ try:
297
+ return self._assignments[key]
298
+ except KeyError:
299
+ pass
300
+
301
+ if key not in self.template_vars:
302
+ raise KeyError('Invalid template variable %r' % key)
303
+ else:
304
+ raise KeyError('No value known for key %r' % key)
305
+
306
+ def __call__(self, *args):
307
+ """Set the signature for this function and return an FunctionCall
308
+ object. Each argument can be verbatim code or a FunctionCall object.
309
+ """
310
+ return FunctionCall(self, args)
311
+
312
+ def __contains__(self, key):
313
+ return key in self.template_vars
314
+
315
+ # Public API methods
316
+
317
+ @property
318
+ def signature(self):
319
+ if self._signature is None:
320
+ try:
321
+ self._signature = parsing.parse_function_signature(self._code)
322
+ except Exception as err:
323
+ raise ValueError('Invalid code: ' + str(err))
324
+ return self._signature
325
+
326
+ @property
327
+ def name(self):
328
+ """The function name. The name may be mangled in the final code
329
+ to avoid name clashes.
330
+ """
331
+ return self.signature[0]
332
+
333
+ @property
334
+ def args(self):
335
+ """
336
+ List of input arguments in the function signature::
337
+ [(arg_name, arg_type), ...]
338
+ """
339
+ return self.signature[1]
340
+
341
+ @property
342
+ def rtype(self):
343
+ """The return type of this function."""
344
+ return self.signature[2]
345
+
346
+ @property
347
+ def code(self):
348
+ """The template code used to generate the definition for this function."""
349
+ return self._code
350
+
351
+ @code.setter
352
+ def code(self, code):
353
+ # Get and strip code
354
+ if isinstance(code, Function):
355
+ code = code._code
356
+ elif not isinstance(code, str):
357
+ raise ValueError('Function needs a string or Function; got %s.' %
358
+ type(code))
359
+ self._code = self._clean_code(code)
360
+
361
+ # (name, args, rval)
362
+ self._signature = None
363
+
364
+ # $placeholders parsed from the code
365
+ self._template_vars = None
366
+
367
+ # Create static Variable instances for any global variables declared
368
+ # in the code
369
+ self._static_vars = None
370
+
371
+ @property
372
+ def template_vars(self):
373
+ if self._template_vars is None:
374
+ self._template_vars = self._parse_template_vars()
375
+ return self._template_vars
376
+
377
+ def static_names(self):
378
+ if self._static_vars is None:
379
+ self._static_vars = parsing.find_program_variables(self._code)
380
+ return list(self._static_vars.keys()) + [arg[0] for arg in self.args]
381
+
382
+ def replace(self, str1, str2):
383
+ """Set verbatim code replacement
384
+
385
+ It is strongly recommended to use function['$foo'] = 'bar' where
386
+ possible because template variables are less likely to changed
387
+ than the code itself in future versions of vispy.
388
+
389
+ Parameters
390
+ ----------
391
+ str1 : str
392
+ String to replace
393
+ str2 : str
394
+ String to replace str1 with
395
+ """
396
+ if str2 != self._replacements.get(str1, None):
397
+ self._replacements[str1] = str2
398
+ self.changed(code_changed=True)
399
+ # self._last_changed = time.time()
400
+
401
+ # Private methods
402
+
403
+ def _parse_template_vars(self):
404
+ """Find all template variables in self._code, excluding the function name."""
405
+ template_vars = set()
406
+ for var in parsing.find_template_variables(self._code):
407
+ var = var.lstrip('$')
408
+ if var == self.name:
409
+ continue
410
+ if var in ('pre', 'post'):
411
+ raise ValueError('GLSL uses reserved template variable $%s' %
412
+ var)
413
+ template_vars.add(var)
414
+ return template_vars
415
+
416
+ def _get_replaced_code(self, names, version, shader):
417
+ """Return code, with new name, expressions, and replacements applied."""
418
+ code = self._code
419
+
420
+ # Modify name
421
+ fname = names[self]
422
+ code = code.replace(" " + self.name + "(", " " + fname + "(")
423
+
424
+ # Apply string replacements first -- these may contain $placeholders
425
+ for key, val in self._replacements.items():
426
+ code = code.replace(key, val)
427
+
428
+ # Apply assignments to the end of the function
429
+
430
+ # Collect post lines
431
+ post_lines = []
432
+ for key, val in self._assignments.items():
433
+ if isinstance(key, Variable):
434
+ key = names[key]
435
+ if isinstance(val, ShaderObject):
436
+ val = val.expression(names)
437
+ line = ' %s = %s;' % (key, val)
438
+ post_lines.append(line)
439
+
440
+ # Add a default $post placeholder if needed
441
+ if 'post' in self._expressions:
442
+ post_lines.append(' $post')
443
+
444
+ # Apply placeholders for hooks
445
+ post_text = '\n'.join(post_lines)
446
+ if post_text:
447
+ post_text = '\n' + post_text + '\n'
448
+ code = code.rpartition('}')
449
+ code = code[0] + post_text + code[1] + code[2]
450
+
451
+ # Add a default $pre placeholder if needed
452
+ if 'pre' in self._expressions:
453
+ m = re.search(fname + r'\s*\([^{]*\)\s*{', code)
454
+ if m is None:
455
+ raise RuntimeError("Cound not find beginning of function '%s'"
456
+ % fname)
457
+ ind = m.span()[1]
458
+ code = code[:ind] + "\n $pre\n" + code[ind:]
459
+
460
+ # Apply template variables
461
+ for key, val in self._expressions.items():
462
+ val = val.expression(names)
463
+ search = r'\$' + key + r'($|[^a-zA-Z0-9_])'
464
+ code = re.sub(search, val+r'\1', code)
465
+
466
+ # Done
467
+ if '$' in code:
468
+ v = parsing.find_template_variables(code)
469
+ logger.warning('Unsubstituted placeholders in code: %s\n'
470
+ ' replacements made: %s',
471
+ v, list(self._expressions.keys()))
472
+
473
+ return code + '\n'
474
+
475
+ def definition(self, names, version, shader):
476
+ return self._get_replaced_code(names, version, shader)
477
+
478
+ def expression(self, names):
479
+ return names[self]
480
+
481
+ def _clean_code(self, code):
482
+ """Return *code* with indentation and leading/trailing blank lines removed."""
483
+ lines = code.split("\n")
484
+ min_indent = 100
485
+ for line in lines:
486
+ if line.strip() != "":
487
+ indent = len(line) - len(line.lstrip())
488
+ min_indent = min(indent, min_indent)
489
+ if min_indent > 0:
490
+ lines = [line[min_indent:] for line in lines]
491
+ code = "\n".join(lines)
492
+ return code
493
+
494
+ def __repr__(self):
495
+ try:
496
+ args = ', '.join([' '.join(arg) for arg in self.args])
497
+ except Exception:
498
+ return ('<%s (error parsing signature) at 0x%x>' %
499
+ (self.__class__.__name__, id(self)))
500
+ return '<%s "%s %s(%s)" at 0x%x>' % (self.__class__.__name__,
501
+ self.rtype,
502
+ self.name,
503
+ args,
504
+ id(self))
505
+
506
+
507
+ class MainFunction(Function):
508
+ """Subclass of Function that allows multiple functions and variables to
509
+ be defined in a single code string. The code must contain a main() function
510
+ definition.
511
+ """
512
+
513
+ def __init__(self, shader_type, *args, **kwargs):
514
+ self.shader_type = shader_type
515
+ self._chains = {}
516
+ Function.__init__(self, *args, **kwargs)
517
+
518
+ @property
519
+ def signature(self):
520
+ return ('main', [], 'void')
521
+
522
+ @property
523
+ def version_pragma(self):
524
+ """Return version number and extra qualifiers from pragma if present."""
525
+ m = re.search(parsing.re_version_pragma, self.code)
526
+ if m is None:
527
+ return None
528
+ return int(m.group(1)), m.group(2)
529
+
530
+ def definition(self, obj_names, version, shader):
531
+ code = Function.definition(self, obj_names, version, shader)
532
+ # strip out version pragma before returning code; this will be
533
+ # added to the final compiled code later.
534
+ code = re.sub(parsing.re_version_pragma, '', code)
535
+ return code
536
+
537
+ def static_names(self):
538
+ if self._static_vars is not None:
539
+ return self._static_vars
540
+
541
+ # parse static variables
542
+ names = Function.static_names(self)
543
+
544
+ # parse all function names + argument names
545
+ funcs = parsing.find_functions(self.code)
546
+ for f in funcs:
547
+ if f[0] == 'main':
548
+ continue
549
+ names.append(f[0])
550
+ for arg in f[1]:
551
+ names.append(arg[1])
552
+
553
+ self._static_vars = names
554
+ return names
555
+
556
+ def add_chain(self, var):
557
+ """Create a new ChainFunction and attach to $var."""
558
+ chain = FunctionChain(var, [])
559
+ self._chains[var] = chain
560
+ self[var] = chain
561
+
562
+ def add_callback(self, hook, func):
563
+ self._chains[hook].append(func)
564
+
565
+ def remove_callback(self, hook, func):
566
+ self._chains[hook].remove(func)
567
+
568
+
569
+ class FunctionChain(Function):
570
+ """Subclass that generates GLSL code to call Function list in order
571
+
572
+ Functions may be called independently, or composed such that the
573
+ output of each function provides the input to the next.
574
+
575
+ Parameters
576
+ ----------
577
+ name : str
578
+ The name of the generated function
579
+ funcs : list of Functions
580
+ The list of Functions that will be called by the generated GLSL code.
581
+
582
+ Examples
583
+ --------
584
+ This creates a function chain::
585
+
586
+ >>> func1 = Function('void my_func_1() {}')
587
+ >>> func2 = Function('void my_func_2() {}')
588
+ >>> chain = FunctionChain('my_func_chain', [func1, func2])
589
+
590
+ If *chain* is included in a ModularProgram, it will generate the following
591
+ output::
592
+
593
+ void my_func_1() {}
594
+ void my_func_2() {}
595
+
596
+ void my_func_chain() {
597
+ my_func_1();
598
+ my_func_2();
599
+ }
600
+
601
+ The return type of the generated function is the same as the return type
602
+ of the last function in the chain. Likewise, the arguments for the
603
+ generated function are the same as the first function in the chain.
604
+
605
+ If the return type is not 'void', then the return value of each function
606
+ will be used to supply the first input argument of the next function in
607
+ the chain. For example::
608
+
609
+ vec3 my_func_1(vec3 input) {return input + vec3(1, 0, 0);}
610
+ void my_func_2(vec3 input) {return input + vec3(0, 1, 0);}
611
+
612
+ vec3 my_func_chain(vec3 input) {
613
+ return my_func_2(my_func_1(input));
614
+ }
615
+ """
616
+
617
+ def __init__(self, name=None, funcs=()):
618
+ # bypass Function.__init__ completely.
619
+ ShaderObject.__init__(self)
620
+ if not (name is None or isinstance(name, str)):
621
+ raise TypeError("Name argument must be string or None.")
622
+ self._funcs = []
623
+ self._code = None
624
+ self._name = name or "chain"
625
+ self._args = []
626
+ self._rtype = 'void'
627
+ self.functions = funcs
628
+
629
+ @property
630
+ def functions(self):
631
+ return self._funcs[:]
632
+
633
+ @functions.setter
634
+ def functions(self, funcs):
635
+ while self._funcs:
636
+ self.remove(self._funcs[0], update=False)
637
+ for f in funcs:
638
+ self.append(f, update=False)
639
+ self._update()
640
+
641
+ @property
642
+ def signature(self):
643
+ return self._name, self._args, self._rtype
644
+
645
+ def _update(self):
646
+ funcs = self._funcs
647
+ if len(funcs) > 0:
648
+ self._rtype = funcs[-1].rtype
649
+ self._args = funcs[0].args[:]
650
+ else:
651
+ self._rtype = 'void'
652
+ self._args = []
653
+
654
+ self.changed(code_changed=True)
655
+
656
+ @property
657
+ def code(self):
658
+ # Code is generated at compile time; hopefully it is not requested
659
+ # before then..
660
+ return None
661
+
662
+ @code.setter
663
+ def code(self, c):
664
+ raise TypeError("Cannot set code property on FunctionChain.")
665
+
666
+ @property
667
+ def template_vars(self):
668
+ return {}
669
+
670
+ def append(self, function, update=True):
671
+ """Append a new function to the end of this chain."""
672
+ self._funcs.append(function)
673
+ self._add_dep(function)
674
+ if update:
675
+ self._update()
676
+
677
+ def __setitem__(self, index, func):
678
+ self._remove_dep(self._funcs[index])
679
+ self._add_dep(func)
680
+ self._funcs[index] = func
681
+
682
+ self._update()
683
+
684
+ def __getitem__(self, k):
685
+ return self.functions[k]
686
+
687
+ def insert(self, index, function, update=True):
688
+ """Insert a new function into the chain at *index*."""
689
+ self._funcs.insert(index, function)
690
+ self._add_dep(function)
691
+ if update:
692
+ self._update()
693
+
694
+ def remove(self, function, update=True):
695
+ """Remove a function from the chain."""
696
+ self._funcs.remove(function)
697
+ self._remove_dep(function)
698
+ if update:
699
+ self._update()
700
+
701
+ def definition(self, obj_names, version, shader):
702
+ name = obj_names[self]
703
+
704
+ args = ", ".join(["%s %s" % arg for arg in self.args])
705
+ code = "%s %s(%s) {\n" % (self.rtype, name, args)
706
+
707
+ result_index = 0
708
+ if len(self.args) == 0:
709
+ last_rtype = 'void'
710
+ last_result = ''
711
+ else:
712
+ last_rtype, last_result = self.args[0][:2]
713
+
714
+ for fn in self._funcs:
715
+ # Use previous return value as an argument to the next function
716
+ if last_rtype == 'void':
717
+ args = ''
718
+ else:
719
+ args = last_result
720
+ if len(fn.args) != 1 or last_rtype != fn.args[0][0]:
721
+ raise Exception("Cannot chain output '%s' of function to "
722
+ "input of '%s'" %
723
+ (last_rtype, fn.signature))
724
+ last_rtype = fn.rtype
725
+
726
+ # Store the return value of this function
727
+ if fn.rtype == 'void':
728
+ set_str = ''
729
+ else:
730
+ result_index += 1
731
+ result = 'result_%d' % result_index
732
+ set_str = '%s %s = ' % (fn.rtype, result)
733
+ last_result = result
734
+
735
+ code += " %s%s(%s);\n" % (set_str, obj_names[fn], args)
736
+
737
+ # return the last function's output
738
+ if self.rtype != 'void':
739
+ code += " return result_%d;\n" % result_index
740
+
741
+ code += "}\n"
742
+ return code
743
+
744
+ def static_names(self):
745
+ return []
746
+
747
+ def __repr__(self):
748
+ fn = ",\n ".join(map(repr, self.functions))
749
+ return "<FunctionChain [%s] at 0x%x>" % (fn, id(self))
750
+
751
+
752
+ class StatementList(ShaderObject):
753
+ """Represents a list of statements."""
754
+
755
+ def __init__(self):
756
+ self.items = {}
757
+ self.order = []
758
+ ShaderObject.__init__(self)
759
+
760
+ def add(self, item, position=5):
761
+ """Add an item to the list unless it is already present.
762
+
763
+ If the item is an expression, then a semicolon will be appended to it
764
+ in the final compiled code.
765
+ """
766
+ if item in self.items:
767
+ return
768
+ self.items[item] = position
769
+ self._add_dep(item)
770
+ self.order = None
771
+ self.changed(code_changed=True)
772
+
773
+ def remove(self, item):
774
+ """Remove an item from the list."""
775
+ self.items.pop(item)
776
+ self._remove_dep(item)
777
+ self.order = None
778
+ self.changed(code_changed=True)
779
+
780
+ def expression(self, obj_names):
781
+ if self.order is None:
782
+ self.order = list(self.items.items())
783
+ self.order.sort(key=lambda x: x[1])
784
+
785
+ code = ""
786
+ for item, pos in self.order:
787
+ code += item.expression(obj_names) + ';\n'
788
+ return code