psychopy 2024.1.0__py3-none-any.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 psychopy might be problematic. Click here for more details.

Files changed (2950) hide show
  1. psychopy/CHANGELOG.txt +3571 -0
  2. psychopy/LICENSE.txt +11 -0
  3. psychopy/LICENSES.txt +55 -0
  4. psychopy/__init__.py +74 -0
  5. psychopy/alerts/__init__.py +65 -0
  6. psychopy/alerts/_alerts.py +184 -0
  7. psychopy/alerts/_errorHandler.py +51 -0
  8. psychopy/alerts/alertsCatalogue/1000.yaml +0 -0
  9. psychopy/alerts/alertsCatalogue/1100.yaml +0 -0
  10. psychopy/alerts/alertsCatalogue/1500.yaml +0 -0
  11. psychopy/alerts/alertsCatalogue/2000.yaml +0 -0
  12. psychopy/alerts/alertsCatalogue/2100.yaml +0 -0
  13. psychopy/alerts/alertsCatalogue/2110.yaml +0 -0
  14. psychopy/alerts/alertsCatalogue/2115.yaml +21 -0
  15. psychopy/alerts/alertsCatalogue/2120.yaml +22 -0
  16. psychopy/alerts/alertsCatalogue/2150.yaml +0 -0
  17. psychopy/alerts/alertsCatalogue/2155.yaml +21 -0
  18. psychopy/alerts/alertsCatalogue/2300.yaml +0 -0
  19. psychopy/alerts/alertsCatalogue/2500.yaml +0 -0
  20. psychopy/alerts/alertsCatalogue/3000.yaml +0 -0
  21. psychopy/alerts/alertsCatalogue/3100.yaml +0 -0
  22. psychopy/alerts/alertsCatalogue/3110.yaml +25 -0
  23. psychopy/alerts/alertsCatalogue/3115.yaml +24 -0
  24. psychopy/alerts/alertsCatalogue/3200.yaml +0 -0
  25. psychopy/alerts/alertsCatalogue/3400.yaml +0 -0
  26. psychopy/alerts/alertsCatalogue/4000.yaml +0 -0
  27. psychopy/alerts/alertsCatalogue/4051.yaml +19 -0
  28. psychopy/alerts/alertsCatalogue/4052.yaml +19 -0
  29. psychopy/alerts/alertsCatalogue/4100.yaml +0 -0
  30. psychopy/alerts/alertsCatalogue/4105.yaml +18 -0
  31. psychopy/alerts/alertsCatalogue/4115.yaml +21 -0
  32. psychopy/alerts/alertsCatalogue/4120.yaml +19 -0
  33. psychopy/alerts/alertsCatalogue/4125.yaml +23 -0
  34. psychopy/alerts/alertsCatalogue/4200.yaml +0 -0
  35. psychopy/alerts/alertsCatalogue/4205.yaml +19 -0
  36. psychopy/alerts/alertsCatalogue/4210.yaml +19 -0
  37. psychopy/alerts/alertsCatalogue/4305.yaml +21 -0
  38. psychopy/alerts/alertsCatalogue/4310.yaml +21 -0
  39. psychopy/alerts/alertsCatalogue/4315.yaml +21 -0
  40. psychopy/alerts/alertsCatalogue/4320.yaml +19 -0
  41. psychopy/alerts/alertsCatalogue/4325.yaml +23 -0
  42. psychopy/alerts/alertsCatalogue/4330.yaml +19 -0
  43. psychopy/alerts/alertsCatalogue/4335.yaml +19 -0
  44. psychopy/alerts/alertsCatalogue/4340.yaml +19 -0
  45. psychopy/alerts/alertsCatalogue/4405.yaml +24 -0
  46. psychopy/alerts/alertsCatalogue/4505.yaml +22 -0
  47. psychopy/alerts/alertsCatalogue/4510.yaml +25 -0
  48. psychopy/alerts/alertsCatalogue/4520.yaml +26 -0
  49. psychopy/alerts/alertsCatalogue/4530.yaml +23 -0
  50. psychopy/alerts/alertsCatalogue/4540.yaml +19 -0
  51. psychopy/alerts/alertsCatalogue/4545.yaml +22 -0
  52. psychopy/alerts/alertsCatalogue/4550.yaml +19 -0
  53. psychopy/alerts/alertsCatalogue/4605.yaml +22 -0
  54. psychopy/alerts/alertsCatalogue/4610.yaml +22 -0
  55. psychopy/alerts/alertsCatalogue/4615.yaml +19 -0
  56. psychopy/alerts/alertsCatalogue/4705.yaml +19 -0
  57. psychopy/alerts/alertsCatalogue/4710.yaml +19 -0
  58. psychopy/alerts/alertsCatalogue/5000.yaml +0 -0
  59. psychopy/alerts/alertsCatalogue/5055.yaml +25 -0
  60. psychopy/alerts/alertsCatalogue/6000.yaml +0 -0
  61. psychopy/alerts/alertsCatalogue/6105.yaml +18 -0
  62. psychopy/alerts/alertsCatalogue/7105.yaml +19 -0
  63. psychopy/alerts/alertsCatalogue/8105.yaml +21 -0
  64. psychopy/alerts/alertsCatalogue/8110.yaml +21 -0
  65. psychopy/alerts/alertsCatalogue/9998.yaml +19 -0
  66. psychopy/alerts/alertsCatalogue/9999.yaml +19 -0
  67. psychopy/alerts/alertsCatalogue/alertCategories.yaml +109 -0
  68. psychopy/alerts/alertsCatalogue/alertTemplate.yaml +19 -0
  69. psychopy/alerts/alertsCatalogue/alertmsg.py +144 -0
  70. psychopy/alerts/alertsCatalogue/generateAlertmsg.py +34 -0
  71. psychopy/alerts/alerttools.py +338 -0
  72. psychopy/app/Resources/Psychopy Window Favicon@16w.png +0 -0
  73. psychopy/app/Resources/Psychopy Window Favicon@32w.png +0 -0
  74. psychopy/app/Resources/README.md +12 -0
  75. psychopy/app/Resources/USB-C.png +0 -0
  76. psychopy/app/Resources/USB.png +0 -0
  77. psychopy/app/Resources/__init__.py +0 -0
  78. psychopy/app/Resources/builder.ico +0 -0
  79. psychopy/app/Resources/classic/FlowBottom_CompLeft.png +0 -0
  80. psychopy/app/Resources/classic/FlowBottom_CompRight.png +0 -0
  81. psychopy/app/Resources/classic/FlowTop_CompLeft.png +0 -0
  82. psychopy/app/Resources/classic/FlowTop_CompRight.png +0 -0
  83. psychopy/app/Resources/classic/README.txt +9 -0
  84. psychopy/app/Resources/classic/__init__.py +0 -0
  85. psychopy/app/Resources/classic/_layouts.ai +1138 -1
  86. psychopy/app/Resources/classic/add.png +0 -0
  87. psychopy/app/Resources/classic/add@2x.png +0 -0
  88. psychopy/app/Resources/classic/addExp32.png +0 -0
  89. psychopy/app/Resources/classic/alerts.png +0 -0
  90. psychopy/app/Resources/classic/beta.png +0 -0
  91. psychopy/app/Resources/classic/browser.png +0 -0
  92. psychopy/app/Resources/classic/browser@2x.png +0 -0
  93. psychopy/app/Resources/classic/bug16.png +0 -0
  94. psychopy/app/Resources/classic/circle_mask.png +0 -0
  95. psychopy/app/Resources/classic/circle_mask@2x.png +0 -0
  96. psychopy/app/Resources/classic/clear.png +0 -0
  97. psychopy/app/Resources/classic/clear@2x.png +0 -0
  98. psychopy/app/Resources/classic/coderclass16.png +0 -0
  99. psychopy/app/Resources/classic/coderfunc16.png +0 -0
  100. psychopy/app/Resources/classic/coderimport16.png +0 -0
  101. psychopy/app/Resources/classic/coderjs16.png +0 -0
  102. psychopy/app/Resources/classic/coderpython16.png +0 -0
  103. psychopy/app/Resources/classic/codervar16.png +0 -0
  104. psychopy/app/Resources/classic/cogwindow32.png +0 -0
  105. psychopy/app/Resources/classic/color32.png +0 -0
  106. psychopy/app/Resources/classic/compile32.png +0 -0
  107. psychopy/app/Resources/classic/compile_js.png +0 -0
  108. psychopy/app/Resources/classic/compile_js@2x.png +0 -0
  109. psychopy/app/Resources/classic/compile_py.png +0 -0
  110. psychopy/app/Resources/classic/compile_py@2x.png +0 -0
  111. psychopy/app/Resources/classic/copy16.png +0 -0
  112. psychopy/app/Resources/classic/currentFile.png +0 -0
  113. psychopy/app/Resources/classic/currentFile@2x.png +0 -0
  114. psychopy/app/Resources/classic/delete16.png +0 -0
  115. psychopy/app/Resources/classic/desktop.png +0 -0
  116. psychopy/app/Resources/classic/desktop@2x.png +0 -0
  117. psychopy/app/Resources/classic/dirup16.png +0 -0
  118. psychopy/app/Resources/classic/docclose16.png +0 -0
  119. psychopy/app/Resources/classic/download.png +0 -0
  120. psychopy/app/Resources/classic/edit.png +0 -0
  121. psychopy/app/Resources/classic/edit@2x.png +0 -0
  122. psychopy/app/Resources/classic/editbtn.png +0 -0
  123. psychopy/app/Resources/classic/editbtn16.png +0 -0
  124. psychopy/app/Resources/classic/editbtn16@2x.png +0 -0
  125. psychopy/app/Resources/classic/editbtn@2x.png +0 -0
  126. psychopy/app/Resources/classic/email.png +0 -0
  127. psychopy/app/Resources/classic/email@2x.png +0 -0
  128. psychopy/app/Resources/classic/experiment.png +0 -0
  129. psychopy/app/Resources/classic/experiment@2x.png +0 -0
  130. psychopy/app/Resources/classic/expsettings.png +0 -0
  131. psychopy/app/Resources/classic/expsettings@2x.png +0 -0
  132. psychopy/app/Resources/classic/file.png +0 -0
  133. psychopy/app/Resources/classic/file@2x.png +0 -0
  134. psychopy/app/Resources/classic/filecsv16.png +0 -0
  135. psychopy/app/Resources/classic/fileimage16.png +0 -0
  136. psychopy/app/Resources/classic/filenew.png +0 -0
  137. psychopy/app/Resources/classic/filenew32.png +0 -0
  138. psychopy/app/Resources/classic/filenew@2x.png +0 -0
  139. psychopy/app/Resources/classic/fileopen.png +0 -0
  140. psychopy/app/Resources/classic/fileopen32.png +0 -0
  141. psychopy/app/Resources/classic/fileopen@2x.png +0 -0
  142. psychopy/app/Resources/classic/filesave.png +0 -0
  143. psychopy/app/Resources/classic/filesave32.png +0 -0
  144. psychopy/app/Resources/classic/filesave@2x.png +0 -0
  145. psychopy/app/Resources/classic/filesaveas.png +0 -0
  146. psychopy/app/Resources/classic/filesaveas32.png +0 -0
  147. psychopy/app/Resources/classic/filesaveas@2x.png +0 -0
  148. psychopy/app/Resources/classic/fileunknown16.png +0 -0
  149. psychopy/app/Resources/classic/filter.png +0 -0
  150. psychopy/app/Resources/classic/filter@2x.png +0 -0
  151. psychopy/app/Resources/classic/folder-open16.png +0 -0
  152. psychopy/app/Resources/classic/folder16.png +0 -0
  153. psychopy/app/Resources/classic/foldernew16.png +0 -0
  154. psychopy/app/Resources/classic/fork.png +0 -0
  155. psychopy/app/Resources/classic/fork@2x.png +0 -0
  156. psychopy/app/Resources/classic/github.png +0 -0
  157. psychopy/app/Resources/classic/github@2x.png +0 -0
  158. psychopy/app/Resources/classic/globe.png +0 -0
  159. psychopy/app/Resources/classic/globe@2x.png +0 -0
  160. psychopy/app/Resources/classic/globe_bug.png +0 -0
  161. psychopy/app/Resources/classic/globe_bug@2x.png +0 -0
  162. psychopy/app/Resources/classic/globe_greensync.png +0 -0
  163. psychopy/app/Resources/classic/globe_greensync@2x.png +0 -0
  164. psychopy/app/Resources/classic/globe_info.png +0 -0
  165. psychopy/app/Resources/classic/globe_info@2x.png +0 -0
  166. psychopy/app/Resources/classic/globe_magnifier.png +0 -0
  167. psychopy/app/Resources/classic/globe_magnifier@2x.png +0 -0
  168. psychopy/app/Resources/classic/globe_run.png +0 -0
  169. psychopy/app/Resources/classic/globe_run@2x.png +0 -0
  170. psychopy/app/Resources/classic/globe_user.png +0 -0
  171. psychopy/app/Resources/classic/globe_user@2x.png +0 -0
  172. psychopy/app/Resources/classic/goto16.png +0 -0
  173. psychopy/app/Resources/classic/greendot.png +0 -0
  174. psychopy/app/Resources/classic/greendot@2x.png +0 -0
  175. psychopy/app/Resources/classic/greenglobe.png +0 -0
  176. psychopy/app/Resources/classic/greenglobe@2x.png +0 -0
  177. psychopy/app/Resources/classic/greenglobe_bug.png +0 -0
  178. psychopy/app/Resources/classic/greenglobe_bug@2x.png +0 -0
  179. psychopy/app/Resources/classic/greenglobe_greensync.png +0 -0
  180. psychopy/app/Resources/classic/greenglobe_greensync@2x.png +0 -0
  181. psychopy/app/Resources/classic/greenglobe_info.png +0 -0
  182. psychopy/app/Resources/classic/greenglobe_info@2x.png +0 -0
  183. psychopy/app/Resources/classic/greenglobe_magnifier.png +0 -0
  184. psychopy/app/Resources/classic/greenglobe_magnifier@2x.png +0 -0
  185. psychopy/app/Resources/classic/greenglobe_run.png +0 -0
  186. psychopy/app/Resources/classic/greenglobe_run@2x.png +0 -0
  187. psychopy/app/Resources/classic/greenglobe_user.png +0 -0
  188. psychopy/app/Resources/classic/greenglobe_user@2x.png +0 -0
  189. psychopy/app/Resources/classic/greydot.png +0 -0
  190. psychopy/app/Resources/classic/greydot@2x.png +0 -0
  191. psychopy/app/Resources/classic/greytick.png +0 -0
  192. psychopy/app/Resources/classic/greytick@2x.png +0 -0
  193. psychopy/app/Resources/classic/invalid_img.png +0 -0
  194. psychopy/app/Resources/classic/jsPilot.png +0 -0
  195. psychopy/app/Resources/classic/jsPilot@2x.png +0 -0
  196. psychopy/app/Resources/classic/jsRun.png +0 -0
  197. psychopy/app/Resources/classic/jsRun@2x.png +0 -0
  198. psychopy/app/Resources/classic/libroot.png +0 -0
  199. psychopy/app/Resources/classic/libroot@2x.png +0 -0
  200. psychopy/app/Resources/classic/monitor16.png +0 -0
  201. psychopy/app/Resources/classic/monitors.png +0 -0
  202. psychopy/app/Resources/classic/monitors16.png +0 -0
  203. psychopy/app/Resources/classic/monitors32.png +0 -0
  204. psychopy/app/Resources/classic/monitors@2x.png +0 -0
  205. psychopy/app/Resources/classic/orangedot.png +0 -0
  206. psychopy/app/Resources/classic/orangedot@2x.png +0 -0
  207. psychopy/app/Resources/classic/pavlovia.png +0 -0
  208. psychopy/app/Resources/classic/pavlovia16.png +0 -0
  209. psychopy/app/Resources/classic/pavlovia16@2x.png +0 -0
  210. psychopy/app/Resources/classic/pavlovia@2x.png +0 -0
  211. psychopy/app/Resources/classic/pavsync.png +0 -0
  212. psychopy/app/Resources/classic/pavsync@2x.png +0 -0
  213. psychopy/app/Resources/classic/person_off.png +0 -0
  214. psychopy/app/Resources/classic/person_off@2x.png +0 -0
  215. psychopy/app/Resources/classic/person_on.png +0 -0
  216. psychopy/app/Resources/classic/person_on@2x.png +0 -0
  217. psychopy/app/Resources/classic/plugins32.png +0 -0
  218. psychopy/app/Resources/classic/plus.png +0 -0
  219. psychopy/app/Resources/classic/plus@2x.png +0 -0
  220. psychopy/app/Resources/classic/preferences-app.png +0 -0
  221. psychopy/app/Resources/classic/preferences-app48.png +0 -0
  222. psychopy/app/Resources/classic/preferences-app@2x.png +0 -0
  223. psychopy/app/Resources/classic/preferences-conn.png +0 -0
  224. psychopy/app/Resources/classic/preferences-conn48.png +0 -0
  225. psychopy/app/Resources/classic/preferences-conn@2x.png +0 -0
  226. psychopy/app/Resources/classic/preferences-debug.png +0 -0
  227. psychopy/app/Resources/classic/preferences-debug@2x.png +0 -0
  228. psychopy/app/Resources/classic/preferences-general.png +0 -0
  229. psychopy/app/Resources/classic/preferences-general48.png +0 -0
  230. psychopy/app/Resources/classic/preferences-general@2x.png +0 -0
  231. psychopy/app/Resources/classic/preferences-hardware.png +0 -0
  232. psychopy/app/Resources/classic/preferences-hardware48.png +0 -0
  233. psychopy/app/Resources/classic/preferences-hardware@2x.png +0 -0
  234. psychopy/app/Resources/classic/preferences-keyboard.png +0 -0
  235. psychopy/app/Resources/classic/preferences-keyboard48.png +0 -0
  236. psychopy/app/Resources/classic/preferences-keyboard@2x.png +0 -0
  237. psychopy/app/Resources/classic/preferences-pilot.png +0 -0
  238. psychopy/app/Resources/classic/preferences-pilot@2x.png +0 -0
  239. psychopy/app/Resources/classic/preferences32.png +0 -0
  240. psychopy/app/Resources/classic/pyPilot.png +0 -0
  241. psychopy/app/Resources/classic/pyPilot@2x.png +0 -0
  242. psychopy/app/Resources/classic/pyRun.png +0 -0
  243. psychopy/app/Resources/classic/pyRun@2x.png +0 -0
  244. psychopy/app/Resources/classic/reddot.png +0 -0
  245. psychopy/app/Resources/classic/reddot@2x.png +0 -0
  246. psychopy/app/Resources/classic/redglobe.png +0 -0
  247. psychopy/app/Resources/classic/redglobe@2x.png +0 -0
  248. psychopy/app/Resources/classic/redglobe_bug.png +0 -0
  249. psychopy/app/Resources/classic/redglobe_bug@2x.png +0 -0
  250. psychopy/app/Resources/classic/redglobe_greensync.png +0 -0
  251. psychopy/app/Resources/classic/redglobe_greensync@2x.png +0 -0
  252. psychopy/app/Resources/classic/redglobe_info.png +0 -0
  253. psychopy/app/Resources/classic/redglobe_info@2x.png +0 -0
  254. psychopy/app/Resources/classic/redglobe_magnifier.png +0 -0
  255. psychopy/app/Resources/classic/redglobe_magnifier@2x.png +0 -0
  256. psychopy/app/Resources/classic/redglobe_run.png +0 -0
  257. psychopy/app/Resources/classic/redglobe_run@2x.png +0 -0
  258. psychopy/app/Resources/classic/redglobe_user.png +0 -0
  259. psychopy/app/Resources/classic/redglobe_user@2x.png +0 -0
  260. psychopy/app/Resources/classic/redo.png +0 -0
  261. psychopy/app/Resources/classic/redo32.png +0 -0
  262. psychopy/app/Resources/classic/redo@2x.png +0 -0
  263. psychopy/app/Resources/classic/removeExp32.png +0 -0
  264. psychopy/app/Resources/classic/rename16.png +0 -0
  265. psychopy/app/Resources/classic/restart.png +0 -0
  266. psychopy/app/Resources/classic/restart@2x.png +0 -0
  267. psychopy/app/Resources/classic/run.png +0 -0
  268. psychopy/app/Resources/classic/run@2x.png +0 -0
  269. psychopy/app/Resources/classic/runner.png +0 -0
  270. psychopy/app/Resources/classic/runner@2x.png +0 -0
  271. psychopy/app/Resources/classic/runnerPilot.png +0 -0
  272. psychopy/app/Resources/classic/runnerPilot@2x.png +0 -0
  273. psychopy/app/Resources/classic/savebtn.png +0 -0
  274. psychopy/app/Resources/classic/savebtn16.png +0 -0
  275. psychopy/app/Resources/classic/savebtn16@2x.png +0 -0
  276. psychopy/app/Resources/classic/savebtn@2x.png +0 -0
  277. psychopy/app/Resources/classic/search.png +0 -0
  278. psychopy/app/Resources/classic/search@2x.png +0 -0
  279. psychopy/app/Resources/classic/showBuilder.png +0 -0
  280. psychopy/app/Resources/classic/showBuilder@2x.png +0 -0
  281. psychopy/app/Resources/classic/showCoder.png +0 -0
  282. psychopy/app/Resources/classic/showCoder@2x.png +0 -0
  283. psychopy/app/Resources/classic/showRunner.png +0 -0
  284. psychopy/app/Resources/classic/showRunner@2x.png +0 -0
  285. psychopy/app/Resources/classic/starred.png +0 -0
  286. psychopy/app/Resources/classic/starred@2x.png +0 -0
  287. psychopy/app/Resources/classic/start.png +0 -0
  288. psychopy/app/Resources/classic/start@2x.png +0 -0
  289. psychopy/app/Resources/classic/stdout.png +0 -0
  290. psychopy/app/Resources/classic/stop.png +0 -0
  291. psychopy/app/Resources/classic/stop32.png +0 -0
  292. psychopy/app/Resources/classic/stop@2x.png +0 -0
  293. psychopy/app/Resources/classic/switchCtrlBot.png +0 -0
  294. psychopy/app/Resources/classic/switchCtrlBot@2x.png +0 -0
  295. psychopy/app/Resources/classic/switchCtrlLeft.png +0 -0
  296. psychopy/app/Resources/classic/switchCtrlLeft@2x.png +0 -0
  297. psychopy/app/Resources/classic/switchCtrlRight.png +0 -0
  298. psychopy/app/Resources/classic/switchCtrlRight@2x.png +0 -0
  299. psychopy/app/Resources/classic/switchCtrlTop.png +0 -0
  300. psychopy/app/Resources/classic/switchCtrlTop@2x.png +0 -0
  301. psychopy/app/Resources/classic/tick.png +0 -0
  302. psychopy/app/Resources/classic/tick@2x.png +0 -0
  303. psychopy/app/Resources/classic/undo.png +0 -0
  304. psychopy/app/Resources/classic/undo32.png +0 -0
  305. psychopy/app/Resources/classic/undo@2x.png +0 -0
  306. psychopy/app/Resources/classic/unstarred.png +0 -0
  307. psychopy/app/Resources/classic/unstarred@2x.png +0 -0
  308. psychopy/app/Resources/classic/user_none.png +0 -0
  309. psychopy/app/Resources/classic/view-refresh16.png +0 -0
  310. psychopy/app/Resources/classic/viewbtn.png +0 -0
  311. psychopy/app/Resources/classic/viewbtn16.png +0 -0
  312. psychopy/app/Resources/classic/viewbtn16@2x.png +0 -0
  313. psychopy/app/Resources/classic/viewbtn@2x.png +0 -0
  314. psychopy/app/Resources/classic/windows16.png +0 -0
  315. psychopy/app/Resources/classic/windows16@2x.png +0 -0
  316. psychopy/app/Resources/click.png +0 -0
  317. psychopy/app/Resources/coder.ico +0 -0
  318. psychopy/app/Resources/creditCard.png +0 -0
  319. psychopy/app/Resources/dark/FlowBottom_CompLeft.png +0 -0
  320. psychopy/app/Resources/dark/FlowBottom_CompRight.png +0 -0
  321. psychopy/app/Resources/dark/FlowTop_CompLeft.png +0 -0
  322. psychopy/app/Resources/dark/FlowTop_CompRight.png +0 -0
  323. psychopy/app/Resources/dark/README.txt +3 -0
  324. psychopy/app/Resources/dark/__init__.py +0 -0
  325. psychopy/app/Resources/dark/add.png +0 -0
  326. psychopy/app/Resources/dark/add@2x.png +0 -0
  327. psychopy/app/Resources/dark/addExp32.png +0 -0
  328. psychopy/app/Resources/dark/addExp32@2x.png +0 -0
  329. psychopy/app/Resources/dark/alerts.png +0 -0
  330. psychopy/app/Resources/dark/alerts@2x.png +0 -0
  331. psychopy/app/Resources/dark/beta.png +0 -0
  332. psychopy/app/Resources/dark/beta@2x.png +0 -0
  333. psychopy/app/Resources/dark/browser.png +0 -0
  334. psychopy/app/Resources/dark/browser@2x.png +0 -0
  335. psychopy/app/Resources/dark/bug16.png +0 -0
  336. psychopy/app/Resources/dark/bug16@2x.png +0 -0
  337. psychopy/app/Resources/dark/circle_mask.png +0 -0
  338. psychopy/app/Resources/dark/circle_mask@2x.png +0 -0
  339. psychopy/app/Resources/dark/clear.png +0 -0
  340. psychopy/app/Resources/dark/clear@2x.png +0 -0
  341. psychopy/app/Resources/dark/coderclass16.png +0 -0
  342. psychopy/app/Resources/dark/coderclass16@2x.png +0 -0
  343. psychopy/app/Resources/dark/coderfunc16.png +0 -0
  344. psychopy/app/Resources/dark/coderfunc16@2x.png +0 -0
  345. psychopy/app/Resources/dark/coderimport16.png +0 -0
  346. psychopy/app/Resources/dark/coderimport16@2x.png +0 -0
  347. psychopy/app/Resources/dark/coderjs.png +0 -0
  348. psychopy/app/Resources/dark/coderjs@2x.png +0 -0
  349. psychopy/app/Resources/dark/coderpython.png +0 -0
  350. psychopy/app/Resources/dark/coderpython@2x.png +0 -0
  351. psychopy/app/Resources/dark/codervar16.png +0 -0
  352. psychopy/app/Resources/dark/codervar16@2x.png +0 -0
  353. psychopy/app/Resources/dark/cogwindow32.png +0 -0
  354. psychopy/app/Resources/dark/cogwindow32@2x.png +0 -0
  355. psychopy/app/Resources/dark/color32.png +0 -0
  356. psychopy/app/Resources/dark/color32@2x.png +0 -0
  357. psychopy/app/Resources/dark/compile_js.png +0 -0
  358. psychopy/app/Resources/dark/compile_js@2x.png +0 -0
  359. psychopy/app/Resources/dark/compile_py.png +0 -0
  360. psychopy/app/Resources/dark/compile_py@2x.png +0 -0
  361. psychopy/app/Resources/dark/copy16.png +0 -0
  362. psychopy/app/Resources/dark/copy16@2x.png +0 -0
  363. psychopy/app/Resources/dark/currentFile16.png +0 -0
  364. psychopy/app/Resources/dark/currentFile16@2x.png +0 -0
  365. psychopy/app/Resources/dark/delete16.png +0 -0
  366. psychopy/app/Resources/dark/delete16@2x.png +0 -0
  367. psychopy/app/Resources/dark/desktop.png +0 -0
  368. psychopy/app/Resources/dark/desktop@2x.png +0 -0
  369. psychopy/app/Resources/dark/dirup16.png +0 -0
  370. psychopy/app/Resources/dark/dirup16@2x.png +0 -0
  371. psychopy/app/Resources/dark/docclose16.png +0 -0
  372. psychopy/app/Resources/dark/docclose16@2x.png +0 -0
  373. psychopy/app/Resources/dark/download.png +0 -0
  374. psychopy/app/Resources/dark/download@2x.png +0 -0
  375. psychopy/app/Resources/dark/edit.png +0 -0
  376. psychopy/app/Resources/dark/edit@2x.png +0 -0
  377. psychopy/app/Resources/dark/editbtn16.png +0 -0
  378. psychopy/app/Resources/dark/editbtn16@2x.png +0 -0
  379. psychopy/app/Resources/dark/email.png +0 -0
  380. psychopy/app/Resources/dark/email@2x.png +0 -0
  381. psychopy/app/Resources/dark/experiment.png +0 -0
  382. psychopy/app/Resources/dark/experiment@2x.png +0 -0
  383. psychopy/app/Resources/dark/expsettings.png +0 -0
  384. psychopy/app/Resources/dark/expsettings@2x.png +0 -0
  385. psychopy/app/Resources/dark/file.png +0 -0
  386. psychopy/app/Resources/dark/file@16w.png +0 -0
  387. psychopy/app/Resources/dark/file@16w@2x.png +0 -0
  388. psychopy/app/Resources/dark/file@2x.png +0 -0
  389. psychopy/app/Resources/dark/filecsv16.png +0 -0
  390. psychopy/app/Resources/dark/filecsv16@2x.png +0 -0
  391. psychopy/app/Resources/dark/fileimage16.png +0 -0
  392. psychopy/app/Resources/dark/fileimage16@2x.png +0 -0
  393. psychopy/app/Resources/dark/filenew.png +0 -0
  394. psychopy/app/Resources/dark/filenew32.png +0 -0
  395. psychopy/app/Resources/dark/filenew32@2x.png +0 -0
  396. psychopy/app/Resources/dark/filenew@2x.png +0 -0
  397. psychopy/app/Resources/dark/fileopen.png +0 -0
  398. psychopy/app/Resources/dark/fileopen32.png +0 -0
  399. psychopy/app/Resources/dark/fileopen32@2x.png +0 -0
  400. psychopy/app/Resources/dark/fileopen@2x.png +0 -0
  401. psychopy/app/Resources/dark/filesave.png +0 -0
  402. psychopy/app/Resources/dark/filesave32.png +0 -0
  403. psychopy/app/Resources/dark/filesave32@2x.png +0 -0
  404. psychopy/app/Resources/dark/filesave@2x.png +0 -0
  405. psychopy/app/Resources/dark/filesaveas.png +0 -0
  406. psychopy/app/Resources/dark/filesaveas32.png +0 -0
  407. psychopy/app/Resources/dark/filesaveas32@2x.png +0 -0
  408. psychopy/app/Resources/dark/filesaveas@2x.png +0 -0
  409. psychopy/app/Resources/dark/fileunknown16.png +0 -0
  410. psychopy/app/Resources/dark/fileunknown16@2x.png +0 -0
  411. psychopy/app/Resources/dark/filter.png +0 -0
  412. psychopy/app/Resources/dark/filter@2x.png +0 -0
  413. psychopy/app/Resources/dark/folder-open16.png +0 -0
  414. psychopy/app/Resources/dark/folder-open16@2x.png +0 -0
  415. psychopy/app/Resources/dark/folder16.png +0 -0
  416. psychopy/app/Resources/dark/folder16@2x.png +0 -0
  417. psychopy/app/Resources/dark/foldernew16.png +0 -0
  418. psychopy/app/Resources/dark/foldernew16@2x.png +0 -0
  419. psychopy/app/Resources/dark/fork.png +0 -0
  420. psychopy/app/Resources/dark/fork@2x.png +0 -0
  421. psychopy/app/Resources/dark/github.png +0 -0
  422. psychopy/app/Resources/dark/github@2x.png +0 -0
  423. psychopy/app/Resources/dark/globe.png +0 -0
  424. psychopy/app/Resources/dark/globe@2x.png +0 -0
  425. psychopy/app/Resources/dark/globe_bug.png +0 -0
  426. psychopy/app/Resources/dark/globe_bug@2x.png +0 -0
  427. psychopy/app/Resources/dark/globe_greensync.png +0 -0
  428. psychopy/app/Resources/dark/globe_greensync@2x.png +0 -0
  429. psychopy/app/Resources/dark/globe_info.png +0 -0
  430. psychopy/app/Resources/dark/globe_info@2x.png +0 -0
  431. psychopy/app/Resources/dark/globe_magnifier.png +0 -0
  432. psychopy/app/Resources/dark/globe_magnifier@2x.png +0 -0
  433. psychopy/app/Resources/dark/globe_run.png +0 -0
  434. psychopy/app/Resources/dark/globe_run@2x.png +0 -0
  435. psychopy/app/Resources/dark/globe_user.png +0 -0
  436. psychopy/app/Resources/dark/globe_user@2x.png +0 -0
  437. psychopy/app/Resources/dark/goto.png +0 -0
  438. psychopy/app/Resources/dark/goto@2x.png +0 -0
  439. psychopy/app/Resources/dark/greendot.png +0 -0
  440. psychopy/app/Resources/dark/greendot@2x.png +0 -0
  441. psychopy/app/Resources/dark/greenglobe.png +0 -0
  442. psychopy/app/Resources/dark/greenglobe@2x.png +0 -0
  443. psychopy/app/Resources/dark/greenglobe_bug.png +0 -0
  444. psychopy/app/Resources/dark/greenglobe_bug@2x.png +0 -0
  445. psychopy/app/Resources/dark/greenglobe_greensync.png +0 -0
  446. psychopy/app/Resources/dark/greenglobe_greensync@2x.png +0 -0
  447. psychopy/app/Resources/dark/greenglobe_info.png +0 -0
  448. psychopy/app/Resources/dark/greenglobe_info@2x.png +0 -0
  449. psychopy/app/Resources/dark/greenglobe_magnifier.png +0 -0
  450. psychopy/app/Resources/dark/greenglobe_magnifier@2x.png +0 -0
  451. psychopy/app/Resources/dark/greenglobe_run.png +0 -0
  452. psychopy/app/Resources/dark/greenglobe_run@2x.png +0 -0
  453. psychopy/app/Resources/dark/greenglobe_user.png +0 -0
  454. psychopy/app/Resources/dark/greenglobe_user@2x.png +0 -0
  455. psychopy/app/Resources/dark/greydot.png +0 -0
  456. psychopy/app/Resources/dark/greydot@2x.png +0 -0
  457. psychopy/app/Resources/dark/greytick.png +0 -0
  458. psychopy/app/Resources/dark/greytick@2x.png +0 -0
  459. psychopy/app/Resources/dark/invalid_img.png +0 -0
  460. psychopy/app/Resources/dark/jsPilot.png +0 -0
  461. psychopy/app/Resources/dark/jsPilot@2x.png +0 -0
  462. psychopy/app/Resources/dark/jsRun.png +0 -0
  463. psychopy/app/Resources/dark/jsRun@2x.png +0 -0
  464. psychopy/app/Resources/dark/libroot16.png +0 -0
  465. psychopy/app/Resources/dark/libroot16@2x.png +0 -0
  466. psychopy/app/Resources/dark/monitor16.png +0 -0
  467. psychopy/app/Resources/dark/monitor16@2x.png +0 -0
  468. psychopy/app/Resources/dark/monitors.png +0 -0
  469. psychopy/app/Resources/dark/monitors32.png +0 -0
  470. psychopy/app/Resources/dark/monitors32@2x.png +0 -0
  471. psychopy/app/Resources/dark/monitors@2x.png +0 -0
  472. psychopy/app/Resources/dark/orangedot.png +0 -0
  473. psychopy/app/Resources/dark/orangedot@2x.png +0 -0
  474. psychopy/app/Resources/dark/pavlovia.png +0 -0
  475. psychopy/app/Resources/dark/pavlovia16.png +0 -0
  476. psychopy/app/Resources/dark/pavlovia16@2x.png +0 -0
  477. psychopy/app/Resources/dark/pavlovia@2x.png +0 -0
  478. psychopy/app/Resources/dark/pavsync.png +0 -0
  479. psychopy/app/Resources/dark/pavsync@2x.png +0 -0
  480. psychopy/app/Resources/dark/person_off.png +0 -0
  481. psychopy/app/Resources/dark/person_off@2x.png +0 -0
  482. psychopy/app/Resources/dark/person_on.png +0 -0
  483. psychopy/app/Resources/dark/person_on@2x.png +0 -0
  484. psychopy/app/Resources/dark/plugins32.png +0 -0
  485. psychopy/app/Resources/dark/plugins32@2x.png +0 -0
  486. psychopy/app/Resources/dark/plus.png +0 -0
  487. psychopy/app/Resources/dark/plus@2x.png +0 -0
  488. psychopy/app/Resources/dark/preferences-app.png +0 -0
  489. psychopy/app/Resources/dark/preferences-app48.png +0 -0
  490. psychopy/app/Resources/dark/preferences-app48@2x.png +0 -0
  491. psychopy/app/Resources/dark/preferences-app@2x.png +0 -0
  492. psychopy/app/Resources/dark/preferences-conn.png +0 -0
  493. psychopy/app/Resources/dark/preferences-conn48.png +0 -0
  494. psychopy/app/Resources/dark/preferences-conn48@2x.png +0 -0
  495. psychopy/app/Resources/dark/preferences-conn@2x.png +0 -0
  496. psychopy/app/Resources/dark/preferences-debug.png +0 -0
  497. psychopy/app/Resources/dark/preferences-debug@2x.png +0 -0
  498. psychopy/app/Resources/dark/preferences-general.png +0 -0
  499. psychopy/app/Resources/dark/preferences-general48.png +0 -0
  500. psychopy/app/Resources/dark/preferences-general48@2x.png +0 -0
  501. psychopy/app/Resources/dark/preferences-general@2x.png +0 -0
  502. psychopy/app/Resources/dark/preferences-hardware.png +0 -0
  503. psychopy/app/Resources/dark/preferences-hardware48.png +0 -0
  504. psychopy/app/Resources/dark/preferences-hardware48@2x.png +0 -0
  505. psychopy/app/Resources/dark/preferences-hardware@2x.png +0 -0
  506. psychopy/app/Resources/dark/preferences-keyboard.png +0 -0
  507. psychopy/app/Resources/dark/preferences-keyboard48.png +0 -0
  508. psychopy/app/Resources/dark/preferences-keyboard48@2x.png +0 -0
  509. psychopy/app/Resources/dark/preferences-keyboard@2x.png +0 -0
  510. psychopy/app/Resources/dark/preferences-pilot.png +0 -0
  511. psychopy/app/Resources/dark/preferences-pilot@2x.png +0 -0
  512. psychopy/app/Resources/dark/preferences32.png +0 -0
  513. psychopy/app/Resources/dark/preferences32@2x.png +0 -0
  514. psychopy/app/Resources/dark/pyPilot.png +0 -0
  515. psychopy/app/Resources/dark/pyPilot@2x.png +0 -0
  516. psychopy/app/Resources/dark/pyRun.png +0 -0
  517. psychopy/app/Resources/dark/pyRun@2x.png +0 -0
  518. psychopy/app/Resources/dark/reddot.png +0 -0
  519. psychopy/app/Resources/dark/reddot@2x.png +0 -0
  520. psychopy/app/Resources/dark/redglobe.png +0 -0
  521. psychopy/app/Resources/dark/redglobe@2x.png +0 -0
  522. psychopy/app/Resources/dark/redglobe_bug.png +0 -0
  523. psychopy/app/Resources/dark/redglobe_bug@2x.png +0 -0
  524. psychopy/app/Resources/dark/redglobe_greensync.png +0 -0
  525. psychopy/app/Resources/dark/redglobe_greensync@2x.png +0 -0
  526. psychopy/app/Resources/dark/redglobe_info.png +0 -0
  527. psychopy/app/Resources/dark/redglobe_info@2x.png +0 -0
  528. psychopy/app/Resources/dark/redglobe_magnifier.png +0 -0
  529. psychopy/app/Resources/dark/redglobe_magnifier@2x.png +0 -0
  530. psychopy/app/Resources/dark/redglobe_run.png +0 -0
  531. psychopy/app/Resources/dark/redglobe_run@2x.png +0 -0
  532. psychopy/app/Resources/dark/redglobe_user.png +0 -0
  533. psychopy/app/Resources/dark/redglobe_user@2x.png +0 -0
  534. psychopy/app/Resources/dark/redo.png +0 -0
  535. psychopy/app/Resources/dark/redo32.png +0 -0
  536. psychopy/app/Resources/dark/redo32@2x.png +0 -0
  537. psychopy/app/Resources/dark/redo@2x.png +0 -0
  538. psychopy/app/Resources/dark/removeExp32.png +0 -0
  539. psychopy/app/Resources/dark/removeExp32@2x.png +0 -0
  540. psychopy/app/Resources/dark/rename16.png +0 -0
  541. psychopy/app/Resources/dark/rename16@2x.png +0 -0
  542. psychopy/app/Resources/dark/restart.png +0 -0
  543. psychopy/app/Resources/dark/restart@2x.png +0 -0
  544. psychopy/app/Resources/dark/runner.png +0 -0
  545. psychopy/app/Resources/dark/runner@2x.png +0 -0
  546. psychopy/app/Resources/dark/runnerPilot.png +0 -0
  547. psychopy/app/Resources/dark/runnerPilot@2x.png +0 -0
  548. psychopy/app/Resources/dark/savebtn16.png +0 -0
  549. psychopy/app/Resources/dark/savebtn16@2x.png +0 -0
  550. psychopy/app/Resources/dark/search.png +0 -0
  551. psychopy/app/Resources/dark/search@2x.png +0 -0
  552. psychopy/app/Resources/dark/showBuilder.png +0 -0
  553. psychopy/app/Resources/dark/showBuilder@2x.png +0 -0
  554. psychopy/app/Resources/dark/showCoder.png +0 -0
  555. psychopy/app/Resources/dark/showCoder@2x.png +0 -0
  556. psychopy/app/Resources/dark/showRunner.png +0 -0
  557. psychopy/app/Resources/dark/showRunner@2x.png +0 -0
  558. psychopy/app/Resources/dark/starred.png +0 -0
  559. psychopy/app/Resources/dark/starred@2x.png +0 -0
  560. psychopy/app/Resources/dark/start.png +0 -0
  561. psychopy/app/Resources/dark/start@2x.png +0 -0
  562. psychopy/app/Resources/dark/stdout.png +0 -0
  563. psychopy/app/Resources/dark/stdout@2x.png +0 -0
  564. psychopy/app/Resources/dark/stop.png +0 -0
  565. psychopy/app/Resources/dark/stop32.png +0 -0
  566. psychopy/app/Resources/dark/stop32@2x.png +0 -0
  567. psychopy/app/Resources/dark/stop@2x.png +0 -0
  568. psychopy/app/Resources/dark/switchCtrlBot.png +0 -0
  569. psychopy/app/Resources/dark/switchCtrlBot@2x.png +0 -0
  570. psychopy/app/Resources/dark/switchCtrlLeft.png +0 -0
  571. psychopy/app/Resources/dark/switchCtrlLeft@2x.png +0 -0
  572. psychopy/app/Resources/dark/switchCtrlRight.png +0 -0
  573. psychopy/app/Resources/dark/switchCtrlRight@2x.png +0 -0
  574. psychopy/app/Resources/dark/switchCtrlTop.png +0 -0
  575. psychopy/app/Resources/dark/switchCtrlTop@2x.png +0 -0
  576. psychopy/app/Resources/dark/tick.png +0 -0
  577. psychopy/app/Resources/dark/tick@2x.png +0 -0
  578. psychopy/app/Resources/dark/undo.png +0 -0
  579. psychopy/app/Resources/dark/undo32.png +0 -0
  580. psychopy/app/Resources/dark/undo32@2x.png +0 -0
  581. psychopy/app/Resources/dark/undo@2x.png +0 -0
  582. psychopy/app/Resources/dark/unstarred.png +0 -0
  583. psychopy/app/Resources/dark/unstarred@2x.png +0 -0
  584. psychopy/app/Resources/dark/user_none.png +0 -0
  585. psychopy/app/Resources/dark/view-refresh16.png +0 -0
  586. psychopy/app/Resources/dark/view-refresh16@2x.png +0 -0
  587. psychopy/app/Resources/dark/viewbtn16.png +0 -0
  588. psychopy/app/Resources/dark/viewbtn16@2x.png +0 -0
  589. psychopy/app/Resources/dark/windows16.png +0 -0
  590. psychopy/app/Resources/dark/windows16@2x.png +0 -0
  591. psychopy/app/Resources/default.mp3 +0 -0
  592. psychopy/app/Resources/default.mp4 +0 -0
  593. psychopy/app/Resources/default.png +0 -0
  594. psychopy/app/Resources/fonts/Arvo-Bold.ttf +0 -0
  595. psychopy/app/Resources/fonts/Arvo-BoldItalic.ttf +0 -0
  596. psychopy/app/Resources/fonts/Arvo-Italic.ttf +0 -0
  597. psychopy/app/Resources/fonts/Arvo-Regular.ttf +0 -0
  598. psychopy/app/Resources/fonts/DejaVuSerif.ttf +0 -0
  599. psychopy/app/Resources/fonts/IndieFlower-Regular.ttf +0 -0
  600. psychopy/app/Resources/fonts/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  601. psychopy/app/Resources/fonts/JetBrainsMono-VariableFont_wght.ttf +0 -0
  602. psychopy/app/Resources/fonts/OpenSans-Bold.ttf +0 -0
  603. psychopy/app/Resources/fonts/OpenSans-BoldItalic.ttf +0 -0
  604. psychopy/app/Resources/fonts/OpenSans-ExtraBold.ttf +0 -0
  605. psychopy/app/Resources/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
  606. psychopy/app/Resources/fonts/OpenSans-Italic.ttf +0 -0
  607. psychopy/app/Resources/fonts/OpenSans-Light.ttf +0 -0
  608. psychopy/app/Resources/fonts/OpenSans-LightItalic.ttf +0 -0
  609. psychopy/app/Resources/fonts/OpenSans-Regular.ttf +0 -0
  610. psychopy/app/Resources/fonts/OpenSans-SemiBold.ttf +0 -0
  611. psychopy/app/Resources/fonts/OpenSans-SemiBoldItalic.ttf +0 -0
  612. psychopy/app/Resources/instruct1.png +0 -0
  613. psychopy/app/Resources/instruct2.png +0 -0
  614. psychopy/app/Resources/light/FlowBottom_CompLeft.png +0 -0
  615. psychopy/app/Resources/light/FlowBottom_CompRight.png +0 -0
  616. psychopy/app/Resources/light/FlowTop_CompLeft.png +0 -0
  617. psychopy/app/Resources/light/FlowTop_CompRight.png +0 -0
  618. psychopy/app/Resources/light/README.txt +3 -0
  619. psychopy/app/Resources/light/__init__.py +0 -0
  620. psychopy/app/Resources/light/add.png +0 -0
  621. psychopy/app/Resources/light/add@2x.png +0 -0
  622. psychopy/app/Resources/light/addExp32.png +0 -0
  623. psychopy/app/Resources/light/addExp32@2x.png +0 -0
  624. psychopy/app/Resources/light/alerts.png +0 -0
  625. psychopy/app/Resources/light/alerts@2x.png +0 -0
  626. psychopy/app/Resources/light/beta.png +0 -0
  627. psychopy/app/Resources/light/beta@2x.png +0 -0
  628. psychopy/app/Resources/light/browser.png +0 -0
  629. psychopy/app/Resources/light/browser@2x.png +0 -0
  630. psychopy/app/Resources/light/bug16.png +0 -0
  631. psychopy/app/Resources/light/bug16@2x.png +0 -0
  632. psychopy/app/Resources/light/circle_mask.png +0 -0
  633. psychopy/app/Resources/light/circle_mask@2x.png +0 -0
  634. psychopy/app/Resources/light/clear.png +0 -0
  635. psychopy/app/Resources/light/clear@2x.png +0 -0
  636. psychopy/app/Resources/light/coderclass16.png +0 -0
  637. psychopy/app/Resources/light/coderclass16@2x.png +0 -0
  638. psychopy/app/Resources/light/coderfunc16.png +0 -0
  639. psychopy/app/Resources/light/coderfunc16@2x.png +0 -0
  640. psychopy/app/Resources/light/coderimport16.png +0 -0
  641. psychopy/app/Resources/light/coderimport16@2x.png +0 -0
  642. psychopy/app/Resources/light/coderjs.png +0 -0
  643. psychopy/app/Resources/light/coderjs@2x.png +0 -0
  644. psychopy/app/Resources/light/coderpython.png +0 -0
  645. psychopy/app/Resources/light/coderpython@2x.png +0 -0
  646. psychopy/app/Resources/light/codervar16.png +0 -0
  647. psychopy/app/Resources/light/codervar16@2x.png +0 -0
  648. psychopy/app/Resources/light/cogwindow32.png +0 -0
  649. psychopy/app/Resources/light/cogwindow32@2x.png +0 -0
  650. psychopy/app/Resources/light/color16.png +0 -0
  651. psychopy/app/Resources/light/color16@2x.png +0 -0
  652. psychopy/app/Resources/light/color32.png +0 -0
  653. psychopy/app/Resources/light/color32@2x.png +0 -0
  654. psychopy/app/Resources/light/compile_js.png +0 -0
  655. psychopy/app/Resources/light/compile_js@2x.png +0 -0
  656. psychopy/app/Resources/light/compile_py.png +0 -0
  657. psychopy/app/Resources/light/compile_py@2x.png +0 -0
  658. psychopy/app/Resources/light/copy16.png +0 -0
  659. psychopy/app/Resources/light/copy16@2x.png +0 -0
  660. psychopy/app/Resources/light/currentFile16.png +0 -0
  661. psychopy/app/Resources/light/currentFile16@2x.png +0 -0
  662. psychopy/app/Resources/light/delete16.png +0 -0
  663. psychopy/app/Resources/light/delete16@2x.png +0 -0
  664. psychopy/app/Resources/light/delete8.png +0 -0
  665. psychopy/app/Resources/light/desktop.png +0 -0
  666. psychopy/app/Resources/light/desktop@2x.png +0 -0
  667. psychopy/app/Resources/light/dirup16.png +0 -0
  668. psychopy/app/Resources/light/dirup16@2x.png +0 -0
  669. psychopy/app/Resources/light/docclose16.png +0 -0
  670. psychopy/app/Resources/light/docclose16@2x.png +0 -0
  671. psychopy/app/Resources/light/download.png +0 -0
  672. psychopy/app/Resources/light/download@2x.png +0 -0
  673. psychopy/app/Resources/light/edit.png +0 -0
  674. psychopy/app/Resources/light/edit@2x.png +0 -0
  675. psychopy/app/Resources/light/editbtn16.png +0 -0
  676. psychopy/app/Resources/light/editbtn16@2x.png +0 -0
  677. psychopy/app/Resources/light/email.png +0 -0
  678. psychopy/app/Resources/light/email@2x.png +0 -0
  679. psychopy/app/Resources/light/experiment.png +0 -0
  680. psychopy/app/Resources/light/experiment@2x.png +0 -0
  681. psychopy/app/Resources/light/expsettings.png +0 -0
  682. psychopy/app/Resources/light/expsettings@2x.png +0 -0
  683. psychopy/app/Resources/light/file.png +0 -0
  684. psychopy/app/Resources/light/file@2x.png +0 -0
  685. psychopy/app/Resources/light/filecsv16.png +0 -0
  686. psychopy/app/Resources/light/filecsv16@2x.png +0 -0
  687. psychopy/app/Resources/light/fileimage16.png +0 -0
  688. psychopy/app/Resources/light/fileimage16@2x.png +0 -0
  689. psychopy/app/Resources/light/filenew.png +0 -0
  690. psychopy/app/Resources/light/filenew32.png +0 -0
  691. psychopy/app/Resources/light/filenew32@2x.png +0 -0
  692. psychopy/app/Resources/light/filenew@2x.png +0 -0
  693. psychopy/app/Resources/light/fileopen.png +0 -0
  694. psychopy/app/Resources/light/fileopen32.png +0 -0
  695. psychopy/app/Resources/light/fileopen32@2x.png +0 -0
  696. psychopy/app/Resources/light/fileopen@2x.png +0 -0
  697. psychopy/app/Resources/light/filesave.png +0 -0
  698. psychopy/app/Resources/light/filesave32.png +0 -0
  699. psychopy/app/Resources/light/filesave32@2x.png +0 -0
  700. psychopy/app/Resources/light/filesave@2x.png +0 -0
  701. psychopy/app/Resources/light/filesaveas.png +0 -0
  702. psychopy/app/Resources/light/filesaveas32.png +0 -0
  703. psychopy/app/Resources/light/filesaveas32@2x.png +0 -0
  704. psychopy/app/Resources/light/filesaveas@2x.png +0 -0
  705. psychopy/app/Resources/light/fileunknown16.png +0 -0
  706. psychopy/app/Resources/light/fileunknown16@2x.png +0 -0
  707. psychopy/app/Resources/light/filter.png +0 -0
  708. psychopy/app/Resources/light/filter@2x.png +0 -0
  709. psychopy/app/Resources/light/folder-open16.png +0 -0
  710. psychopy/app/Resources/light/folder-open16@2x.png +0 -0
  711. psychopy/app/Resources/light/folder16.png +0 -0
  712. psychopy/app/Resources/light/folder16@2x.png +0 -0
  713. psychopy/app/Resources/light/foldernew16.png +0 -0
  714. psychopy/app/Resources/light/foldernew16@2x.png +0 -0
  715. psychopy/app/Resources/light/fork.png +0 -0
  716. psychopy/app/Resources/light/fork@2x.png +0 -0
  717. psychopy/app/Resources/light/github.png +0 -0
  718. psychopy/app/Resources/light/github@2x.png +0 -0
  719. psychopy/app/Resources/light/globe.png +0 -0
  720. psychopy/app/Resources/light/globe@2x.png +0 -0
  721. psychopy/app/Resources/light/globe_bug.png +0 -0
  722. psychopy/app/Resources/light/globe_bug@2x.png +0 -0
  723. psychopy/app/Resources/light/globe_greensync.png +0 -0
  724. psychopy/app/Resources/light/globe_greensync@2x.png +0 -0
  725. psychopy/app/Resources/light/globe_info.png +0 -0
  726. psychopy/app/Resources/light/globe_info@2x.png +0 -0
  727. psychopy/app/Resources/light/globe_magnifier.png +0 -0
  728. psychopy/app/Resources/light/globe_magnifier@2x.png +0 -0
  729. psychopy/app/Resources/light/globe_run.png +0 -0
  730. psychopy/app/Resources/light/globe_run@2x.png +0 -0
  731. psychopy/app/Resources/light/globe_user.png +0 -0
  732. psychopy/app/Resources/light/globe_user@2x.png +0 -0
  733. psychopy/app/Resources/light/goto16.png +0 -0
  734. psychopy/app/Resources/light/goto16@2x.png +0 -0
  735. psychopy/app/Resources/light/greendot.png +0 -0
  736. psychopy/app/Resources/light/greendot@2x.png +0 -0
  737. psychopy/app/Resources/light/greenglobe.png +0 -0
  738. psychopy/app/Resources/light/greenglobe@2x.png +0 -0
  739. psychopy/app/Resources/light/greenglobe_bug.png +0 -0
  740. psychopy/app/Resources/light/greenglobe_bug@2x.png +0 -0
  741. psychopy/app/Resources/light/greenglobe_greensync.png +0 -0
  742. psychopy/app/Resources/light/greenglobe_greensync@2x.png +0 -0
  743. psychopy/app/Resources/light/greenglobe_info.png +0 -0
  744. psychopy/app/Resources/light/greenglobe_info@2x.png +0 -0
  745. psychopy/app/Resources/light/greenglobe_magnifier.png +0 -0
  746. psychopy/app/Resources/light/greenglobe_magnifier@2x.png +0 -0
  747. psychopy/app/Resources/light/greenglobe_run.png +0 -0
  748. psychopy/app/Resources/light/greenglobe_run@2x.png +0 -0
  749. psychopy/app/Resources/light/greenglobe_user.png +0 -0
  750. psychopy/app/Resources/light/greenglobe_user@2x.png +0 -0
  751. psychopy/app/Resources/light/greydot.png +0 -0
  752. psychopy/app/Resources/light/greydot@2x.png +0 -0
  753. psychopy/app/Resources/light/greytick.png +0 -0
  754. psychopy/app/Resources/light/greytick@2x.png +0 -0
  755. psychopy/app/Resources/light/invalid_img.png +0 -0
  756. psychopy/app/Resources/light/jsPilot.png +0 -0
  757. psychopy/app/Resources/light/jsPilot@2x.png +0 -0
  758. psychopy/app/Resources/light/jsRun.png +0 -0
  759. psychopy/app/Resources/light/jsRun@2x.png +0 -0
  760. psychopy/app/Resources/light/libroot16.png +0 -0
  761. psychopy/app/Resources/light/libroot16@2x.png +0 -0
  762. psychopy/app/Resources/light/monitor16.png +0 -0
  763. psychopy/app/Resources/light/monitor16@2x.png +0 -0
  764. psychopy/app/Resources/light/monitors.png +0 -0
  765. psychopy/app/Resources/light/monitors32.png +0 -0
  766. psychopy/app/Resources/light/monitors32@2x.png +0 -0
  767. psychopy/app/Resources/light/monitors@2x.png +0 -0
  768. psychopy/app/Resources/light/orangedot.png +0 -0
  769. psychopy/app/Resources/light/orangedot@2x.png +0 -0
  770. psychopy/app/Resources/light/pavlovia.png +0 -0
  771. psychopy/app/Resources/light/pavlovia16.png +0 -0
  772. psychopy/app/Resources/light/pavlovia16@2x.png +0 -0
  773. psychopy/app/Resources/light/pavlovia@2x.png +0 -0
  774. psychopy/app/Resources/light/pavsync.png +0 -0
  775. psychopy/app/Resources/light/pavsync@2x.png +0 -0
  776. psychopy/app/Resources/light/person_off.png +0 -0
  777. psychopy/app/Resources/light/person_off@2x.png +0 -0
  778. psychopy/app/Resources/light/person_on.png +0 -0
  779. psychopy/app/Resources/light/person_on@2x.png +0 -0
  780. psychopy/app/Resources/light/plugins32.png +0 -0
  781. psychopy/app/Resources/light/plugins32@2x.png +0 -0
  782. psychopy/app/Resources/light/plus.png +0 -0
  783. psychopy/app/Resources/light/plus@2x.png +0 -0
  784. psychopy/app/Resources/light/preferences-app.png +0 -0
  785. psychopy/app/Resources/light/preferences-app48.png +0 -0
  786. psychopy/app/Resources/light/preferences-app48@2x.png +0 -0
  787. psychopy/app/Resources/light/preferences-app@2x.png +0 -0
  788. psychopy/app/Resources/light/preferences-conn.png +0 -0
  789. psychopy/app/Resources/light/preferences-conn48.png +0 -0
  790. psychopy/app/Resources/light/preferences-conn48@2x.png +0 -0
  791. psychopy/app/Resources/light/preferences-conn@2x.png +0 -0
  792. psychopy/app/Resources/light/preferences-general.png +0 -0
  793. psychopy/app/Resources/light/preferences-general48.png +0 -0
  794. psychopy/app/Resources/light/preferences-general48@2x.png +0 -0
  795. psychopy/app/Resources/light/preferences-general@2x.png +0 -0
  796. psychopy/app/Resources/light/preferences-hardware.png +0 -0
  797. psychopy/app/Resources/light/preferences-hardware48.png +0 -0
  798. psychopy/app/Resources/light/preferences-hardware48@2x.png +0 -0
  799. psychopy/app/Resources/light/preferences-hardware@2x.png +0 -0
  800. psychopy/app/Resources/light/preferences-keyboard.png +0 -0
  801. psychopy/app/Resources/light/preferences-keyboard48.png +0 -0
  802. psychopy/app/Resources/light/preferences-keyboard48@2x.png +0 -0
  803. psychopy/app/Resources/light/preferences-keyboard@2x.png +0 -0
  804. psychopy/app/Resources/light/preferences-pilot.png +0 -0
  805. psychopy/app/Resources/light/preferences-pilot@2x.png +0 -0
  806. psychopy/app/Resources/light/preferences32.png +0 -0
  807. psychopy/app/Resources/light/preferences32@2x.png +0 -0
  808. psychopy/app/Resources/light/pyPilot.png +0 -0
  809. psychopy/app/Resources/light/pyPilot@2x.png +0 -0
  810. psychopy/app/Resources/light/pyRun.png +0 -0
  811. psychopy/app/Resources/light/pyRun@2x.png +0 -0
  812. psychopy/app/Resources/light/reddot.png +0 -0
  813. psychopy/app/Resources/light/reddot@2x.png +0 -0
  814. psychopy/app/Resources/light/redglobe.png +0 -0
  815. psychopy/app/Resources/light/redglobe@2x.png +0 -0
  816. psychopy/app/Resources/light/redglobe_bug.png +0 -0
  817. psychopy/app/Resources/light/redglobe_bug@2x.png +0 -0
  818. psychopy/app/Resources/light/redglobe_greensync.png +0 -0
  819. psychopy/app/Resources/light/redglobe_greensync@2x.png +0 -0
  820. psychopy/app/Resources/light/redglobe_info.png +0 -0
  821. psychopy/app/Resources/light/redglobe_info@2x.png +0 -0
  822. psychopy/app/Resources/light/redglobe_magnifier.png +0 -0
  823. psychopy/app/Resources/light/redglobe_magnifier@2x.png +0 -0
  824. psychopy/app/Resources/light/redglobe_run.png +0 -0
  825. psychopy/app/Resources/light/redglobe_run@2x.png +0 -0
  826. psychopy/app/Resources/light/redglobe_user.png +0 -0
  827. psychopy/app/Resources/light/redglobe_user@2x.png +0 -0
  828. psychopy/app/Resources/light/redo.png +0 -0
  829. psychopy/app/Resources/light/redo32.png +0 -0
  830. psychopy/app/Resources/light/redo32@2x.png +0 -0
  831. psychopy/app/Resources/light/redo@2x.png +0 -0
  832. psychopy/app/Resources/light/removeExp32.png +0 -0
  833. psychopy/app/Resources/light/removeExp32@2x.png +0 -0
  834. psychopy/app/Resources/light/rename16.png +0 -0
  835. psychopy/app/Resources/light/rename16@2x.png +0 -0
  836. psychopy/app/Resources/light/restart.png +0 -0
  837. psychopy/app/Resources/light/restart@2x.png +0 -0
  838. psychopy/app/Resources/light/runner.png +0 -0
  839. psychopy/app/Resources/light/runner@2x.png +0 -0
  840. psychopy/app/Resources/light/runnerPilot.png +0 -0
  841. psychopy/app/Resources/light/runnerPilot@2x.png +0 -0
  842. psychopy/app/Resources/light/savebtn16.png +0 -0
  843. psychopy/app/Resources/light/savebtn16@2x.png +0 -0
  844. psychopy/app/Resources/light/search.png +0 -0
  845. psychopy/app/Resources/light/search@2x.png +0 -0
  846. psychopy/app/Resources/light/showBuilder.png +0 -0
  847. psychopy/app/Resources/light/showBuilder@2x.png +0 -0
  848. psychopy/app/Resources/light/showCoder.png +0 -0
  849. psychopy/app/Resources/light/showCoder@2x.png +0 -0
  850. psychopy/app/Resources/light/showRunner.png +0 -0
  851. psychopy/app/Resources/light/showRunner@2x.png +0 -0
  852. psychopy/app/Resources/light/starred.png +0 -0
  853. psychopy/app/Resources/light/starred@2x.png +0 -0
  854. psychopy/app/Resources/light/start.png +0 -0
  855. psychopy/app/Resources/light/start@2x.png +0 -0
  856. psychopy/app/Resources/light/stdout.png +0 -0
  857. psychopy/app/Resources/light/stdout@2x.png +0 -0
  858. psychopy/app/Resources/light/stop.png +0 -0
  859. psychopy/app/Resources/light/stop32.png +0 -0
  860. psychopy/app/Resources/light/stop32@2x.png +0 -0
  861. psychopy/app/Resources/light/stop@2x.png +0 -0
  862. psychopy/app/Resources/light/switchCtrlBot.png +0 -0
  863. psychopy/app/Resources/light/switchCtrlBot@2x.png +0 -0
  864. psychopy/app/Resources/light/switchCtrlLeft.png +0 -0
  865. psychopy/app/Resources/light/switchCtrlLeft@2x.png +0 -0
  866. psychopy/app/Resources/light/switchCtrlRight.png +0 -0
  867. psychopy/app/Resources/light/switchCtrlRight@2x.png +0 -0
  868. psychopy/app/Resources/light/switchCtrlTop.png +0 -0
  869. psychopy/app/Resources/light/switchCtrlTop@2x.png +0 -0
  870. psychopy/app/Resources/light/tick.png +0 -0
  871. psychopy/app/Resources/light/tick@2x.png +0 -0
  872. psychopy/app/Resources/light/undo.png +0 -0
  873. psychopy/app/Resources/light/undo32.png +0 -0
  874. psychopy/app/Resources/light/undo32@2x.png +0 -0
  875. psychopy/app/Resources/light/undo@2x.png +0 -0
  876. psychopy/app/Resources/light/unstarred.png +0 -0
  877. psychopy/app/Resources/light/unstarred@2x.png +0 -0
  878. psychopy/app/Resources/light/user_none.png +0 -0
  879. psychopy/app/Resources/light/view-refresh16.png +0 -0
  880. psychopy/app/Resources/light/view-refresh16@2x.png +0 -0
  881. psychopy/app/Resources/light/viewbtn16.png +0 -0
  882. psychopy/app/Resources/light/viewbtn16@2x.png +0 -0
  883. psychopy/app/Resources/light/windows16.png +0 -0
  884. psychopy/app/Resources/light/windows16@2x.png +0 -0
  885. psychopy/app/Resources/moveComponentIcons.py +50 -0
  886. psychopy/app/Resources/next.png +0 -0
  887. psychopy/app/Resources/psychopy.desktop +13 -0
  888. psychopy/app/Resources/psychopy.icns +0 -0
  889. psychopy/app/Resources/psychopy.ico +0 -0
  890. psychopy/app/Resources/psychopy.png +0 -0
  891. psychopy/app/Resources/psychopy.xml +9 -0
  892. psychopy/app/Resources/psychopy@2x.png +0 -0
  893. psychopy/app/Resources/psychopySplash.png +0 -0
  894. psychopy/app/Resources/psychopySplash@2x.png +0 -0
  895. psychopy/app/Resources/routine_templates/Basic.psyexp +345 -0
  896. psychopy/app/Resources/routine_templates/Misc.psyexp +229 -0
  897. psychopy/app/Resources/routine_templates/Online.psyexp +202 -0
  898. psychopy/app/Resources/routine_templates/Trials.psyexp +736 -0
  899. psychopy/app/Resources/routine_templates/readme.md +14 -0
  900. psychopy/app/Resources/runner.ico +0 -0
  901. psychopy/app/Resources/tips.txt +45 -0
  902. psychopy/app/Resources/tips_ar_001.txt +45 -0
  903. psychopy/app/Resources/tips_fr_FR.txt +45 -0
  904. psychopy/app/Resources/tips_ja_JP.txt +42 -0
  905. psychopy/app/Resources/tips_zh_CN.txt +45 -0
  906. psychopy/app/Resources/window.ico +0 -0
  907. psychopy/app/__init__.py +224 -0
  908. psychopy/app/_psychopyApp.py +1224 -0
  909. psychopy/app/appData.spec +58 -0
  910. psychopy/app/builder/__init__.py +5 -0
  911. psychopy/app/builder/builder.py +4658 -0
  912. psychopy/app/builder/dialogs/__init__.py +2014 -0
  913. psychopy/app/builder/dialogs/dlgsCode.py +610 -0
  914. psychopy/app/builder/dialogs/dlgsConditions.py +670 -0
  915. psychopy/app/builder/dialogs/findDlg.py +189 -0
  916. psychopy/app/builder/dialogs/paramCtrls.py +1213 -0
  917. psychopy/app/builder/localizedStrings.py +225 -0
  918. psychopy/app/builder/validators.py +581 -0
  919. psychopy/app/coder/__init__.py +8 -0
  920. psychopy/app/coder/codeEditorBase.py +460 -0
  921. psychopy/app/coder/coder.py +3086 -0
  922. psychopy/app/coder/fileBrowser.py +668 -0
  923. psychopy/app/coder/folding.py +128 -0
  924. psychopy/app/coder/psychoParser.py +139 -0
  925. psychopy/app/coder/repl.py +493 -0
  926. psychopy/app/coder/sourceTree.py +302 -0
  927. psychopy/app/colorpicker/__init__.py +594 -0
  928. psychopy/app/colorpicker/ui.py +336 -0
  929. psychopy/app/connections/__init__.py +10 -0
  930. psychopy/app/connections/news.py +104 -0
  931. psychopy/app/connections/sendusage.py +61 -0
  932. psychopy/app/connections/updates.py +642 -0
  933. psychopy/app/console.py +164 -0
  934. psychopy/app/dialogs.py +632 -0
  935. psychopy/app/errorDlg.py +238 -0
  936. psychopy/app/frametracker.py +8 -0
  937. psychopy/app/idle.py +143 -0
  938. psychopy/app/jobs.py +648 -0
  939. psychopy/app/linuxconfig/__init__.py +144 -0
  940. psychopy/app/linuxconfig/ui.py +88 -0
  941. psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
  942. psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +9554 -0
  943. psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
  944. psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.po +24 -0
  945. psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
  946. psychopy/app/locale/da_DK/LC_MESSAGE/messages.po +24 -0
  947. psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
  948. psychopy/app/locale/de_DE/LC_MESSAGE/messages.po +9712 -0
  949. psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
  950. psychopy/app/locale/el_GR/LC_MESSAGE/messages.po +25 -0
  951. psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
  952. psychopy/app/locale/en_NZ/LC_MESSAGE/messages.po +25 -0
  953. psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
  954. psychopy/app/locale/en_US/LC_MESSAGE/messages.po +18 -0
  955. psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
  956. psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +9100 -0
  957. psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
  958. psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +9094 -0
  959. psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
  960. psychopy/app/locale/es_US/LC_MESSAGE/messages.po +9100 -0
  961. psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
  962. psychopy/app/locale/et_EE/LC_MESSAGE/messages.po +9569 -0
  963. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
  964. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.po +5806 -0
  965. psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
  966. psychopy/app/locale/fi_FI/LC_MESSAGE/messages.po +24 -0
  967. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
  968. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.po +9577 -0
  969. psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
  970. psychopy/app/locale/he_IL/LC_MESSAGE/messages.po +9549 -0
  971. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
  972. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.po +9559 -0
  973. psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
  974. psychopy/app/locale/hu_HU/LC_MESSAGE/messages.po +25 -0
  975. psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
  976. psychopy/app/locale/it_IT/LC_MESSAGE/messages.po +9560 -0
  977. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
  978. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +11687 -0
  979. psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
  980. psychopy/app/locale/ko_KR/LC_MESSAGE/messages.po +24 -0
  981. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
  982. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.po +8757 -0
  983. psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
  984. psychopy/app/locale/nl_NL/LC_MESSAGE/messages.po +25 -0
  985. psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
  986. psychopy/app/locale/nn_NO/LC_MESSAGE/messages.po +25 -0
  987. psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
  988. psychopy/app/locale/pl_PL/LC_MESSAGE/messages.po +25 -0
  989. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
  990. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +24 -0
  991. psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
  992. psychopy/app/locale/ro_RO/LC_MESSAGE/messages.po +25 -0
  993. psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
  994. psychopy/app/locale/ru_RU/LC_MESSAGE/messages.po +24 -0
  995. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
  996. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.po +8747 -0
  997. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
  998. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.po +9545 -0
  999. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
  1000. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.po +8268 -0
  1001. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
  1002. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.po +8022 -0
  1003. psychopy/app/pavlovia_ui/__init__.py +22 -0
  1004. psychopy/app/pavlovia_ui/_base.py +237 -0
  1005. psychopy/app/pavlovia_ui/functions.py +176 -0
  1006. psychopy/app/pavlovia_ui/menu.py +140 -0
  1007. psychopy/app/pavlovia_ui/project.py +943 -0
  1008. psychopy/app/pavlovia_ui/search.py +445 -0
  1009. psychopy/app/pavlovia_ui/sync.py +137 -0
  1010. psychopy/app/pavlovia_ui/user.py +264 -0
  1011. psychopy/app/plugin_manager/__init__.py +5 -0
  1012. psychopy/app/plugin_manager/dialog.py +400 -0
  1013. psychopy/app/plugin_manager/output.py +132 -0
  1014. psychopy/app/plugin_manager/packages.py +502 -0
  1015. psychopy/app/plugin_manager/plugins.py +1315 -0
  1016. psychopy/app/plugin_manager/utils.py +115 -0
  1017. psychopy/app/preferencesDlg.py +790 -0
  1018. psychopy/app/psychopyApp.py +103 -0
  1019. psychopy/app/ribbon.py +907 -0
  1020. psychopy/app/runner/__init__.py +1 -0
  1021. psychopy/app/runner/runner.py +1262 -0
  1022. psychopy/app/runner/scriptProcess.py +353 -0
  1023. psychopy/app/stdout/__init__.py +1 -0
  1024. psychopy/app/stdout/stdOutRich.py +380 -0
  1025. psychopy/app/sysInfoDlg.py +242 -0
  1026. psychopy/app/themes/__init__.py +78 -0
  1027. psychopy/app/themes/colors.py +201 -0
  1028. psychopy/app/themes/css/contrast_black.css +112 -0
  1029. psychopy/app/themes/css/contrast_white.css +115 -0
  1030. psychopy/app/themes/css/dark.css +112 -0
  1031. psychopy/app/themes/css/light.css +115 -0
  1032. psychopy/app/themes/fonts.py +629 -0
  1033. psychopy/app/themes/handlers.py +321 -0
  1034. psychopy/app/themes/icons.py +250 -0
  1035. psychopy/app/themes/spec/Classic.json +154 -0
  1036. psychopy/app/themes/spec/ClassicDark.json +154 -0
  1037. psychopy/app/themes/spec/GitHub.json +154 -0
  1038. psychopy/app/themes/spec/HiVisDark.json +153 -0
  1039. psychopy/app/themes/spec/HiVisLight.json +154 -0
  1040. psychopy/app/themes/spec/MinimalDark.json +154 -0
  1041. psychopy/app/themes/spec/MinimalLight.json +153 -0
  1042. psychopy/app/themes/spec/PsychopyDark.json +231 -0
  1043. psychopy/app/themes/spec/PsychopyLight.json +236 -0
  1044. psychopy/app/themes/ui.py +74 -0
  1045. psychopy/app/ui/__init__.py +184 -0
  1046. psychopy/app/urls.py +31 -0
  1047. psychopy/app/utils.py +1680 -0
  1048. psychopy/app/viewer/__init__.py +0 -0
  1049. psychopy/clock.py +612 -0
  1050. psychopy/colors.py +1050 -0
  1051. psychopy/compatibility.py +95 -0
  1052. psychopy/constants.py +87 -0
  1053. psychopy/contrib/__init__.py +0 -0
  1054. psychopy/contrib/configobj/LICENSE +39 -0
  1055. psychopy/contrib/configobj/__init__.py +2453 -0
  1056. psychopy/contrib/configobj/_version.py +2 -0
  1057. psychopy/contrib/configobj/validate.py +1458 -0
  1058. psychopy/contrib/lazy_import.py +402 -0
  1059. psychopy/contrib/mseq.py +273 -0
  1060. psychopy/contrib/mseqSearch.py +183 -0
  1061. psychopy/contrib/psi.py +100 -0
  1062. psychopy/contrib/quest.py +484 -0
  1063. psychopy/contrib/tesselate.py +188 -0
  1064. psychopy/core.py +167 -0
  1065. psychopy/data/__init__.py +44 -0
  1066. psychopy/data/base.py +566 -0
  1067. psychopy/data/counterbalance.py +210 -0
  1068. psychopy/data/experiment.py +708 -0
  1069. psychopy/data/fit.py +248 -0
  1070. psychopy/data/shelf.py +237 -0
  1071. psychopy/data/staircase.py +2247 -0
  1072. psychopy/data/trial.py +1978 -0
  1073. psychopy/data/utils.py +783 -0
  1074. psychopy/demos/__init__.py +0 -0
  1075. psychopy/demos/builder/Design Templates/branchedExperiment/README.md +5 -0
  1076. psychopy/demos/builder/Design Templates/branchedExperiment/branchedExperiment.psyexp +239 -0
  1077. psychopy/demos/builder/Design Templates/branchedExperiment/trialTypes.xlsx +0 -0
  1078. psychopy/demos/builder/Design Templates/psychophysicsStaircase/README.md +20 -0
  1079. psychopy/demos/builder/Design Templates/psychophysicsStaircase/psychophysicsStaircase.psyexp +264 -0
  1080. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/README.md +14 -0
  1081. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/psychophysicsStaircaseInterleaved.psyexp +201 -0
  1082. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/stairDefinitions.xlsx +0 -0
  1083. psychopy/demos/builder/Design Templates/randomisedBlocks/README.md +18 -0
  1084. psychopy/demos/builder/Design Templates/randomisedBlocks/chooseBlock.xlsx +0 -0
  1085. psychopy/demos/builder/Design Templates/randomisedBlocks/facesBlock.xlsx +0 -0
  1086. psychopy/demos/builder/Design Templates/randomisedBlocks/housesBlock.xlsx +0 -0
  1087. psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks.psyexp +131 -0
  1088. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/face01.jpg +0 -0
  1089. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/face02.jpg +0 -0
  1090. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/face03.jpg +0 -0
  1091. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/house01.jpg +0 -0
  1092. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/house02.jpg +0 -0
  1093. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/house03.jpg +0 -0
  1094. psychopy/demos/builder/Experiments/BART/README.md +30 -0
  1095. psychopy/demos/builder/Experiments/BART/assets/background.png +0 -0
  1096. psychopy/demos/builder/Experiments/BART/assets/bang.mp3 +0 -0
  1097. psychopy/demos/builder/Experiments/BART/assets/bang.wav +0 -0
  1098. psychopy/demos/builder/Experiments/BART/assets/blueBalloon.png +0 -0
  1099. psychopy/demos/builder/Experiments/BART/assets/greenBalloon.png +0 -0
  1100. psychopy/demos/builder/Experiments/BART/assets/redBalloon.png +0 -0
  1101. psychopy/demos/builder/Experiments/BART/bart.psyexp +931 -0
  1102. psychopy/demos/builder/Experiments/BART/spreadsheets/conditions.xlsx +0 -0
  1103. psychopy/demos/builder/Experiments/BigFiveInventory/BFI.psyexp +193 -0
  1104. psychopy/demos/builder/Experiments/BigFiveInventory/README.md +23 -0
  1105. psychopy/demos/builder/Experiments/BigFiveInventory/TIPI.xlsx +0 -0
  1106. psychopy/demos/builder/Experiments/BigFiveInventory/bigFiveItems.xlsx +0 -0
  1107. psychopy/demos/builder/Experiments/BigFiveInventory/demographics.xlsx +0 -0
  1108. psychopy/demos/builder/Experiments/BigFiveInventory/mini_IPIP.xlsx +0 -0
  1109. psychopy/demos/builder/Experiments/dragAndDrop/README.md +40 -0
  1110. psychopy/demos/builder/Experiments/dragAndDrop/archived_conditions.xlsx +0 -0
  1111. psychopy/demos/builder/Experiments/dragAndDrop/drag_and_drop.psyexp +1221 -0
  1112. psychopy/demos/builder/Experiments/dragAndDrop/draw grid stim.py +61 -0
  1113. psychopy/demos/builder/Experiments/dragAndDrop/shapeMaker.psyexp +91 -0
  1114. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_1.png +0 -0
  1115. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_10.png +0 -0
  1116. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_2.png +0 -0
  1117. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_3.png +0 -0
  1118. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_4.png +0 -0
  1119. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_5.png +0 -0
  1120. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_6.png +0 -0
  1121. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_7.png +0 -0
  1122. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_8.png +0 -0
  1123. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_9.png +0 -0
  1124. psychopy/demos/builder/Experiments/dragAndDrop/updated_conditions.xlsx +0 -0
  1125. psychopy/demos/builder/Experiments/goNoGo/conditions.xlsx +0 -0
  1126. psychopy/demos/builder/Experiments/goNoGo/gng.psyexp +449 -0
  1127. psychopy/demos/builder/Experiments/goNoGo/go.png +0 -0
  1128. psychopy/demos/builder/Experiments/goNoGo/nogo.png +0 -0
  1129. psychopy/demos/builder/Experiments/goNoGo/readme.md +14 -0
  1130. psychopy/demos/builder/Experiments/mentalRotation/F.png +0 -0
  1131. psychopy/demos/builder/Experiments/mentalRotation/FR.png +0 -0
  1132. psychopy/demos/builder/Experiments/mentalRotation/MentalRot.csv +33 -0
  1133. psychopy/demos/builder/Experiments/mentalRotation/MentalRotation.psyexp +605 -0
  1134. psychopy/demos/builder/Experiments/mentalRotation/README.md +23 -0
  1135. psychopy/demos/builder/Experiments/navon/NavonTask.psyexp +478 -0
  1136. psychopy/demos/builder/Experiments/navon/README.md +26 -0
  1137. psychopy/demos/builder/Experiments/navon/bigHsmallH.png +0 -0
  1138. psychopy/demos/builder/Experiments/navon/bigHsmallS.png +0 -0
  1139. psychopy/demos/builder/Experiments/navon/bigSsmallH.png +0 -0
  1140. psychopy/demos/builder/Experiments/navon/bigSsmallS.png +0 -0
  1141. psychopy/demos/builder/Experiments/navon/mask.png +0 -0
  1142. psychopy/demos/builder/Experiments/navon/stimuli.pptx +0 -0
  1143. psychopy/demos/builder/Experiments/navon/trialTypes.xlsx +0 -0
  1144. psychopy/demos/builder/Experiments/sternberg/README.md +14 -0
  1145. psychopy/demos/builder/Experiments/sternberg/mainTrials.xlsx +0 -0
  1146. psychopy/demos/builder/Experiments/sternberg/pracTrials.xlsx +0 -0
  1147. psychopy/demos/builder/Experiments/sternberg/sternberg.psyexp +611 -0
  1148. psychopy/demos/builder/Experiments/stroop/README.md +15 -0
  1149. psychopy/demos/builder/Experiments/stroop/stroop.psyexp +225 -0
  1150. psychopy/demos/builder/Experiments/stroop/trialTypes.csv +7 -0
  1151. psychopy/demos/builder/Experiments/stroopExtended/README.md +14 -0
  1152. psychopy/demos/builder/Experiments/stroopExtended/stroop.psyexp +243 -0
  1153. psychopy/demos/builder/Experiments/stroopExtended/stroopReverse.psyexp +243 -0
  1154. psychopy/demos/builder/Experiments/stroopExtended/trialTypes.xlsx +0 -0
  1155. psychopy/demos/builder/Experiments/stroopExtended/trialTypesReverse.xlsx +0 -0
  1156. psychopy/demos/builder/Experiments/stroopVoice/README.md +27 -0
  1157. psychopy/demos/builder/Experiments/stroopVoice/conditions.xlsx +0 -0
  1158. psychopy/demos/builder/Experiments/stroopVoice/stroopVoice.psyexp +366 -0
  1159. psychopy/demos/builder/Feature Demos/counterbalance/counterbalance.psyexp +298 -0
  1160. psychopy/demos/builder/Feature Demos/gratings/gratings.psyexp +341 -0
  1161. psychopy/demos/builder/Feature Demos/gratings/readme.md +8 -0
  1162. psychopy/demos/builder/Feature Demos/noise/face.jpg +0 -0
  1163. psychopy/demos/builder/Feature Demos/noise/noise.psyexp +424 -0
  1164. psychopy/demos/builder/Feature Demos/noise/readme.md +3 -0
  1165. psychopy/demos/builder/Feature Demos/panorama/panImg.jpg +0 -0
  1166. psychopy/demos/builder/Feature Demos/panorama/panorama.psyexp +142 -0
  1167. psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp +423 -0
  1168. psychopy/demos/builder/Feature Demos/progress/readme.md +1 -0
  1169. psychopy/demos/builder/Feature Demos/sliders/README.md +8 -0
  1170. psychopy/demos/builder/Feature Demos/sliders/fruitConditions.xlsx +0 -0
  1171. psychopy/demos/builder/Feature Demos/sliders/sliders.psyexp +938 -0
  1172. psychopy/demos/builder/Hardware/EEG_parallel_component/EEG_triggers_parallel_comp.psyexp +621 -0
  1173. psychopy/demos/builder/Hardware/EEG_serial_code/EEG_triggers_serial_code.psyexp +404 -0
  1174. psychopy/demos/builder/Hardware/EEG_serial_component/EEG_triggers_serial_comp.psyexp +641 -0
  1175. psychopy/demos/builder/Hardware/EGI_netstation/README.md +17 -0
  1176. psychopy/demos/builder/Hardware/EGI_netstation/stroop.psyexp +254 -0
  1177. psychopy/demos/builder/Hardware/EGI_netstation/trialTypesEEG.csv +7 -0
  1178. psychopy/demos/builder/Hardware/Eyetracking_visual_search/readme.md +19 -0
  1179. psychopy/demos/builder/Hardware/Eyetracking_visual_search/trials_params.xlsx +0 -0
  1180. psychopy/demos/builder/Hardware/Eyetracking_visual_search/visualSearch.psyexp +691 -0
  1181. psychopy/demos/builder/Hardware/camera/camera.psyexp +263 -0
  1182. psychopy/demos/builder/Hardware/camera/readme.md +6 -0
  1183. psychopy/demos/builder/Hardware/eyetracking/eyetracking.psyexp +354 -0
  1184. psychopy/demos/builder/Hardware/eyetracking/readme.md +7 -0
  1185. psychopy/demos/builder/Hardware/eyetracking_custom_cal/Bullseye_grey.mov +0 -0
  1186. psychopy/demos/builder/Hardware/eyetracking_custom_cal/eyetracking_custom_cal.psyexp +349 -0
  1187. psychopy/demos/builder/Hardware/eyetracking_custom_cal/readme.md +7 -0
  1188. psychopy/demos/builder/Hardware/fMRI/fMRI_demo.psyexp +202 -0
  1189. psychopy/demos/builder/Hardware/fMRI/readme.md +7 -0
  1190. psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo.psyexp +349 -0
  1191. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy.psyexp +304 -0
  1192. psychopy/demos/builder/Hardware/microphone/microphone.psyexp +451 -0
  1193. psychopy/demos/builder/Hardware/microphone/phrases.xlsx +0 -0
  1194. psychopy/demos/builder/Hardware/microphone/readme.md +9 -0
  1195. psychopy/demos/builder/Hardware/pump/README.md +19 -0
  1196. psychopy/demos/builder/Hardware/pump/pump.psyexp +382 -0
  1197. psychopy/demos/builder/Helper Tools/achorVSalignment/anchorAlignment.psyexp +288 -0
  1198. psychopy/demos/builder/Helper Tools/achorVSalignment/readme.md +5 -0
  1199. psychopy/demos/builder/Helper Tools/clockFace/README.md +3 -0
  1200. psychopy/demos/builder/Helper Tools/clockFace/clockFace.psyexp +160 -0
  1201. psychopy/demos/builder/Helper Tools/colors/README.md +5 -0
  1202. psychopy/demos/builder/Helper Tools/colors/colors.psyexp +300 -0
  1203. psychopy/demos/builder/Helper Tools/drawPolygon/README.md +5 -0
  1204. psychopy/demos/builder/Helper Tools/drawPolygon/drawPolygon.psyexp +591 -0
  1205. psychopy/demos/builder/Helper Tools/keyNameFinder/README.md +14 -0
  1206. psychopy/demos/builder/Helper Tools/keyNameFinder/keyNameFinder.psyexp +169 -0
  1207. psychopy/demos/builder/Helper Tools/spatialUnits/README.md +6 -0
  1208. psychopy/demos/builder/Helper Tools/spatialUnits/unitDemo.psyexp +157 -0
  1209. psychopy/demos/builder/README.txt +43 -0
  1210. psychopy/demos/builder/__init__.py +0 -0
  1211. psychopy/demos/coder/__init__.py +0 -0
  1212. psychopy/demos/coder/basic/hello_world.py +37 -0
  1213. psychopy/demos/coder/csvFromPsydat.py +29 -0
  1214. psychopy/demos/coder/experiment control/JND_staircase_analysis.py +85 -0
  1215. psychopy/demos/coder/experiment control/JND_staircase_exp.py +110 -0
  1216. psychopy/demos/coder/experiment control/TrialHandler.py +64 -0
  1217. psychopy/demos/coder/experiment control/TrialHandler2.py +42 -0
  1218. psychopy/demos/coder/experiment control/__init__.py +0 -0
  1219. psychopy/demos/coder/experiment control/autoDraw_autoLog.py +50 -0
  1220. psychopy/demos/coder/experiment control/experimentHandler.py +57 -0
  1221. psychopy/demos/coder/experiment control/fMRI_launchScan.py +74 -0
  1222. psychopy/demos/coder/experiment control/gammaMotionAnalysis.py +68 -0
  1223. psychopy/demos/coder/experiment control/gammaMotionNull.py +169 -0
  1224. psychopy/demos/coder/experiment control/logFiles.py +55 -0
  1225. psychopy/demos/coder/experiment control/piloting.py +65 -0
  1226. psychopy/demos/coder/experiment control/runtimeInfo.py +79 -0
  1227. psychopy/demos/coder/hardware/CRS_BitsBox.py +75 -0
  1228. psychopy/demos/coder/hardware/CRS_BitsPlusPlus.py +73 -0
  1229. psychopy/demos/coder/hardware/RiftHeadTrackingExample.py +95 -0
  1230. psychopy/demos/coder/hardware/RiftMinimal.py +44 -0
  1231. psychopy/demos/coder/hardware/VSHD_Distortion.py +49 -0
  1232. psychopy/demos/coder/hardware/__init__.py +0 -0
  1233. psychopy/demos/coder/hardware/camera.py +90 -0
  1234. psychopy/demos/coder/hardware/cedrusRB730.py +38 -0
  1235. psychopy/demos/coder/hardware/crsBitsAdvancedDemo.py +780 -0
  1236. psychopy/demos/coder/hardware/egi_netstation.py +45 -0
  1237. psychopy/demos/coder/hardware/ioLab_bbox.py +62 -0
  1238. psychopy/demos/coder/hardware/labjack_u3.py +61 -0
  1239. psychopy/demos/coder/hardware/monitorDemo.py +28 -0
  1240. psychopy/demos/coder/hardware/parallelPortOutput.py +49 -0
  1241. psychopy/demos/coder/hardware/qmixPump.py +79 -0
  1242. psychopy/demos/coder/hardware/testSoundLatency.py +127 -0
  1243. psychopy/demos/coder/input/GUI.py +52 -0
  1244. psychopy/demos/coder/input/__init__.py +0 -0
  1245. psychopy/demos/coder/input/customMouse.py +51 -0
  1246. psychopy/demos/coder/input/joystick_universal.py +84 -0
  1247. psychopy/demos/coder/input/keyNameFinder.py +39 -0
  1248. psychopy/demos/coder/input/mic.png +0 -0
  1249. psychopy/demos/coder/input/mouse.py +66 -0
  1250. psychopy/demos/coder/iohub/delaytest.py +231 -0
  1251. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/canal.jpg +0 -0
  1252. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/fall.jpg +0 -0
  1253. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/lake.jpg +0 -0
  1254. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/party.jpg +0 -0
  1255. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/swimming.jpg +0 -0
  1256. psychopy/demos/coder/iohub/eyetracking/gcCursor/readTrialEventsByConditionVariables.py +67 -0
  1257. psychopy/demos/coder/iohub/eyetracking/gcCursor/readTrialEventsByMessages.py +34 -0
  1258. psychopy/demos/coder/iohub/eyetracking/gcCursor/run.py +323 -0
  1259. psychopy/demos/coder/iohub/eyetracking/gcCursor/trial_conditions.xlsx +0 -0
  1260. psychopy/demos/coder/iohub/eyetracking/simple.py +147 -0
  1261. psychopy/demos/coder/iohub/eyetracking/validation.py +251 -0
  1262. psychopy/demos/coder/iohub/iodatastore/saveEventReport.py +56 -0
  1263. psychopy/demos/coder/iohub/keyboard.py +189 -0
  1264. psychopy/demos/coder/iohub/keyboardreactiontime.py +88 -0
  1265. psychopy/demos/coder/iohub/launchHub.py +160 -0
  1266. psychopy/demos/coder/iohub/mouse.py +112 -0
  1267. psychopy/demos/coder/iohub/mouse_multi_window.py +124 -0
  1268. psychopy/demos/coder/iohub/serial/_parseserial.py +53 -0
  1269. psychopy/demos/coder/iohub/serial/customparser.py +84 -0
  1270. psychopy/demos/coder/iohub/serial/pstbox.py +166 -0
  1271. psychopy/demos/coder/iohub/wintab/_wintabgraphics.py +281 -0
  1272. psychopy/demos/coder/iohub/wintab/pen_demo.py +260 -0
  1273. psychopy/demos/coder/misc/encrypt_data.py +48 -0
  1274. psychopy/demos/coder/misc/makeMovie.py +28 -0
  1275. psychopy/demos/coder/misc/rigidBodyTransform.py +76 -0
  1276. psychopy/demos/coder/stimuli/Campaign.ttf +0 -0
  1277. psychopy/demos/coder/stimuli/MovieStim.py +65 -0
  1278. psychopy/demos/coder/stimuli/__init__.py +0 -0
  1279. psychopy/demos/coder/stimuli/aperture.py +37 -0
  1280. psychopy/demos/coder/stimuli/beach.jpg +0 -0
  1281. psychopy/demos/coder/stimuli/bufferImageStim.py +78 -0
  1282. psychopy/demos/coder/stimuli/clockface.py +43 -0
  1283. psychopy/demos/coder/stimuli/colorPalette.py +134 -0
  1284. psychopy/demos/coder/stimuli/compare_text_timing.py +193 -0
  1285. psychopy/demos/coder/stimuli/counterphase.py +43 -0
  1286. psychopy/demos/coder/stimuli/customTextures.py +57 -0
  1287. psychopy/demos/coder/stimuli/dot_gabors.py +35 -0
  1288. psychopy/demos/coder/stimuli/dots.py +35 -0
  1289. psychopy/demos/coder/stimuli/elementArrays.py +92 -0
  1290. psychopy/demos/coder/stimuli/embeddedOpenGL.py +35 -0
  1291. psychopy/demos/coder/stimuli/face.jpg +0 -0
  1292. psychopy/demos/coder/stimuli/face_jpg.py +48 -0
  1293. psychopy/demos/coder/stimuli/gabor.py +30 -0
  1294. psychopy/demos/coder/stimuli/imagesAndPatches.py +51 -0
  1295. psychopy/demos/coder/stimuli/jwpIntro.mp4 +0 -0
  1296. psychopy/demos/coder/stimuli/kanizsa.py +41 -0
  1297. psychopy/demos/coder/stimuli/maskReveal.py +63 -0
  1298. psychopy/demos/coder/stimuli/plaid.py +43 -0
  1299. psychopy/demos/coder/stimuli/ratingScale.py +183 -0
  1300. psychopy/demos/coder/stimuli/rotatingFlashingWedge.py +37 -0
  1301. psychopy/demos/coder/stimuli/screensAndWindows.py +58 -0
  1302. psychopy/demos/coder/stimuli/secondOrderGratings.py +66 -0
  1303. psychopy/demos/coder/stimuli/shapeContains.py +50 -0
  1304. psychopy/demos/coder/stimuli/shapes.py +63 -0
  1305. psychopy/demos/coder/stimuli/soundStimuli.py +49 -0
  1306. psychopy/demos/coder/stimuli/starField.py +48 -0
  1307. psychopy/demos/coder/stimuli/stim3d.py +107 -0
  1308. psychopy/demos/coder/stimuli/textBoxStim/textbox_glyph_placement.py +93 -0
  1309. psychopy/demos/coder/stimuli/textBoxStim/textbox_simple.py +71 -0
  1310. psychopy/demos/coder/stimuli/textStimuli.py +106 -0
  1311. psychopy/demos/coder/stimuli/textbox_editable.py +64 -0
  1312. psychopy/demos/coder/stimuli/variousVisualStims.py +47 -0
  1313. psychopy/demos/coder/stimuli/visual_noise.py +31 -0
  1314. psychopy/demos/coder/sysInfo.py +56 -0
  1315. psychopy/demos/coder/timing/__init__.py +0 -0
  1316. psychopy/demos/coder/timing/callOnFlip.py +39 -0
  1317. psychopy/demos/coder/timing/clocksAndTimers.py +46 -0
  1318. psychopy/demos/coder/timing/millikeyKeyboardTimingTest.py +323 -0
  1319. psychopy/demos/coder/timing/timeByFrames.py +74 -0
  1320. psychopy/demos/coder/timing/timeByFramesEx.py +107 -0
  1321. psychopy/demos/coder/understanding psychopy/colors.py +70 -0
  1322. psychopy/demos/coder/understanding psychopy/fontLayout.py +69 -0
  1323. psychopy/demos/demo_migration.py +214 -0
  1324. psychopy/demos/modernizeDemos.py +16 -0
  1325. psychopy/demos/test_demo_migration.py +155 -0
  1326. psychopy/devices/__init__.py +8 -0
  1327. psychopy/event.py +1333 -0
  1328. psychopy/exceptions.py +59 -0
  1329. psychopy/experiment/__init__.py +51 -0
  1330. psychopy/experiment/_experiment.py +1392 -0
  1331. psychopy/experiment/blankTemplate.xltx +0 -0
  1332. psychopy/experiment/components/__init__.py +411 -0
  1333. psychopy/experiment/components/_base.py +1351 -0
  1334. psychopy/experiment/components/aperture/__init__.py +149 -0
  1335. psychopy/experiment/components/aperture/classic/aperture.png +0 -0
  1336. psychopy/experiment/components/aperture/classic/aperture@2x.png +0 -0
  1337. psychopy/experiment/components/aperture/dark/aperture.png +0 -0
  1338. psychopy/experiment/components/aperture/dark/aperture@2x.png +0 -0
  1339. psychopy/experiment/components/aperture/light/aperture.png +0 -0
  1340. psychopy/experiment/components/aperture/light/aperture@2x.png +0 -0
  1341. psychopy/experiment/components/brush/__init__.py +163 -0
  1342. psychopy/experiment/components/brush/classic/brush.png +0 -0
  1343. psychopy/experiment/components/brush/classic/brush@2x.png +0 -0
  1344. psychopy/experiment/components/brush/dark/brush.png +0 -0
  1345. psychopy/experiment/components/brush/dark/brush@2x.png +0 -0
  1346. psychopy/experiment/components/brush/light/brush.png +0 -0
  1347. psychopy/experiment/components/brush/light/brush@2x.png +0 -0
  1348. psychopy/experiment/components/button/__init__.py +489 -0
  1349. psychopy/experiment/components/button/classic/button.png +0 -0
  1350. psychopy/experiment/components/button/classic/button@2x.png +0 -0
  1351. psychopy/experiment/components/button/dark/button.png +0 -0
  1352. psychopy/experiment/components/button/dark/button@2x.png +0 -0
  1353. psychopy/experiment/components/button/light/button.png +0 -0
  1354. psychopy/experiment/components/button/light/button@2x.png +0 -0
  1355. psychopy/experiment/components/buttonBox/__init__.py +316 -0
  1356. psychopy/experiment/components/buttonBox/classic/buttonBox.png +0 -0
  1357. psychopy/experiment/components/buttonBox/classic/buttonBox@2x.png +0 -0
  1358. psychopy/experiment/components/buttonBox/dark/buttonBox.png +0 -0
  1359. psychopy/experiment/components/buttonBox/dark/buttonBox@2x.png +0 -0
  1360. psychopy/experiment/components/buttonBox/light/buttonBox.png +0 -0
  1361. psychopy/experiment/components/buttonBox/light/buttonBox@2x.png +0 -0
  1362. psychopy/experiment/components/camera/__init__.py +591 -0
  1363. psychopy/experiment/components/camera/classic/webcam.png +0 -0
  1364. psychopy/experiment/components/camera/classic/webcam@2x.png +0 -0
  1365. psychopy/experiment/components/camera/dark/webcam.png +0 -0
  1366. psychopy/experiment/components/camera/dark/webcam@2x.png +0 -0
  1367. psychopy/experiment/components/camera/light/webcam.png +0 -0
  1368. psychopy/experiment/components/camera/light/webcam@2x.png +0 -0
  1369. psychopy/experiment/components/code/__init__.py +266 -0
  1370. psychopy/experiment/components/code/classic/code.png +0 -0
  1371. psychopy/experiment/components/code/classic/code@2x.png +0 -0
  1372. psychopy/experiment/components/code/dark/code.png +0 -0
  1373. psychopy/experiment/components/code/dark/code@2x.png +0 -0
  1374. psychopy/experiment/components/code/light/code.png +0 -0
  1375. psychopy/experiment/components/code/light/code@2x.png +0 -0
  1376. psychopy/experiment/components/dots/__init__.py +199 -0
  1377. psychopy/experiment/components/dots/classic/dots.png +0 -0
  1378. psychopy/experiment/components/dots/classic/dots@2x.png +0 -0
  1379. psychopy/experiment/components/dots/dark/dots.png +0 -0
  1380. psychopy/experiment/components/dots/dark/dots@2x.png +0 -0
  1381. psychopy/experiment/components/dots/dots.xcf +0 -0
  1382. psychopy/experiment/components/dots/light/dots.png +0 -0
  1383. psychopy/experiment/components/dots/light/dots@2x.png +0 -0
  1384. psychopy/experiment/components/eyetracker_record/__init__.py +128 -0
  1385. psychopy/experiment/components/eyetracker_record/classic/eyetracker_record.png +0 -0
  1386. psychopy/experiment/components/eyetracker_record/classic/eyetracker_record@2x.png +0 -0
  1387. psychopy/experiment/components/eyetracker_record/dark/eyetracker_record.png +0 -0
  1388. psychopy/experiment/components/eyetracker_record/dark/eyetracker_record@2x.png +0 -0
  1389. psychopy/experiment/components/eyetracker_record/light/eyetracker_record.png +0 -0
  1390. psychopy/experiment/components/eyetracker_record/light/eyetracker_record@2x.png +0 -0
  1391. psychopy/experiment/components/form/__init__.py +223 -0
  1392. psychopy/experiment/components/form/classic/form.png +0 -0
  1393. psychopy/experiment/components/form/classic/form@2x.png +0 -0
  1394. psychopy/experiment/components/form/dark/form.png +0 -0
  1395. psychopy/experiment/components/form/dark/form@2x.png +0 -0
  1396. psychopy/experiment/components/form/formItems.xltx +0 -0
  1397. psychopy/experiment/components/form/light/form.png +0 -0
  1398. psychopy/experiment/components/form/light/form@2x.png +0 -0
  1399. psychopy/experiment/components/grating/__init__.py +192 -0
  1400. psychopy/experiment/components/grating/classic/grating.png +0 -0
  1401. psychopy/experiment/components/grating/classic/grating@2x.png +0 -0
  1402. psychopy/experiment/components/grating/dark/grating.png +0 -0
  1403. psychopy/experiment/components/grating/dark/grating@2x.png +0 -0
  1404. psychopy/experiment/components/grating/light/grating.png +0 -0
  1405. psychopy/experiment/components/grating/light/grating@2x.png +0 -0
  1406. psychopy/experiment/components/image/__init__.py +184 -0
  1407. psychopy/experiment/components/image/classic/image.png +0 -0
  1408. psychopy/experiment/components/image/classic/image@2x.png +0 -0
  1409. psychopy/experiment/components/image/dark/image.png +0 -0
  1410. psychopy/experiment/components/image/dark/image@2x.png +0 -0
  1411. psychopy/experiment/components/image/light/image.png +0 -0
  1412. psychopy/experiment/components/image/light/image@2x.png +0 -0
  1413. psychopy/experiment/components/joyButtons/__init__.py +453 -0
  1414. psychopy/experiment/components/joyButtons/classic/joyButtons.png +0 -0
  1415. psychopy/experiment/components/joyButtons/classic/joybuttons@2x.png +0 -0
  1416. psychopy/experiment/components/joyButtons/dark/joyButtons.png +0 -0
  1417. psychopy/experiment/components/joyButtons/dark/joyButtons@2x.png +0 -0
  1418. psychopy/experiment/components/joyButtons/light/joyButtons.png +0 -0
  1419. psychopy/experiment/components/joyButtons/light/joyButtons@2x.png +0 -0
  1420. psychopy/experiment/components/joyButtons/virtualJoyButtons.py +34 -0
  1421. psychopy/experiment/components/joystick/__init__.py +572 -0
  1422. psychopy/experiment/components/joystick/classic/joystick.png +0 -0
  1423. psychopy/experiment/components/joystick/classic/joystick@2x.png +0 -0
  1424. psychopy/experiment/components/joystick/dark/joystick.png +0 -0
  1425. psychopy/experiment/components/joystick/dark/joystick@2x.png +0 -0
  1426. psychopy/experiment/components/joystick/light/joystick.png +0 -0
  1427. psychopy/experiment/components/joystick/light/joystick@2x.png +0 -0
  1428. psychopy/experiment/components/joystick/virtualJoystick.py +40 -0
  1429. psychopy/experiment/components/keyboard/__init__.py +587 -0
  1430. psychopy/experiment/components/keyboard/classic/keyboard.png +0 -0
  1431. psychopy/experiment/components/keyboard/classic/keyboard@2x.png +0 -0
  1432. psychopy/experiment/components/keyboard/dark/keyboard.png +0 -0
  1433. psychopy/experiment/components/keyboard/dark/keyboard@2x.png +0 -0
  1434. psychopy/experiment/components/keyboard/light/keyboard.png +0 -0
  1435. psychopy/experiment/components/keyboard/light/keyboard@2x.png +0 -0
  1436. psychopy/experiment/components/keyboard.xcf +0 -0
  1437. psychopy/experiment/components/microphone/__init__.py +664 -0
  1438. psychopy/experiment/components/microphone/classic/microphone.png +0 -0
  1439. psychopy/experiment/components/microphone/classic/microphone@2x.png +0 -0
  1440. psychopy/experiment/components/microphone/dark/microphone.png +0 -0
  1441. psychopy/experiment/components/microphone/dark/microphone@2x.png +0 -0
  1442. psychopy/experiment/components/microphone/light/microphone.png +0 -0
  1443. psychopy/experiment/components/microphone/light/microphone@2x.png +0 -0
  1444. psychopy/experiment/components/mouse/__init__.py +747 -0
  1445. psychopy/experiment/components/mouse/classic/mouse.png +0 -0
  1446. psychopy/experiment/components/mouse/classic/mouse@2x.png +0 -0
  1447. psychopy/experiment/components/mouse/dark/mouse.png +0 -0
  1448. psychopy/experiment/components/mouse/dark/mouse@2x.png +0 -0
  1449. psychopy/experiment/components/mouse/light/mouse.png +0 -0
  1450. psychopy/experiment/components/mouse/light/mouse@2x.png +0 -0
  1451. psychopy/experiment/components/movie/__init__.py +367 -0
  1452. psychopy/experiment/components/movie/classic/movie.png +0 -0
  1453. psychopy/experiment/components/movie/classic/movie@2x.png +0 -0
  1454. psychopy/experiment/components/movie/dark/movie.png +0 -0
  1455. psychopy/experiment/components/movie/dark/movie@2x.png +0 -0
  1456. psychopy/experiment/components/movie/light/movie.png +0 -0
  1457. psychopy/experiment/components/movie/light/movie@2x.png +0 -0
  1458. psychopy/experiment/components/panorama/__init__.py +456 -0
  1459. psychopy/experiment/components/panorama/classic/panorama.png +0 -0
  1460. psychopy/experiment/components/panorama/classic/panorama@2x.png +0 -0
  1461. psychopy/experiment/components/panorama/dark/panorama.png +0 -0
  1462. psychopy/experiment/components/panorama/dark/panorama@2x.png +0 -0
  1463. psychopy/experiment/components/panorama/light/panorama.png +0 -0
  1464. psychopy/experiment/components/panorama/light/panorama@2x.png +0 -0
  1465. psychopy/experiment/components/parallelOut/__init__.py +178 -0
  1466. psychopy/experiment/components/parallelOut/classic/parallel.png +0 -0
  1467. psychopy/experiment/components/parallelOut/classic/parallel@2x.png +0 -0
  1468. psychopy/experiment/components/parallelOut/dark/parallel.png +0 -0
  1469. psychopy/experiment/components/parallelOut/dark/parallel@2x.png +0 -0
  1470. psychopy/experiment/components/parallelOut/light/parallel.png +0 -0
  1471. psychopy/experiment/components/parallelOut/light/parallel@2x.png +0 -0
  1472. psychopy/experiment/components/patch/__init__.py +121 -0
  1473. psychopy/experiment/components/patch/classic/patch.png +0 -0
  1474. psychopy/experiment/components/patch/dark/patch.png +0 -0
  1475. psychopy/experiment/components/patch/dark/patch@2x.png +0 -0
  1476. psychopy/experiment/components/patch/light/patch.png +0 -0
  1477. psychopy/experiment/components/patch/light/patch@2x.png +0 -0
  1478. psychopy/experiment/components/polygon/__init__.py +303 -0
  1479. psychopy/experiment/components/polygon/classic/polygon.png +0 -0
  1480. psychopy/experiment/components/polygon/classic/polygon@2x.png +0 -0
  1481. psychopy/experiment/components/polygon/dark/polygon.png +0 -0
  1482. psychopy/experiment/components/polygon/dark/polygon@2x.png +0 -0
  1483. psychopy/experiment/components/polygon/light/polygon.png +0 -0
  1484. psychopy/experiment/components/polygon/light/polygon@2x.png +0 -0
  1485. psychopy/experiment/components/progress/__init__.py +130 -0
  1486. psychopy/experiment/components/progress/classic/progress.png +0 -0
  1487. psychopy/experiment/components/progress/classic/progress@2x.png +0 -0
  1488. psychopy/experiment/components/progress/dark/progress.png +0 -0
  1489. psychopy/experiment/components/progress/dark/progress@2x.png +0 -0
  1490. psychopy/experiment/components/progress/light/progress.png +0 -0
  1491. psychopy/experiment/components/progress/light/progress@2x.png +0 -0
  1492. psychopy/experiment/components/ratingScale/__init__.py +337 -0
  1493. psychopy/experiment/components/ratingScale/classic/ratingscale.png +0 -0
  1494. psychopy/experiment/components/ratingScale/classic/ratingscale@2x.png +0 -0
  1495. psychopy/experiment/components/ratingScale/dark/ratingScale@2x.png +0 -0
  1496. psychopy/experiment/components/ratingScale/dark/ratingscale.png +0 -0
  1497. psychopy/experiment/components/ratingScale/light/ratingScale@2x.png +0 -0
  1498. psychopy/experiment/components/ratingScale/light/ratingscale.png +0 -0
  1499. psychopy/experiment/components/resourceManager/__init__.py +176 -0
  1500. psychopy/experiment/components/resourceManager/classic/resource_manager.png +0 -0
  1501. psychopy/experiment/components/resourceManager/classic/resource_manager@2x.png +0 -0
  1502. psychopy/experiment/components/resourceManager/dark/resource_manager.png +0 -0
  1503. psychopy/experiment/components/resourceManager/dark/resource_manager@2x.png +0 -0
  1504. psychopy/experiment/components/resourceManager/light/resource_manager.png +0 -0
  1505. psychopy/experiment/components/resourceManager/light/resource_manager@2x.png +0 -0
  1506. psychopy/experiment/components/roi/__init__.py +311 -0
  1507. psychopy/experiment/components/roi/classic/eyetracker_roi.png +0 -0
  1508. psychopy/experiment/components/roi/classic/eyetracker_roi@2x.png +0 -0
  1509. psychopy/experiment/components/roi/dark/eyetracker_roi.png +0 -0
  1510. psychopy/experiment/components/roi/dark/eyetracker_roi@2X.png +0 -0
  1511. psychopy/experiment/components/roi/light/eyetracker_roi.png +0 -0
  1512. psychopy/experiment/components/roi/light/eyetracker_roi@2X.png +0 -0
  1513. psychopy/experiment/components/routineSettings/__init__.py +338 -0
  1514. psychopy/experiment/components/routineSettings/classic/routineSettings.png +0 -0
  1515. psychopy/experiment/components/routineSettings/classic/routineSettings@2x.png +0 -0
  1516. psychopy/experiment/components/routineSettings/dark/routineSettings.png +0 -0
  1517. psychopy/experiment/components/routineSettings/dark/routineSettings@2x.png +0 -0
  1518. psychopy/experiment/components/routineSettings/light/routineSettings.png +0 -0
  1519. psychopy/experiment/components/routineSettings/light/routineSettings@2x.png +0 -0
  1520. psychopy/experiment/components/serialOut/__init__.py +205 -0
  1521. psychopy/experiment/components/serialOut/classic/serial.png +0 -0
  1522. psychopy/experiment/components/serialOut/classic/serial@2x.png +0 -0
  1523. psychopy/experiment/components/serialOut/dark/serial.png +0 -0
  1524. psychopy/experiment/components/serialOut/dark/serial@2x.png +0 -0
  1525. psychopy/experiment/components/serialOut/light/serial.png +0 -0
  1526. psychopy/experiment/components/serialOut/light/serial@2x.png +0 -0
  1527. psychopy/experiment/components/settings/JS_htmlHeader.tmpl +23 -0
  1528. psychopy/experiment/components/settings/JS_setupExp.tmpl +28 -0
  1529. psychopy/experiment/components/settings/__init__.py +2155 -0
  1530. psychopy/experiment/components/settings/classic/settings.png +0 -0
  1531. psychopy/experiment/components/settings/classic/settings@2x.png +0 -0
  1532. psychopy/experiment/components/settings/dark/settings.png +0 -0
  1533. psychopy/experiment/components/settings/dark/settings@2x.png +0 -0
  1534. psychopy/experiment/components/settings/light/settings.png +0 -0
  1535. psychopy/experiment/components/settings/light/settings@2x.png +0 -0
  1536. psychopy/experiment/components/slider/__init__.py +410 -0
  1537. psychopy/experiment/components/slider/classic/slider.png +0 -0
  1538. psychopy/experiment/components/slider/classic/slider@2x.png +0 -0
  1539. psychopy/experiment/components/slider/dark/slider.png +0 -0
  1540. psychopy/experiment/components/slider/dark/slider@2x.png +0 -0
  1541. psychopy/experiment/components/slider/light/slider.png +0 -0
  1542. psychopy/experiment/components/slider/light/slider@2x.png +0 -0
  1543. psychopy/experiment/components/sound/__init__.py +307 -0
  1544. psychopy/experiment/components/sound/classic/sound.png +0 -0
  1545. psychopy/experiment/components/sound/classic/sound@2x.png +0 -0
  1546. psychopy/experiment/components/sound/dark/sound.png +0 -0
  1547. psychopy/experiment/components/sound/dark/sound@2x.png +0 -0
  1548. psychopy/experiment/components/sound/light/sound.png +0 -0
  1549. psychopy/experiment/components/sound/light/sound@2x.png +0 -0
  1550. psychopy/experiment/components/static/__init__.py +267 -0
  1551. psychopy/experiment/components/static/classic/static.png +0 -0
  1552. psychopy/experiment/components/static/classic/static@2x.png +0 -0
  1553. psychopy/experiment/components/static/dark/static.png +0 -0
  1554. psychopy/experiment/components/static/dark/static@2x.png +0 -0
  1555. psychopy/experiment/components/static/light/static.png +0 -0
  1556. psychopy/experiment/components/static/light/static@2x.png +0 -0
  1557. psychopy/experiment/components/text/__init__.py +169 -0
  1558. psychopy/experiment/components/text/classic/text.png +0 -0
  1559. psychopy/experiment/components/text/classic/text@2x.png +0 -0
  1560. psychopy/experiment/components/text/dark/text.png +0 -0
  1561. psychopy/experiment/components/text/dark/text@2x.png +0 -0
  1562. psychopy/experiment/components/text/light/text.png +0 -0
  1563. psychopy/experiment/components/text/light/text@2x.png +0 -0
  1564. psychopy/experiment/components/textbox/__init__.py +330 -0
  1565. psychopy/experiment/components/textbox/classic/textbox.png +0 -0
  1566. psychopy/experiment/components/textbox/classic/textbox@2x.png +0 -0
  1567. psychopy/experiment/components/textbox/dark/textbox.png +0 -0
  1568. psychopy/experiment/components/textbox/dark/textbox@2x.png +0 -0
  1569. psychopy/experiment/components/textbox/light/textbox.png +0 -0
  1570. psychopy/experiment/components/textbox/light/textbox@2x.png +0 -0
  1571. psychopy/experiment/components/unknown/__init__.py +86 -0
  1572. psychopy/experiment/components/unknown/classic/unknown.png +0 -0
  1573. psychopy/experiment/components/unknown/classic/unknown@2x.png +0 -0
  1574. psychopy/experiment/components/unknown/dark/unknown.png +0 -0
  1575. psychopy/experiment/components/unknown/dark/unknown@2x.png +0 -0
  1576. psychopy/experiment/components/unknown/light/unknown.png +0 -0
  1577. psychopy/experiment/components/unknown/light/unknown@2x.png +0 -0
  1578. psychopy/experiment/components/unknownPlugin/__init__.py +84 -0
  1579. psychopy/experiment/components/unknownPlugin/classic/unknownPlugin.png +0 -0
  1580. psychopy/experiment/components/unknownPlugin/classic/unknownPlugin@2x.png +0 -0
  1581. psychopy/experiment/components/unknownPlugin/dark/unknownPlugin.png +0 -0
  1582. psychopy/experiment/components/unknownPlugin/dark/unknownPlugin@2x.png +0 -0
  1583. psychopy/experiment/components/unknownPlugin/light/unknownPlugin.png +0 -0
  1584. psychopy/experiment/components/unknownPlugin/light/unknownPlugin@2x.png +0 -0
  1585. psychopy/experiment/components/utils.py +0 -0
  1586. psychopy/experiment/components/variable/__init__.py +184 -0
  1587. psychopy/experiment/components/variable/classic/variable.png +0 -0
  1588. psychopy/experiment/components/variable/classic/variable@2x.png +0 -0
  1589. psychopy/experiment/components/variable/dark/variable.png +0 -0
  1590. psychopy/experiment/components/variable/dark/variable@2x.png +0 -0
  1591. psychopy/experiment/components/variable/light/variable.png +0 -0
  1592. psychopy/experiment/components/variable/light/variable@2x.png +0 -0
  1593. psychopy/experiment/experiment.xsd +223 -0
  1594. psychopy/experiment/exports.py +388 -0
  1595. psychopy/experiment/flow.py +531 -0
  1596. psychopy/experiment/localization.py +11 -0
  1597. psychopy/experiment/loopTemplate.xltx +0 -0
  1598. psychopy/experiment/loops.py +952 -0
  1599. psychopy/experiment/params.py +437 -0
  1600. psychopy/experiment/plugins.py +115 -0
  1601. psychopy/experiment/py2js.py +183 -0
  1602. psychopy/experiment/py2js_transpiler.py +606 -0
  1603. psychopy/experiment/questPlusTemplate.xltx +0 -0
  1604. psychopy/experiment/questTemplate.xltx +0 -0
  1605. psychopy/experiment/routines/__init__.py +108 -0
  1606. psychopy/experiment/routines/_base.py +907 -0
  1607. psychopy/experiment/routines/counterbalance/__init__.py +315 -0
  1608. psychopy/experiment/routines/counterbalance/classic/counterbalance.png +0 -0
  1609. psychopy/experiment/routines/counterbalance/classic/counterbalance@2x.png +0 -0
  1610. psychopy/experiment/routines/counterbalance/counterbalanceItems.xltx +0 -0
  1611. psychopy/experiment/routines/counterbalance/dark/counterbalance.png +0 -0
  1612. psychopy/experiment/routines/counterbalance/dark/counterbalance@2x.png +0 -0
  1613. psychopy/experiment/routines/counterbalance/light/counterbalance.png +0 -0
  1614. psychopy/experiment/routines/counterbalance/light/counterbalance@2x.png +0 -0
  1615. psychopy/experiment/routines/eyetracker_calibrate/__init__.py +275 -0
  1616. psychopy/experiment/routines/eyetracker_calibrate/classic/eyetracker_calib.png +0 -0
  1617. psychopy/experiment/routines/eyetracker_calibrate/dark/eyetracker_calib.png +0 -0
  1618. psychopy/experiment/routines/eyetracker_calibrate/dark/eyetracker_calib@2x.png +0 -0
  1619. psychopy/experiment/routines/eyetracker_calibrate/light/eyetracker_calib.png +0 -0
  1620. psychopy/experiment/routines/eyetracker_calibrate/light/eyetracker_calib@2x.png +0 -0
  1621. psychopy/experiment/routines/eyetracker_validate/__init__.py +354 -0
  1622. psychopy/experiment/routines/eyetracker_validate/classic/eyetracker_valid.png +0 -0
  1623. psychopy/experiment/routines/eyetracker_validate/dark/eyetracker_valid.png +0 -0
  1624. psychopy/experiment/routines/eyetracker_validate/dark/eyetracker_valid@2x.png +0 -0
  1625. psychopy/experiment/routines/eyetracker_validate/light/eyetracker_valid.png +0 -0
  1626. psychopy/experiment/routines/eyetracker_validate/light/eyetracker_valid@2x.png +0 -0
  1627. psychopy/experiment/routines/pavlovia_survey/__init__.py +236 -0
  1628. psychopy/experiment/routines/pavlovia_survey/classic/survey.png +0 -0
  1629. psychopy/experiment/routines/pavlovia_survey/classic/survey@2x.png +0 -0
  1630. psychopy/experiment/routines/pavlovia_survey/dark/survey.png +0 -0
  1631. psychopy/experiment/routines/pavlovia_survey/dark/survey@2x.png +0 -0
  1632. psychopy/experiment/routines/pavlovia_survey/light/survey.png +0 -0
  1633. psychopy/experiment/routines/pavlovia_survey/light/survey@2x.png +0 -0
  1634. psychopy/experiment/routines/photodiodeValidator/__init__.py +429 -0
  1635. psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator.png +0 -0
  1636. psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator@2x.png +0 -0
  1637. psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator.png +0 -0
  1638. psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator@2x.png +0 -0
  1639. psychopy/experiment/routines/photodiodeValidator/light/photodiode_validator.png +0 -0
  1640. psychopy/experiment/routines/photodiodeValidator/light/photodiode_validator@2x.png +0 -0
  1641. psychopy/experiment/routines/unknown/__init__.py +28 -0
  1642. psychopy/experiment/routines/unknown/classic/eyetracker_record.png +0 -0
  1643. psychopy/experiment/routines/unknown/classic/unknown.png +0 -0
  1644. psychopy/experiment/routines/unknown/dark/eyetracker_record.png +0 -0
  1645. psychopy/experiment/routines/unknown/dark/eyetracker_record@2x.png +0 -0
  1646. psychopy/experiment/routines/unknown/dark/unknown.png +0 -0
  1647. psychopy/experiment/routines/unknown/dark/unknown@2x.png +0 -0
  1648. psychopy/experiment/routines/unknown/light/eyetracker_record.png +0 -0
  1649. psychopy/experiment/routines/unknown/light/eyetracker_record@2x.png +0 -0
  1650. psychopy/experiment/routines/unknown/light/unknown.png +0 -0
  1651. psychopy/experiment/routines/unknown/light/unknown@2x.png +0 -0
  1652. psychopy/experiment/routines/utils.py +0 -0
  1653. psychopy/experiment/staircaseTemplate.xltx +0 -0
  1654. psychopy/experiment/utils.py +44 -0
  1655. psychopy/filters.py +11 -0
  1656. psychopy/gamma.py +9 -0
  1657. psychopy/gui/__init__.py +47 -0
  1658. psychopy/gui/qtgui.py +866 -0
  1659. psychopy/gui/util.py +78 -0
  1660. psychopy/gui/wxgui.py +414 -0
  1661. psychopy/hardware/__init__.py +216 -0
  1662. psychopy/hardware/base.py +323 -0
  1663. psychopy/hardware/bbtk/__init__.py +30 -0
  1664. psychopy/hardware/brainproducts.py +31 -0
  1665. psychopy/hardware/button.py +205 -0
  1666. psychopy/hardware/buttonbox/__init__.py +122 -0
  1667. psychopy/hardware/camera/__init__.py +2809 -0
  1668. psychopy/hardware/cedrus.py +36 -0
  1669. psychopy/hardware/crs/__init__.py +46 -0
  1670. psychopy/hardware/crs/bits.py +34 -0
  1671. psychopy/hardware/crs/colorcal.py +30 -0
  1672. psychopy/hardware/crs/optical.py +46 -0
  1673. psychopy/hardware/crs/shaders.py +21 -0
  1674. psychopy/hardware/emotiv.py +33 -0
  1675. psychopy/hardware/emulator.py +37 -0
  1676. psychopy/hardware/eyetracker.py +208 -0
  1677. psychopy/hardware/forp.py +42 -0
  1678. psychopy/hardware/gammasci.py +32 -0
  1679. psychopy/hardware/iolab.py +35 -0
  1680. psychopy/hardware/joystick/__init__.py +597 -0
  1681. psychopy/hardware/keyboard.py +880 -0
  1682. psychopy/hardware/knownDevices.json +52 -0
  1683. psychopy/hardware/labhackers.py +27 -0
  1684. psychopy/hardware/labjacks.py +30 -0
  1685. psychopy/hardware/listener.py +323 -0
  1686. psychopy/hardware/manager.py +963 -0
  1687. psychopy/hardware/microphone.py +1074 -0
  1688. psychopy/hardware/minolta.py +30 -0
  1689. psychopy/hardware/mouse/__init__.py +885 -0
  1690. psychopy/hardware/photodiode.py +639 -0
  1691. psychopy/hardware/photometer/__init__.py +176 -0
  1692. psychopy/hardware/pr.py +30 -0
  1693. psychopy/hardware/qmix.py +41 -0
  1694. psychopy/hardware/serialdevice.py +342 -0
  1695. psychopy/hardware/speaker.py +54 -0
  1696. psychopy/hardware/triggerbox/__init__.py +56 -0
  1697. psychopy/hardware/triggerbox/base.py +170 -0
  1698. psychopy/hardware/triggerbox/parallel.py +362 -0
  1699. psychopy/info.py +790 -0
  1700. psychopy/iohub/__init__.py +45 -0
  1701. psychopy/iohub/client/__init__.py +1454 -0
  1702. psychopy/iohub/client/connect.py +260 -0
  1703. psychopy/iohub/client/eyetracker/__init__.py +4 -0
  1704. psychopy/iohub/client/eyetracker/validation/__init__.py +8 -0
  1705. psychopy/iohub/client/eyetracker/validation/posgrid.py +274 -0
  1706. psychopy/iohub/client/eyetracker/validation/procedure.py +1292 -0
  1707. psychopy/iohub/client/eyetracker/validation/trigger.py +240 -0
  1708. psychopy/iohub/client/keyboard.py +508 -0
  1709. psychopy/iohub/client/wintab.py +378 -0
  1710. psychopy/iohub/constants.py +1176 -0
  1711. psychopy/iohub/datastore/__init__.py +439 -0
  1712. psychopy/iohub/datastore/default_datastore.yaml +8 -0
  1713. psychopy/iohub/datastore/util.py +868 -0
  1714. psychopy/iohub/default_config.yaml +17 -0
  1715. psychopy/iohub/devices/__init__.py +960 -0
  1716. psychopy/iohub/devices/computer.py +607 -0
  1717. psychopy/iohub/devices/default_device.yaml +15 -0
  1718. psychopy/iohub/devices/deviceConfigValidation.py +517 -0
  1719. psychopy/iohub/devices/display/__init__.py +755 -0
  1720. psychopy/iohub/devices/display/default_display.yaml +118 -0
  1721. psychopy/iohub/devices/display/supported_config_settings.yaml +69 -0
  1722. psychopy/iohub/devices/eventfilters.py +3572 -0
  1723. psychopy/iohub/devices/experiment/__init__.py +316 -0
  1724. psychopy/iohub/devices/experiment/default_experiment.yaml +63 -0
  1725. psychopy/iohub/devices/experiment/supported_config_settings.yaml +22 -0
  1726. psychopy/iohub/devices/eyetracker/__init__.py +436 -0
  1727. psychopy/iohub/devices/eyetracker/calibration/__init__.py +1 -0
  1728. psychopy/iohub/devices/eyetracker/calibration/procedure.py +409 -0
  1729. psychopy/iohub/devices/eyetracker/default_eyetracker.yaml +18 -0
  1730. psychopy/iohub/devices/eyetracker/eye_events.py +1751 -0
  1731. psychopy/iohub/devices/eyetracker/filters/__init__.py +4 -0
  1732. psychopy/iohub/devices/eyetracker/filters/parser.py +913 -0
  1733. psychopy/iohub/devices/eyetracker/hw/__init__.py +4 -0
  1734. psychopy/iohub/devices/eyetracker/hw/gazepoint/__init__.py +17 -0
  1735. psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/__init__.py +28 -0
  1736. psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/calibration.py +18 -0
  1737. psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/eyetracker.py +21 -0
  1738. psychopy/iohub/devices/eyetracker/hw/mouse/__init__.py +8 -0
  1739. psychopy/iohub/devices/eyetracker/hw/mouse/calibration.py +10 -0
  1740. psychopy/iohub/devices/eyetracker/hw/mouse/default_eyetracker.yaml +102 -0
  1741. psychopy/iohub/devices/eyetracker/hw/mouse/eyetracker.py +444 -0
  1742. psychopy/iohub/devices/eyetracker/hw/mouse/supported_config_settings.yaml +110 -0
  1743. psychopy/iohub/devices/eyetracker/hw/pupil_labs/__init__.py +4 -0
  1744. psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/__init__.py +26 -0
  1745. psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/eyetracker.py +18 -0
  1746. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/__init__.py +29 -0
  1747. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/bisector.py +20 -0
  1748. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/constants.py +19 -0
  1749. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/data_parse.py +22 -0
  1750. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/eyetracker.py +18 -0
  1751. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/pupil_remote.py +18 -0
  1752. psychopy/iohub/devices/eyetracker/hw/sr_research/__init__.py +4 -0
  1753. psychopy/iohub/devices/eyetracker/hw/sr_research/eyelink/__init__.py +28 -0
  1754. psychopy/iohub/devices/eyetracker/hw/sr_research/eyelink/calibration.py +22 -0
  1755. psychopy/iohub/devices/eyetracker/hw/sr_research/eyelink/eyetracker.py +38 -0
  1756. psychopy/iohub/devices/eyetracker/hw/tobii/__init__.py +29 -0
  1757. psychopy/iohub/devices/eyetracker/hw/tobii/calibration.py +19 -0
  1758. psychopy/iohub/devices/eyetracker/hw/tobii/eyetracker.py +17 -0
  1759. psychopy/iohub/devices/eyetracker/hw/tobii/tobiiwrapper.py +19 -0
  1760. psychopy/iohub/devices/eyetracker/supported_config_settings.yaml +44 -0
  1761. psychopy/iohub/devices/keyboard/__init__.py +309 -0
  1762. psychopy/iohub/devices/keyboard/darwin.py +428 -0
  1763. psychopy/iohub/devices/keyboard/darwinkey.py +94 -0
  1764. psychopy/iohub/devices/keyboard/default_keyboard.yaml +94 -0
  1765. psychopy/iohub/devices/keyboard/linux2.py +102 -0
  1766. psychopy/iohub/devices/keyboard/supported_config_settings.yaml +39 -0
  1767. psychopy/iohub/devices/keyboard/win32.py +356 -0
  1768. psychopy/iohub/devices/mouse/__init__.py +709 -0
  1769. psychopy/iohub/devices/mouse/darwin.py +414 -0
  1770. psychopy/iohub/devices/mouse/default_mouse.yaml +92 -0
  1771. psychopy/iohub/devices/mouse/linux2.py +167 -0
  1772. psychopy/iohub/devices/mouse/supported_config_settings.yaml +39 -0
  1773. psychopy/iohub/devices/mouse/win32.py +279 -0
  1774. psychopy/iohub/devices/pyXHook.py +619 -0
  1775. psychopy/iohub/devices/serial/__init__.py +779 -0
  1776. psychopy/iohub/devices/serial/default_pstbox.yaml +108 -0
  1777. psychopy/iohub/devices/serial/default_serial.yaml +108 -0
  1778. psychopy/iohub/devices/serial/supported_config_settings.yaml +85 -0
  1779. psychopy/iohub/devices/serial/supported_config_settings_pstbox.yaml +85 -0
  1780. psychopy/iohub/devices/supported_config_settings.yaml +36 -0
  1781. psychopy/iohub/devices/wintab/__init__.py +580 -0
  1782. psychopy/iohub/devices/wintab/default_wintab.yaml +89 -0
  1783. psychopy/iohub/devices/wintab/supported_config_settings.yaml +42 -0
  1784. psychopy/iohub/devices/wintab/win32.py +722 -0
  1785. psychopy/iohub/devices/xlib.py +6795 -0
  1786. psychopy/iohub/errors.py +61 -0
  1787. psychopy/iohub/lazy_import.py +582 -0
  1788. psychopy/iohub/net.py +349 -0
  1789. psychopy/iohub/server.py +1075 -0
  1790. psychopy/iohub/start_iohub_process.py +118 -0
  1791. psychopy/iohub/util/__init__.py +841 -0
  1792. psychopy/iohub/util/visualangle.py +126 -0
  1793. psychopy/layout.py +916 -0
  1794. psychopy/liaison.py +419 -0
  1795. psychopy/locale_setup.py +31 -0
  1796. psychopy/localization/__init__.py +22 -0
  1797. psychopy/localization/_localization.py +155 -0
  1798. psychopy/localization/generateTranslationTemplate.py +139 -0
  1799. psychopy/localization/mappings.txt +170 -0
  1800. psychopy/localization/messages.pot +7516 -0
  1801. psychopy/localization/readme.txt +68 -0
  1802. psychopy/logging.py +406 -0
  1803. psychopy/microphone.py +54 -0
  1804. psychopy/misc.py +40 -0
  1805. psychopy/monitors/MonitorCenter.py +1254 -0
  1806. psychopy/monitors/__init__.py +30 -0
  1807. psychopy/monitors/calibData.py +78 -0
  1808. psychopy/monitors/calibTools.py +1300 -0
  1809. psychopy/monitors/getLumSeries.py +50 -0
  1810. psychopy/monitors/psychopy-icon.svg +395 -0
  1811. psychopy/monitors/psychopy.ico +0 -0
  1812. psychopy/parallel/__init__.py +206 -0
  1813. psychopy/parallel/_dlportio.py +150 -0
  1814. psychopy/parallel/_inpout.py +120 -0
  1815. psychopy/parallel/_linux.py +105 -0
  1816. psychopy/piloting.py +61 -0
  1817. psychopy/platform_specific/__init__.py +48 -0
  1818. psychopy/platform_specific/darwin.py +328 -0
  1819. psychopy/platform_specific/linux.py +79 -0
  1820. psychopy/platform_specific/posix.py +16 -0
  1821. psychopy/platform_specific/win32.py +99 -0
  1822. psychopy/plugins/__init__.py +1354 -0
  1823. psychopy/preferences/Darwin.spec +282 -0
  1824. psychopy/preferences/FreeBSD.spec +282 -0
  1825. psychopy/preferences/Linux.spec +282 -0
  1826. psychopy/preferences/Windows.spec +282 -0
  1827. psychopy/preferences/__init__.py +20 -0
  1828. psychopy/preferences/baseNoArch.spec +278 -0
  1829. psychopy/preferences/generateHints.py +91 -0
  1830. psychopy/preferences/generateSpec.py +80 -0
  1831. psychopy/preferences/hints.py +329 -0
  1832. psychopy/preferences/preferences.py +332 -0
  1833. psychopy/projects/__init__.py +11 -0
  1834. psychopy/projects/gitignore.py +45 -0
  1835. psychopy/projects/pavlovia.py +1566 -0
  1836. psychopy/projects/sshkeys.py +107 -0
  1837. psychopy/psychojs.zip +0 -0
  1838. psychopy/pylintrc +69 -0
  1839. psychopy/scripts/__init__.py +0 -0
  1840. psychopy/scripts/psyexpCompile.py +233 -0
  1841. psychopy/session.py +1450 -0
  1842. psychopy/sound/__init__.py +279 -0
  1843. psychopy/sound/_base.py +282 -0
  1844. psychopy/sound/audioclip.py +851 -0
  1845. psychopy/sound/audiodevice.py +857 -0
  1846. psychopy/sound/backend_ptb.py +660 -0
  1847. psychopy/sound/backend_pygame.py +309 -0
  1848. psychopy/sound/backend_pyo.py +33 -0
  1849. psychopy/sound/backend_pysound.py +341 -0
  1850. psychopy/sound/backend_sounddevice.py +32 -0
  1851. psychopy/sound/exceptions.py +115 -0
  1852. psychopy/sound/microphone.py +274 -0
  1853. psychopy/sound/transcribe.py +1248 -0
  1854. psychopy/tests/.DS_Store +0 -0
  1855. psychopy/tests/README.md +344 -0
  1856. psychopy/tests/__init__.py +47 -0
  1857. psychopy/tests/data/Electronic_Chime-KevanGC-495939803.wav +0 -0
  1858. psychopy/tests/data/TestCircle_w128h128_bottom_left.png +0 -0
  1859. psychopy/tests/data/TestCircle_w128h128_bottom_right.png +0 -0
  1860. psychopy/tests/data/TestCircle_w128h128_center_center.png +0 -0
  1861. psychopy/tests/data/TestCircle_w128h128_top_left.png +0 -0
  1862. psychopy/tests/data/TestCircle_w128h128_top_right.png +0 -0
  1863. psychopy/tests/data/TestCircle_w128h64_bottom_left.png +0 -0
  1864. psychopy/tests/data/TestCircle_w128h64_bottom_right.png +0 -0
  1865. psychopy/tests/data/TestCircle_w128h64_center_center.png +0 -0
  1866. psychopy/tests/data/TestCircle_w128h64_top_left.png +0 -0
  1867. psychopy/tests/data/TestCircle_w128h64_top_right.png +0 -0
  1868. psychopy/tests/data/TestCircle_w64h128_bottom_left.png +0 -0
  1869. psychopy/tests/data/TestCircle_w64h128_bottom_right.png +0 -0
  1870. psychopy/tests/data/TestCircle_w64h128_center_center.png +0 -0
  1871. psychopy/tests/data/TestCircle_w64h128_top_left.png +0 -0
  1872. psychopy/tests/data/TestCircle_w64h128_top_right.png +0 -0
  1873. psychopy/tests/data/TestCircle_w64h64_bottom_left.png +0 -0
  1874. psychopy/tests/data/TestCircle_w64h64_bottom_right.png +0 -0
  1875. psychopy/tests/data/TestCircle_w64h64_center_center.png +0 -0
  1876. psychopy/tests/data/TestCircle_w64h64_top_left.png +0 -0
  1877. psychopy/tests/data/TestCircle_w64h64_top_right.png +0 -0
  1878. psychopy/tests/data/TestForm_scrolling_nq10_s0.5.png +0 -0
  1879. psychopy/tests/data/TestForm_scrolling_nq10_s0.png +0 -0
  1880. psychopy/tests/data/TestForm_scrolling_nq10_s1.png +0 -0
  1881. psychopy/tests/data/TestForm_scrolling_nq1_s0.5.png +0 -0
  1882. psychopy/tests/data/TestForm_scrolling_nq1_s0.png +0 -0
  1883. psychopy/tests/data/TestForm_scrolling_nq1_s1.png +0 -0
  1884. psychopy/tests/data/TestForm_scrolling_nq3_s0.5.png +0 -0
  1885. psychopy/tests/data/TestForm_scrolling_nq3_s0.png +0 -0
  1886. psychopy/tests/data/TestForm_scrolling_nq3_s1.png +0 -0
  1887. psychopy/tests/data/TestImage_w128h128_bottom_left.png +0 -0
  1888. psychopy/tests/data/TestImage_w128h128_bottom_right.png +0 -0
  1889. psychopy/tests/data/TestImage_w128h128_center_center.png +0 -0
  1890. psychopy/tests/data/TestImage_w128h128_top_left.png +0 -0
  1891. psychopy/tests/data/TestImage_w128h128_top_right.png +0 -0
  1892. psychopy/tests/data/TestImage_w128h64_bottom_left.png +0 -0
  1893. psychopy/tests/data/TestImage_w128h64_bottom_right.png +0 -0
  1894. psychopy/tests/data/TestImage_w128h64_center_center.png +0 -0
  1895. psychopy/tests/data/TestImage_w128h64_top_left.png +0 -0
  1896. psychopy/tests/data/TestImage_w128h64_top_right.png +0 -0
  1897. psychopy/tests/data/TestImage_w64h128_bottom_left.png +0 -0
  1898. psychopy/tests/data/TestImage_w64h128_bottom_right.png +0 -0
  1899. psychopy/tests/data/TestImage_w64h128_center_center.png +0 -0
  1900. psychopy/tests/data/TestImage_w64h128_top_left.png +0 -0
  1901. psychopy/tests/data/TestImage_w64h128_top_right.png +0 -0
  1902. psychopy/tests/data/TestImage_w64h64_bottom_left.png +0 -0
  1903. psychopy/tests/data/TestImage_w64h64_bottom_right.png +0 -0
  1904. psychopy/tests/data/TestImage_w64h64_center_center.png +0 -0
  1905. psychopy/tests/data/TestImage_w64h64_top_left.png +0 -0
  1906. psychopy/tests/data/TestImage_w64h64_top_right.png +0 -0
  1907. psychopy/tests/data/TestProgress_testValue_horizontal_center center_0.3.png +0 -0
  1908. psychopy/tests/data/TestProgress_testValue_horizontal_center center_0.6.png +0 -0
  1909. psychopy/tests/data/TestProgress_testValue_horizontal_left center_0.3.png +0 -0
  1910. psychopy/tests/data/TestProgress_testValue_horizontal_left center_0.6.png +0 -0
  1911. psychopy/tests/data/TestProgress_testValue_horizontal_right center_0.3.png +0 -0
  1912. psychopy/tests/data/TestProgress_testValue_horizontal_right center_0.6.png +0 -0
  1913. psychopy/tests/data/TestProgress_testValue_minmax_0.png +0 -0
  1914. psychopy/tests/data/TestProgress_testValue_minmax_1.png +0 -0
  1915. psychopy/tests/data/TestProgress_testValue_vertical_bottom center_0.3.png +0 -0
  1916. psychopy/tests/data/TestProgress_testValue_vertical_bottom center_0.6.png +0 -0
  1917. psychopy/tests/data/TestProgress_testValue_vertical_center center_0.3.png +0 -0
  1918. psychopy/tests/data/TestProgress_testValue_vertical_center center_0.6.png +0 -0
  1919. psychopy/tests/data/TestProgress_testValue_vertical_top center_0.3.png +0 -0
  1920. psychopy/tests/data/TestProgress_testValue_vertical_top center_0.6.png +0 -0
  1921. psychopy/tests/data/TestProgress_w128h128_bottom_left.png +0 -0
  1922. psychopy/tests/data/TestProgress_w128h128_bottom_right.png +0 -0
  1923. psychopy/tests/data/TestProgress_w128h128_center_center.png +0 -0
  1924. psychopy/tests/data/TestProgress_w128h128_top_left.png +0 -0
  1925. psychopy/tests/data/TestProgress_w128h128_top_right.png +0 -0
  1926. psychopy/tests/data/TestProgress_w128h64_bottom_left.png +0 -0
  1927. psychopy/tests/data/TestProgress_w128h64_bottom_right.png +0 -0
  1928. psychopy/tests/data/TestProgress_w128h64_center_center.png +0 -0
  1929. psychopy/tests/data/TestProgress_w128h64_top_left.png +0 -0
  1930. psychopy/tests/data/TestProgress_w128h64_top_right.png +0 -0
  1931. psychopy/tests/data/TestProgress_w64h128_bottom_left.png +0 -0
  1932. psychopy/tests/data/TestProgress_w64h128_bottom_right.png +0 -0
  1933. psychopy/tests/data/TestProgress_w64h128_center_center.png +0 -0
  1934. psychopy/tests/data/TestProgress_w64h128_top_left.png +0 -0
  1935. psychopy/tests/data/TestProgress_w64h128_top_right.png +0 -0
  1936. psychopy/tests/data/TestProgress_w64h64_bottom_left.png +0 -0
  1937. psychopy/tests/data/TestProgress_w64h64_bottom_right.png +0 -0
  1938. psychopy/tests/data/TestProgress_w64h64_center_center.png +0 -0
  1939. psychopy/tests/data/TestProgress_w64h64_top_left.png +0 -0
  1940. psychopy/tests/data/TestProgress_w64h64_top_right.png +0 -0
  1941. psychopy/tests/data/TestROI_w128h128_bottom_left.png +0 -0
  1942. psychopy/tests/data/TestROI_w128h128_bottom_right.png +0 -0
  1943. psychopy/tests/data/TestROI_w128h128_center_center.png +0 -0
  1944. psychopy/tests/data/TestROI_w128h128_top_left.png +0 -0
  1945. psychopy/tests/data/TestROI_w128h128_top_right.png +0 -0
  1946. psychopy/tests/data/TestROI_w128h64_bottom_left.png +0 -0
  1947. psychopy/tests/data/TestROI_w128h64_bottom_right.png +0 -0
  1948. psychopy/tests/data/TestROI_w128h64_center_center.png +0 -0
  1949. psychopy/tests/data/TestROI_w128h64_top_left.png +0 -0
  1950. psychopy/tests/data/TestROI_w128h64_top_right.png +0 -0
  1951. psychopy/tests/data/TestROI_w64h128_bottom_left.png +0 -0
  1952. psychopy/tests/data/TestROI_w64h128_bottom_right.png +0 -0
  1953. psychopy/tests/data/TestROI_w64h128_center_center.png +0 -0
  1954. psychopy/tests/data/TestROI_w64h128_top_left.png +0 -0
  1955. psychopy/tests/data/TestROI_w64h128_top_right.png +0 -0
  1956. psychopy/tests/data/TestROI_w64h64_bottom_left.png +0 -0
  1957. psychopy/tests/data/TestROI_w64h64_bottom_right.png +0 -0
  1958. psychopy/tests/data/TestROI_w64h64_center_center.png +0 -0
  1959. psychopy/tests/data/TestROI_w64h64_top_left.png +0 -0
  1960. psychopy/tests/data/TestROI_w64h64_top_right.png +0 -0
  1961. psychopy/tests/data/TestSession_exp1.png +0 -0
  1962. psychopy/tests/data/TestSession_exp2.png +0 -0
  1963. psychopy/tests/data/TestShape_w128h128_bottom_left.png +0 -0
  1964. psychopy/tests/data/TestShape_w128h128_bottom_right.png +0 -0
  1965. psychopy/tests/data/TestShape_w128h128_center_center.png +0 -0
  1966. psychopy/tests/data/TestShape_w128h128_top_left.png +0 -0
  1967. psychopy/tests/data/TestShape_w128h128_top_right.png +0 -0
  1968. psychopy/tests/data/TestShape_w128h64_bottom_left.png +0 -0
  1969. psychopy/tests/data/TestShape_w128h64_bottom_right.png +0 -0
  1970. psychopy/tests/data/TestShape_w128h64_center_center.png +0 -0
  1971. psychopy/tests/data/TestShape_w128h64_top_left.png +0 -0
  1972. psychopy/tests/data/TestShape_w128h64_top_right.png +0 -0
  1973. psychopy/tests/data/TestShape_w64h128_bottom_left.png +0 -0
  1974. psychopy/tests/data/TestShape_w64h128_bottom_right.png +0 -0
  1975. psychopy/tests/data/TestShape_w64h128_center_center.png +0 -0
  1976. psychopy/tests/data/TestShape_w64h128_top_left.png +0 -0
  1977. psychopy/tests/data/TestShape_w64h128_top_right.png +0 -0
  1978. psychopy/tests/data/TestShape_w64h64_bottom_left.png +0 -0
  1979. psychopy/tests/data/TestShape_w64h64_bottom_right.png +0 -0
  1980. psychopy/tests/data/TestShape_w64h64_center_center.png +0 -0
  1981. psychopy/tests/data/TestShape_w64h64_top_left.png +0 -0
  1982. psychopy/tests/data/TestShape_w64h64_top_right.png +0 -0
  1983. psychopy/tests/data/TestTarget_w128h128_bottom_left.png +0 -0
  1984. psychopy/tests/data/TestTarget_w128h128_bottom_right.png +0 -0
  1985. psychopy/tests/data/TestTarget_w128h128_center_center.png +0 -0
  1986. psychopy/tests/data/TestTarget_w128h128_top_left.png +0 -0
  1987. psychopy/tests/data/TestTarget_w128h128_top_right.png +0 -0
  1988. psychopy/tests/data/TestTarget_w128h64_bottom_left.png +0 -0
  1989. psychopy/tests/data/TestTarget_w128h64_bottom_right.png +0 -0
  1990. psychopy/tests/data/TestTarget_w128h64_center_center.png +0 -0
  1991. psychopy/tests/data/TestTarget_w128h64_top_left.png +0 -0
  1992. psychopy/tests/data/TestTarget_w128h64_top_right.png +0 -0
  1993. psychopy/tests/data/TestTarget_w64h128_bottom_left.png +0 -0
  1994. psychopy/tests/data/TestTarget_w64h128_bottom_right.png +0 -0
  1995. psychopy/tests/data/TestTarget_w64h128_center_center.png +0 -0
  1996. psychopy/tests/data/TestTarget_w64h128_top_left.png +0 -0
  1997. psychopy/tests/data/TestTarget_w64h128_top_right.png +0 -0
  1998. psychopy/tests/data/TestTarget_w64h64_bottom_left.png +0 -0
  1999. psychopy/tests/data/TestTarget_w64h64_bottom_right.png +0 -0
  2000. psychopy/tests/data/TestTarget_w64h64_center_center.png +0 -0
  2001. psychopy/tests/data/TestTarget_w64h64_top_left.png +0 -0
  2002. psychopy/tests/data/TestTarget_w64h64_top_right.png +0 -0
  2003. psychopy/tests/data/TestTextbox_testLetterSpacing_0p6.png +0 -0
  2004. psychopy/tests/data/TestTextbox_testLetterSpacing_0p8.png +0 -0
  2005. psychopy/tests/data/TestTextbox_testLetterSpacing_1.png +0 -0
  2006. psychopy/tests/data/TestTextbox_testLetterSpacing_1p2.png +0 -0
  2007. psychopy/tests/data/TestTextbox_testLetterSpacing_1p4.png +0 -0
  2008. psychopy/tests/data/TestTextbox_testLetterSpacing_1p6.png +0 -0
  2009. psychopy/tests/data/TestTextbox_testLetterSpacing_1p8.png +0 -0
  2010. psychopy/tests/data/TestTextbox_testLetterSpacing_2p0.png +0 -0
  2011. psychopy/tests/data/TestTextbox_testLetterSpacing_None.png +0 -0
  2012. psychopy/tests/data/Test_textbox_testSpeechpoint_-3ovr8_0ovr8.png +0 -0
  2013. psychopy/tests/data/Test_textbox_testSpeechpoint_0ovr8_-3ovr8.png +0 -0
  2014. psychopy/tests/data/Test_textbox_testSpeechpoint_0ovr8_3ovr8.png +0 -0
  2015. psychopy/tests/data/Test_textbox_testSpeechpoint_3ovr8_0ovr8.png +0 -0
  2016. psychopy/tests/data/Test_textbox_w128h128_bottom_left.png +0 -0
  2017. psychopy/tests/data/Test_textbox_w128h128_bottom_right.png +0 -0
  2018. psychopy/tests/data/Test_textbox_w128h128_center_center.png +0 -0
  2019. psychopy/tests/data/Test_textbox_w128h128_top_left.png +0 -0
  2020. psychopy/tests/data/Test_textbox_w128h128_top_right.png +0 -0
  2021. psychopy/tests/data/Test_textbox_w128h64_bottom_left.png +0 -0
  2022. psychopy/tests/data/Test_textbox_w128h64_bottom_right.png +0 -0
  2023. psychopy/tests/data/Test_textbox_w128h64_center_center.png +0 -0
  2024. psychopy/tests/data/Test_textbox_w128h64_top_left.png +0 -0
  2025. psychopy/tests/data/Test_textbox_w128h64_top_right.png +0 -0
  2026. psychopy/tests/data/Test_textbox_w64h128_bottom_left.png +0 -0
  2027. psychopy/tests/data/Test_textbox_w64h128_bottom_right.png +0 -0
  2028. psychopy/tests/data/Test_textbox_w64h128_center_center.png +0 -0
  2029. psychopy/tests/data/Test_textbox_w64h128_top_left.png +0 -0
  2030. psychopy/tests/data/Test_textbox_w64h128_top_right.png +0 -0
  2031. psychopy/tests/data/Test_textbox_w64h64_bottom_left.png +0 -0
  2032. psychopy/tests/data/Test_textbox_w64h64_bottom_right.png +0 -0
  2033. psychopy/tests/data/Test_textbox_w64h64_center_center.png +0 -0
  2034. psychopy/tests/data/Test_textbox_w64h64_top_left.png +0 -0
  2035. psychopy/tests/data/Test_textbox_w64h64_top_right.png +0 -0
  2036. psychopy/tests/data/Test_uax14_textbox_w128h128_bottom_left.png +0 -0
  2037. psychopy/tests/data/Test_uax14_textbox_w128h128_bottom_right.png +0 -0
  2038. psychopy/tests/data/Test_uax14_textbox_w128h128_center_center.png +0 -0
  2039. psychopy/tests/data/Test_uax14_textbox_w128h128_top_left.png +0 -0
  2040. psychopy/tests/data/Test_uax14_textbox_w128h128_top_right.png +0 -0
  2041. psychopy/tests/data/Test_uax14_textbox_w128h64_bottom_left.png +0 -0
  2042. psychopy/tests/data/Test_uax14_textbox_w128h64_bottom_right.png +0 -0
  2043. psychopy/tests/data/Test_uax14_textbox_w128h64_center_center.png +0 -0
  2044. psychopy/tests/data/Test_uax14_textbox_w128h64_top_left.png +0 -0
  2045. psychopy/tests/data/Test_uax14_textbox_w128h64_top_right.png +0 -0
  2046. psychopy/tests/data/Test_uax14_textbox_w64h128_bottom_left.png +0 -0
  2047. psychopy/tests/data/Test_uax14_textbox_w64h128_bottom_right.png +0 -0
  2048. psychopy/tests/data/Test_uax14_textbox_w64h128_center_center.png +0 -0
  2049. psychopy/tests/data/Test_uax14_textbox_w64h128_top_left.png +0 -0
  2050. psychopy/tests/data/Test_uax14_textbox_w64h128_top_right.png +0 -0
  2051. psychopy/tests/data/Test_uax14_textbox_w64h64_bottom_left.png +0 -0
  2052. psychopy/tests/data/Test_uax14_textbox_w64h64_bottom_right.png +0 -0
  2053. psychopy/tests/data/Test_uax14_textbox_w64h64_center_center.png +0 -0
  2054. psychopy/tests/data/Test_uax14_textbox_w64h64_top_left.png +0 -0
  2055. psychopy/tests/data/Test_uax14_textbox_w64h64_top_right.png +0 -0
  2056. psychopy/tests/data/TextComponent_disabled.psyexp +63 -0
  2057. psychopy/tests/data/TextComponent_not_disabled.psyexp +63 -0
  2058. psychopy/tests/data/aperture1_deg.png +0 -0
  2059. psychopy/tests/data/aperture1_degFlat.png +0 -0
  2060. psychopy/tests/data/aperture1_degFlatPos.png +0 -0
  2061. psychopy/tests/data/aperture1_norm.png +0 -0
  2062. psychopy/tests/data/aperture1_normHexbackground.png +0 -0
  2063. psychopy/tests/data/aperture1_normNoShade.png +0 -0
  2064. psychopy/tests/data/aperture1_pix.png +0 -0
  2065. psychopy/tests/data/aperture1_stencil.png +0 -0
  2066. psychopy/tests/data/aperture2_deg.png +0 -0
  2067. psychopy/tests/data/aperture2_degFlat.png +0 -0
  2068. psychopy/tests/data/aperture2_degFlatPos.png +0 -0
  2069. psychopy/tests/data/aperture2_norm.png +0 -0
  2070. psychopy/tests/data/aperture2_normHexbackground.png +0 -0
  2071. psychopy/tests/data/aperture2_normNoShade.png +0 -0
  2072. psychopy/tests/data/aperture2_pix.png +0 -0
  2073. psychopy/tests/data/aperture2_stencil.png +0 -0
  2074. psychopy/tests/data/beatandrcos_cm.png +0 -0
  2075. psychopy/tests/data/beatandrcos_deg.png +0 -0
  2076. psychopy/tests/data/beatandrcos_degFlat.png +0 -0
  2077. psychopy/tests/data/beatandrcos_degFlatPos.png +0 -0
  2078. psychopy/tests/data/beatandrcos_height.png +0 -0
  2079. psychopy/tests/data/beatandrcos_norm.png +0 -0
  2080. psychopy/tests/data/beatandrcos_normAddBlend.png +0 -0
  2081. psychopy/tests/data/beatandrcos_normAddBlend_local.png +0 -0
  2082. psychopy/tests/data/beatandrcos_normHexbackground.png +0 -0
  2083. psychopy/tests/data/beatandrcos_normHexbackground_local.png +0 -0
  2084. psychopy/tests/data/beatandrcos_norm_local.png +0 -0
  2085. psychopy/tests/data/beatandrcos_pix.png +0 -0
  2086. psychopy/tests/data/beatandrcos_stencil.png +0 -0
  2087. psychopy/tests/data/blend_add_cm.png +0 -0
  2088. psychopy/tests/data/blend_add_deg.png +0 -0
  2089. psychopy/tests/data/blend_add_degFlat.png +0 -0
  2090. psychopy/tests/data/blend_add_degFlatPos.png +0 -0
  2091. psychopy/tests/data/blend_add_height.png +0 -0
  2092. psychopy/tests/data/blend_add_norm.png +0 -0
  2093. psychopy/tests/data/blend_add_normAddBlend.png +0 -0
  2094. psychopy/tests/data/blend_add_normAddBlend_local.png +0 -0
  2095. psychopy/tests/data/blend_add_normHexbackground.png +0 -0
  2096. psychopy/tests/data/blend_add_normHexbackground_local.png +0 -0
  2097. psychopy/tests/data/blend_add_normNoShade.png +0 -0
  2098. psychopy/tests/data/blend_add_norm_local.png +0 -0
  2099. psychopy/tests/data/blend_add_pix.png +0 -0
  2100. psychopy/tests/data/blend_add_stencil.png +0 -0
  2101. psychopy/tests/data/broken2020_2_5_resources/broken_resources.psyexp +84 -0
  2102. psychopy/tests/data/broken2020_2_5_resources/psychopy72.png +0 -0
  2103. psychopy/tests/data/bufferimg_gabor_cm.png +0 -0
  2104. psychopy/tests/data/bufferimg_gabor_deg.png +0 -0
  2105. psychopy/tests/data/bufferimg_gabor_degFlat.png +0 -0
  2106. psychopy/tests/data/bufferimg_gabor_degFlatPos.png +0 -0
  2107. psychopy/tests/data/bufferimg_gabor_height.png +0 -0
  2108. psychopy/tests/data/bufferimg_gabor_norm.png +0 -0
  2109. psychopy/tests/data/bufferimg_gabor_normAddBlend.png +0 -0
  2110. psychopy/tests/data/bufferimg_gabor_normAddBlend_local.png +0 -0
  2111. psychopy/tests/data/bufferimg_gabor_normHexbackground.png +0 -0
  2112. psychopy/tests/data/bufferimg_gabor_normHexbackground_local.png +0 -0
  2113. psychopy/tests/data/bufferimg_gabor_normNoShade.png +0 -0
  2114. psychopy/tests/data/bufferimg_gabor_norm_local.png +0 -0
  2115. psychopy/tests/data/bufferimg_gabor_pix.png +0 -0
  2116. psychopy/tests/data/bufferimg_gabor_stencil.png +0 -0
  2117. psychopy/tests/data/circleHex_cm.png +0 -0
  2118. psychopy/tests/data/circleHex_deg.png +0 -0
  2119. psychopy/tests/data/circleHex_degFlat.png +0 -0
  2120. psychopy/tests/data/circleHex_degFlatPos.png +0 -0
  2121. psychopy/tests/data/circleHex_height.png +0 -0
  2122. psychopy/tests/data/circleHex_norm.png +0 -0
  2123. psychopy/tests/data/circleHex_normAddBlend.png +0 -0
  2124. psychopy/tests/data/circleHex_normAddBlend_local.png +0 -0
  2125. psychopy/tests/data/circleHex_normHexbackground.png +0 -0
  2126. psychopy/tests/data/circleHex_normHexbackground_local.png +0 -0
  2127. psychopy/tests/data/circleHex_normNoShade.png +0 -0
  2128. psychopy/tests/data/circleHex_norm_local.png +0 -0
  2129. psychopy/tests/data/circleHex_pix.png +0 -0
  2130. psychopy/tests/data/circleHex_stencil.png +0 -0
  2131. psychopy/tests/data/corrFullRandom.csv +16 -0
  2132. psychopy/tests/data/corrFullRandom.tsv +6 -0
  2133. psychopy/tests/data/corrFullRandomTH2.csv +16 -0
  2134. psychopy/tests/data/corrMultiKeyExpWide.csv +3 -0
  2135. psychopy/tests/data/corrMultiKeyTrials.csv +8 -0
  2136. psychopy/tests/data/corrMultiKeyTrials.xlsx +0 -0
  2137. psychopy/tests/data/corrRandom.csv +16 -0
  2138. psychopy/tests/data/corrRandom.tsv +6 -0
  2139. psychopy/tests/data/corrRandomTH2.csv +16 -0
  2140. psychopy/tests/data/corrXlsx.xlsx +0 -0
  2141. psychopy/tests/data/correctScript/js/correctCodeComponent.js +181 -0
  2142. psychopy/tests/data/correctScript/js/correctImageComponent.js +204 -0
  2143. psychopy/tests/data/correctScript/js/correctKeyboardComponent.js +225 -0
  2144. psychopy/tests/data/correctScript/js/correctMouseComponent.js +221 -0
  2145. psychopy/tests/data/correctScript/js/correctMovieComponent.js +210 -0
  2146. psychopy/tests/data/correctScript/js/correctPolygonComponent.js +205 -0
  2147. psychopy/tests/data/correctScript/js/correctSliderComponent.js +209 -0
  2148. psychopy/tests/data/correctScript/js/correctSoundComponent.js +205 -0
  2149. psychopy/tests/data/correctScript/js/correctTextComponent.js +207 -0
  2150. psychopy/tests/data/correctScript/python/correctApertureComponent.py +157 -0
  2151. psychopy/tests/data/correctScript/python/correctCodeComponent.py +135 -0
  2152. psychopy/tests/data/correctScript/python/correctDotsComponent.py +161 -0
  2153. psychopy/tests/data/correctScript/python/correctEnvGratingComponent.py +167 -0
  2154. psychopy/tests/data/correctScript/python/correctFormComponent.py +150 -0
  2155. psychopy/tests/data/correctScript/python/correctGratingComponent.py +158 -0
  2156. psychopy/tests/data/correctScript/python/correctImageComponent.py +160 -0
  2157. psychopy/tests/data/correctScript/python/correctJoyButtonsComponent.py +204 -0
  2158. psychopy/tests/data/correctScript/python/correctJoystickComponent.py +214 -0
  2159. psychopy/tests/data/correctScript/python/correctKeyboardComponent.py +169 -0
  2160. psychopy/tests/data/correctScript/python/correctMicrophoneComponent.py +163 -0
  2161. psychopy/tests/data/correctScript/python/correctMouseComponent.py +174 -0
  2162. psychopy/tests/data/correctScript/python/correctMovieComponent.py +160 -0
  2163. psychopy/tests/data/correctScript/python/correctNoiseStimComponent.py +169 -0
  2164. psychopy/tests/data/correctScript/python/correctParallelOutComponent.py +156 -0
  2165. psychopy/tests/data/correctScript/python/correctPatchComponent.py +159 -0
  2166. psychopy/tests/data/correctScript/python/correctPolygonComponent.py +159 -0
  2167. psychopy/tests/data/correctScript/python/correctQmixPumpComponent.py +174 -0
  2168. psychopy/tests/data/correctScript/python/correctRatingScaleComponent.py +152 -0
  2169. psychopy/tests/data/correctScript/python/correctSliderComponent.py +159 -0
  2170. psychopy/tests/data/correctScript/python/correctSoundComponent.py +157 -0
  2171. psychopy/tests/data/correctScript/python/correctStaticComponent.py +176 -0
  2172. psychopy/tests/data/correctScript/python/correctTextComponent.py +159 -0
  2173. psychopy/tests/data/correctScript/python/correctVariableComponent.py +139 -0
  2174. psychopy/tests/data/correctScript/python/correctcedrusButtonBoxComponent.py +199 -0
  2175. psychopy/tests/data/correctScript/python/correctioLabsButtonBoxComponent.py +187 -0
  2176. psychopy/tests/data/dataTest.xlsx +0 -0
  2177. psychopy/tests/data/dots_cm.png +0 -0
  2178. psychopy/tests/data/dots_deg.png +0 -0
  2179. psychopy/tests/data/dots_degFlat.png +0 -0
  2180. psychopy/tests/data/dots_degFlatPos.png +0 -0
  2181. psychopy/tests/data/dots_height.png +0 -0
  2182. psychopy/tests/data/dots_norm.png +0 -0
  2183. psychopy/tests/data/dots_normAddBlend.png +0 -0
  2184. psychopy/tests/data/dots_normAddBlend_local.png +0 -0
  2185. psychopy/tests/data/dots_normHexbackground.png +0 -0
  2186. psychopy/tests/data/dots_normHexbackground_local.png +0 -0
  2187. psychopy/tests/data/dots_normNoShade.png +0 -0
  2188. psychopy/tests/data/dots_norm_local.png +0 -0
  2189. psychopy/tests/data/dots_pix.png +0 -0
  2190. psychopy/tests/data/dots_stencil.png +0 -0
  2191. psychopy/tests/data/elarray1_cm.png +0 -0
  2192. psychopy/tests/data/elarray1_deg.png +0 -0
  2193. psychopy/tests/data/elarray1_degFlat.png +0 -0
  2194. psychopy/tests/data/elarray1_degFlatPos.png +0 -0
  2195. psychopy/tests/data/elarray1_height.png +0 -0
  2196. psychopy/tests/data/elarray1_norm.png +0 -0
  2197. psychopy/tests/data/elarray1_normAddBlend.png +0 -0
  2198. psychopy/tests/data/elarray1_normAddBlend_local.png +0 -0
  2199. psychopy/tests/data/elarray1_normHexbackground.png +0 -0
  2200. psychopy/tests/data/elarray1_normHexbackground_local.png +0 -0
  2201. psychopy/tests/data/elarray1_norm_local.png +0 -0
  2202. psychopy/tests/data/elarray1_pix.png +0 -0
  2203. psychopy/tests/data/elarray1_stencil.png +0 -0
  2204. psychopy/tests/data/envelopeandrcos_cm.png +0 -0
  2205. psychopy/tests/data/envelopeandrcos_deg.png +0 -0
  2206. psychopy/tests/data/envelopeandrcos_degFlat.png +0 -0
  2207. psychopy/tests/data/envelopeandrcos_degFlatPos.png +0 -0
  2208. psychopy/tests/data/envelopeandrcos_height.png +0 -0
  2209. psychopy/tests/data/envelopeandrcos_norm.png +0 -0
  2210. psychopy/tests/data/envelopeandrcos_normAddBlend.png +0 -0
  2211. psychopy/tests/data/envelopeandrcos_normAddBlend_local.png +0 -0
  2212. psychopy/tests/data/envelopeandrcos_normHexbackground.png +0 -0
  2213. psychopy/tests/data/envelopeandrcos_normHexbackground_local.png +0 -0
  2214. psychopy/tests/data/envelopeandrcos_norm_local.png +0 -0
  2215. psychopy/tests/data/envelopeandrcos_pix.png +0 -0
  2216. psychopy/tests/data/envelopeandrcos_stencil.png +0 -0
  2217. psychopy/tests/data/envelopepowerandrcos_cm.png +0 -0
  2218. psychopy/tests/data/envelopepowerandrcos_deg.png +0 -0
  2219. psychopy/tests/data/envelopepowerandrcos_degFlat.png +0 -0
  2220. psychopy/tests/data/envelopepowerandrcos_degFlatPos.png +0 -0
  2221. psychopy/tests/data/envelopepowerandrcos_height.png +0 -0
  2222. psychopy/tests/data/envelopepowerandrcos_norm.png +0 -0
  2223. psychopy/tests/data/envelopepowerandrcos_normAddBlend.png +0 -0
  2224. psychopy/tests/data/envelopepowerandrcos_normAddBlend_local.png +0 -0
  2225. psychopy/tests/data/envelopepowerandrcos_normHexbackground.png +0 -0
  2226. psychopy/tests/data/envelopepowerandrcos_normHexbackground_local.png +0 -0
  2227. psychopy/tests/data/envelopepowerandrcos_norm_local.png +0 -0
  2228. psychopy/tests/data/envelopepowerandrcos_pix.png +0 -0
  2229. psychopy/tests/data/envelopepowerandrcos_stencil.png +0 -0
  2230. psychopy/tests/data/filltext.png +0 -0
  2231. psychopy/tests/data/form_font_demographics.png +0 -0
  2232. psychopy/tests/data/form_font_demographics.xlsx +0 -0
  2233. psychopy/tests/data/form_font_languages.png +0 -0
  2234. psychopy/tests/data/form_font_languages.xlsx +0 -0
  2235. psychopy/tests/data/form_font_nonstandard.png +0 -0
  2236. psychopy/tests/data/futureParams.psyexp +150 -0
  2237. psychopy/tests/data/gabor1_cm.png +0 -0
  2238. psychopy/tests/data/gabor1_deg.png +0 -0
  2239. psychopy/tests/data/gabor1_degFlat.png +0 -0
  2240. psychopy/tests/data/gabor1_degFlatPos.png +0 -0
  2241. psychopy/tests/data/gabor1_height.png +0 -0
  2242. psychopy/tests/data/gabor1_norm.png +0 -0
  2243. psychopy/tests/data/gabor1_normAddBlend.png +0 -0
  2244. psychopy/tests/data/gabor1_normAddBlend_local.png +0 -0
  2245. psychopy/tests/data/gabor1_normHexbackground.png +0 -0
  2246. psychopy/tests/data/gabor1_normHexbackground_local.png +0 -0
  2247. psychopy/tests/data/gabor1_normNoShade.png +0 -0
  2248. psychopy/tests/data/gabor1_norm_local.png +0 -0
  2249. psychopy/tests/data/gabor1_pix.png +0 -0
  2250. psychopy/tests/data/gabor1_stencil.png +0 -0
  2251. psychopy/tests/data/gabor2_cm.png +0 -0
  2252. psychopy/tests/data/gabor2_deg.png +0 -0
  2253. psychopy/tests/data/gabor2_degFlat.png +0 -0
  2254. psychopy/tests/data/gabor2_degFlatPos.png +0 -0
  2255. psychopy/tests/data/gabor2_height.png +0 -0
  2256. psychopy/tests/data/gabor2_norm.png +0 -0
  2257. psychopy/tests/data/gabor2_normAddBlend.png +0 -0
  2258. psychopy/tests/data/gabor2_normHexbackground.png +0 -0
  2259. psychopy/tests/data/gabor2_normNoShade.png +0 -0
  2260. psychopy/tests/data/gabor2_pix.png +0 -0
  2261. psychopy/tests/data/gabor2_stencil.png +0 -0
  2262. psychopy/tests/data/ghost_stroop.psyexp +131 -0
  2263. psychopy/tests/data/ghost_trialTypes.xlsx +0 -0
  2264. psychopy/tests/data/green_48000.flac.dist +0 -0
  2265. psychopy/tests/data/greyscale.jpg +0 -0
  2266. psychopy/tests/data/greyscale2.png +0 -0
  2267. psychopy/tests/data/greyscale2_cm.png +0 -0
  2268. psychopy/tests/data/greyscale2_deg.png +0 -0
  2269. psychopy/tests/data/greyscale2_degFlat.png +0 -0
  2270. psychopy/tests/data/greyscale2_degFlatPos.png +0 -0
  2271. psychopy/tests/data/greyscale2_height.png +0 -0
  2272. psychopy/tests/data/greyscale2_norm.png +0 -0
  2273. psychopy/tests/data/greyscale2_normAddBlend.png +0 -0
  2274. psychopy/tests/data/greyscale2_normHexbackground.png +0 -0
  2275. psychopy/tests/data/greyscale2_normNoShade.png +0 -0
  2276. psychopy/tests/data/greyscale2_pix.png +0 -0
  2277. psychopy/tests/data/greyscale2_stencil.png +0 -0
  2278. psychopy/tests/data/greyscaleLowContr_cm.png +0 -0
  2279. psychopy/tests/data/greyscaleLowContr_deg.png +0 -0
  2280. psychopy/tests/data/greyscaleLowContr_degFlat.png +0 -0
  2281. psychopy/tests/data/greyscaleLowContr_degFlatPos.png +0 -0
  2282. psychopy/tests/data/greyscaleLowContr_height.png +0 -0
  2283. psychopy/tests/data/greyscaleLowContr_norm.png +0 -0
  2284. psychopy/tests/data/greyscaleLowContr_normAddBlend.png +0 -0
  2285. psychopy/tests/data/greyscaleLowContr_normHexbackground.png +0 -0
  2286. psychopy/tests/data/greyscaleLowContr_normNoShade.png +0 -0
  2287. psychopy/tests/data/greyscaleLowContr_pix.png +0 -0
  2288. psychopy/tests/data/greyscaleLowContr_stencil.png +0 -0
  2289. psychopy/tests/data/greyscale_cm.png +0 -0
  2290. psychopy/tests/data/greyscale_deg.png +0 -0
  2291. psychopy/tests/data/greyscale_degFlat.png +0 -0
  2292. psychopy/tests/data/greyscale_degFlatPos.png +0 -0
  2293. psychopy/tests/data/greyscale_height.png +0 -0
  2294. psychopy/tests/data/greyscale_norm.png +0 -0
  2295. psychopy/tests/data/greyscale_normAddBlend.png +0 -0
  2296. psychopy/tests/data/greyscale_normHexbackground.png +0 -0
  2297. psychopy/tests/data/greyscale_normNoShade.png +0 -0
  2298. psychopy/tests/data/greyscale_pix.png +0 -0
  2299. psychopy/tests/data/greyscale_stencil.png +0 -0
  2300. psychopy/tests/data/imageAndGauss_cm.png +0 -0
  2301. psychopy/tests/data/imageAndGauss_deg.png +0 -0
  2302. psychopy/tests/data/imageAndGauss_degFlat.png +0 -0
  2303. psychopy/tests/data/imageAndGauss_degFlatPos.png +0 -0
  2304. psychopy/tests/data/imageAndGauss_height.png +0 -0
  2305. psychopy/tests/data/imageAndGauss_norm.png +0 -0
  2306. psychopy/tests/data/imageAndGauss_normAddBlend.png +0 -0
  2307. psychopy/tests/data/imageAndGauss_normAddBlend_local.png +0 -0
  2308. psychopy/tests/data/imageAndGauss_normHexbackground.png +0 -0
  2309. psychopy/tests/data/imageAndGauss_normHexbackground_local.png +0 -0
  2310. psychopy/tests/data/imageAndGauss_normNoShade.png +0 -0
  2311. psychopy/tests/data/imageAndGauss_norm_local.png +0 -0
  2312. psychopy/tests/data/imageAndGauss_pix.png +0 -0
  2313. psychopy/tests/data/imageAndGauss_stencil.png +0 -0
  2314. psychopy/tests/data/movFrame1_cm.png +0 -0
  2315. psychopy/tests/data/movFrame1_deg.png +0 -0
  2316. psychopy/tests/data/movFrame1_degFlat.png +0 -0
  2317. psychopy/tests/data/movFrame1_degFlatPos.png +0 -0
  2318. psychopy/tests/data/movFrame1_height.png +0 -0
  2319. psychopy/tests/data/movFrame1_norm.png +0 -0
  2320. psychopy/tests/data/movFrame1_normAddBlend.png +0 -0
  2321. psychopy/tests/data/movFrame1_normHexbackground.png +0 -0
  2322. psychopy/tests/data/movFrame1_normNoShade.png +0 -0
  2323. psychopy/tests/data/movFrame1_pix.png +0 -0
  2324. psychopy/tests/data/movFrame1_stencil.png +0 -0
  2325. psychopy/tests/data/multiKeypressExperiment.psydat +357 -0
  2326. psychopy/tests/data/multiKeypressTrialhandler.psydat +252 -0
  2327. psychopy/tests/data/multiStairConds.xlsx +0 -0
  2328. psychopy/tests/data/multiStairQuestPlus.xlsx +0 -0
  2329. psychopy/tests/data/newstyle.psydat +6155 -0
  2330. psychopy/tests/data/noiseAndRcos_cm.png +0 -0
  2331. psychopy/tests/data/noiseAndRcos_deg.png +0 -0
  2332. psychopy/tests/data/noiseAndRcos_degFlat.png +0 -0
  2333. psychopy/tests/data/noiseAndRcos_degFlatPos.png +0 -0
  2334. psychopy/tests/data/noiseAndRcos_height.png +0 -0
  2335. psychopy/tests/data/noiseAndRcos_norm.png +0 -0
  2336. psychopy/tests/data/noiseAndRcos_normAddBlend.png +0 -0
  2337. psychopy/tests/data/noiseAndRcos_normAddBlend_local.png +0 -0
  2338. psychopy/tests/data/noiseAndRcos_normHexbackground.png +0 -0
  2339. psychopy/tests/data/noiseAndRcos_normHexbackground_local.png +0 -0
  2340. psychopy/tests/data/noiseAndRcos_normNoShade.png +0 -0
  2341. psychopy/tests/data/noiseAndRcos_norm_local.png +0 -0
  2342. psychopy/tests/data/noiseAndRcos_pix.png +0 -0
  2343. psychopy/tests/data/noiseAndRcos_stencil.png +0 -0
  2344. psychopy/tests/data/noiseFiltersAndRcos_cm.png +0 -0
  2345. psychopy/tests/data/noiseFiltersAndRcos_deg.png +0 -0
  2346. psychopy/tests/data/noiseFiltersAndRcos_degFlat.png +0 -0
  2347. psychopy/tests/data/noiseFiltersAndRcos_degFlatPos.png +0 -0
  2348. psychopy/tests/data/noiseFiltersAndRcos_height.png +0 -0
  2349. psychopy/tests/data/noiseFiltersAndRcos_norm.png +0 -0
  2350. psychopy/tests/data/noiseFiltersAndRcos_normAddBlend.png +0 -0
  2351. psychopy/tests/data/noiseFiltersAndRcos_normAddBlend_local.png +0 -0
  2352. psychopy/tests/data/noiseFiltersAndRcos_normHexbackground.png +0 -0
  2353. psychopy/tests/data/noiseFiltersAndRcos_normHexbackground_local.png +0 -0
  2354. psychopy/tests/data/noiseFiltersAndRcos_normNoShade.png +0 -0
  2355. psychopy/tests/data/noiseFiltersAndRcos_norm_local.png +0 -0
  2356. psychopy/tests/data/noiseFiltersAndRcos_pix.png +0 -0
  2357. psychopy/tests/data/noiseFiltersAndRcos_stencil.png +0 -0
  2358. psychopy/tests/data/numpyImage_cm.png +0 -0
  2359. psychopy/tests/data/numpyImage_deg.png +0 -0
  2360. psychopy/tests/data/numpyImage_degFlat.png +0 -0
  2361. psychopy/tests/data/numpyImage_degFlatPos.png +0 -0
  2362. psychopy/tests/data/numpyImage_height.png +0 -0
  2363. psychopy/tests/data/numpyImage_norm.png +0 -0
  2364. psychopy/tests/data/numpyImage_normAddBlend.png +0 -0
  2365. psychopy/tests/data/numpyImage_normAddBlend_local.png +0 -0
  2366. psychopy/tests/data/numpyImage_normHexbackground.png +0 -0
  2367. psychopy/tests/data/numpyImage_normHexbackground_local.png +0 -0
  2368. psychopy/tests/data/numpyImage_normNoShade.png +0 -0
  2369. psychopy/tests/data/numpyImage_norm_local.png +0 -0
  2370. psychopy/tests/data/numpyImage_pix.png +0 -0
  2371. psychopy/tests/data/numpyImage_stencil.png +0 -0
  2372. psychopy/tests/data/numpyLowContr_cm.png +0 -0
  2373. psychopy/tests/data/numpyLowContr_deg.png +0 -0
  2374. psychopy/tests/data/numpyLowContr_degFlat.png +0 -0
  2375. psychopy/tests/data/numpyLowContr_degFlatPos.png +0 -0
  2376. psychopy/tests/data/numpyLowContr_height.png +0 -0
  2377. psychopy/tests/data/numpyLowContr_norm.png +0 -0
  2378. psychopy/tests/data/numpyLowContr_normAddBlend.png +0 -0
  2379. psychopy/tests/data/numpyLowContr_normHexbackground.png +0 -0
  2380. psychopy/tests/data/numpyLowContr_normNoShade.png +0 -0
  2381. psychopy/tests/data/numpyLowContr_pix.png +0 -0
  2382. psychopy/tests/data/numpyLowContr_stencil.png +0 -0
  2383. psychopy/tests/data/oldstyle.psydat +1534 -0
  2384. psychopy/tests/data/oldstyle_stair.psydat +263 -0
  2385. psychopy/tests/data/ratingscale1_cm.png +0 -0
  2386. psychopy/tests/data/ratingscale1_deg.png +0 -0
  2387. psychopy/tests/data/ratingscale1_degFlat.png +0 -0
  2388. psychopy/tests/data/ratingscale1_degFlatPos.png +0 -0
  2389. psychopy/tests/data/ratingscale1_height.png +0 -0
  2390. psychopy/tests/data/ratingscale1_norm.png +0 -0
  2391. psychopy/tests/data/ratingscale1_normAddBlend.png +0 -0
  2392. psychopy/tests/data/ratingscale1_normHexbackground.png +0 -0
  2393. psychopy/tests/data/ratingscale1_normNoShade.png +0 -0
  2394. psychopy/tests/data/ratingscale1_pix.png +0 -0
  2395. psychopy/tests/data/ratingscale1_stencil.png +0 -0
  2396. psychopy/tests/data/red_16000.flac.dist +0 -0
  2397. psychopy/tests/data/retroListParam.psyexp +82 -0
  2398. psychopy/tests/data/right_to_left_unidcode.xlsx +0 -0
  2399. psychopy/tests/data/sample.meshwarp.data +11522 -0
  2400. psychopy/tests/data/shape2_1_cm.png +0 -0
  2401. psychopy/tests/data/shape2_1_deg.png +0 -0
  2402. psychopy/tests/data/shape2_1_degFlat.png +0 -0
  2403. psychopy/tests/data/shape2_1_degFlatPos.png +0 -0
  2404. psychopy/tests/data/shape2_1_height.png +0 -0
  2405. psychopy/tests/data/shape2_1_norm.png +0 -0
  2406. psychopy/tests/data/shape2_1_normAddBlend.png +0 -0
  2407. psychopy/tests/data/shape2_1_normAddBlend_local.png +0 -0
  2408. psychopy/tests/data/shape2_1_normHexbackground.png +0 -0
  2409. psychopy/tests/data/shape2_1_normNoShade.png +0 -0
  2410. psychopy/tests/data/shape2_1_norm_local.png +0 -0
  2411. psychopy/tests/data/shape2_1_pix.png +0 -0
  2412. psychopy/tests/data/shape2_1_stencil.png +0 -0
  2413. psychopy/tests/data/shape2_2_cm.png +0 -0
  2414. psychopy/tests/data/shape2_2_deg.png +0 -0
  2415. psychopy/tests/data/shape2_2_degFlat.png +0 -0
  2416. psychopy/tests/data/shape2_2_degFlatPos.png +0 -0
  2417. psychopy/tests/data/shape2_2_height.png +0 -0
  2418. psychopy/tests/data/shape2_2_norm.png +0 -0
  2419. psychopy/tests/data/shape2_2_normAddBlend.png +0 -0
  2420. psychopy/tests/data/shape2_2_normHexbackground.png +0 -0
  2421. psychopy/tests/data/shape2_2_normNoShade.png +0 -0
  2422. psychopy/tests/data/shape2_2_pix.png +0 -0
  2423. psychopy/tests/data/shape2_2_stencil.png +0 -0
  2424. psychopy/tests/data/simpleimage1_cm.png +0 -0
  2425. psychopy/tests/data/simpleimage1_deg.png +0 -0
  2426. psychopy/tests/data/simpleimage1_degFlat.png +0 -0
  2427. psychopy/tests/data/simpleimage1_degFlatPos.png +0 -0
  2428. psychopy/tests/data/simpleimage1_height.png +0 -0
  2429. psychopy/tests/data/simpleimage1_norm.png +0 -0
  2430. psychopy/tests/data/simpleimage1_normAddBlend.png +0 -0
  2431. psychopy/tests/data/simpleimage1_normHexbackground.png +0 -0
  2432. psychopy/tests/data/simpleimage1_normNoShade.png +0 -0
  2433. psychopy/tests/data/simpleimage1_pix.png +0 -0
  2434. psychopy/tests/data/simpleimage1_stencil.png +0 -0
  2435. psychopy/tests/data/test001EntryImporting.psyexp +66 -0
  2436. psychopy/tests/data/testMovie.mp4 +0 -0
  2437. psychopy/tests/data/test_circle_radius_.1height.png +0 -0
  2438. psychopy/tests/data/test_circle_radius_.2height.png +0 -0
  2439. psychopy/tests/data/test_circle_radius_10pix.png +0 -0
  2440. psychopy/tests/data/test_circle_radius_20pix.png +0 -0
  2441. psychopy/tests/data/test_form_combinations_choice_bigItem.png +0 -0
  2442. psychopy/tests/data/test_form_combinations_choice_bigItemOverflow.png +0 -0
  2443. psychopy/tests/data/test_form_combinations_choice_bigResp.png +0 -0
  2444. psychopy/tests/data/test_form_combinations_choice_bigRespOverflow.png +0 -0
  2445. psychopy/tests/data/test_form_combinations_description_bigItem.png +0 -0
  2446. psychopy/tests/data/test_form_combinations_description_bigItemOverflow.png +0 -0
  2447. psychopy/tests/data/test_form_combinations_description_bigResp.png +0 -0
  2448. psychopy/tests/data/test_form_combinations_description_bigRespOverflow.png +0 -0
  2449. psychopy/tests/data/test_form_combinations_free text_bigItem.png +0 -0
  2450. psychopy/tests/data/test_form_combinations_free text_bigItemOverflow.png +0 -0
  2451. psychopy/tests/data/test_form_combinations_free text_bigResp.png +0 -0
  2452. psychopy/tests/data/test_form_combinations_free text_bigRespOverflow.png +0 -0
  2453. psychopy/tests/data/test_form_combinations_heading_bigItem.png +0 -0
  2454. psychopy/tests/data/test_form_combinations_heading_bigItemOverflow.png +0 -0
  2455. psychopy/tests/data/test_form_combinations_heading_bigResp.png +0 -0
  2456. psychopy/tests/data/test_form_combinations_heading_bigRespOverflow.png +0 -0
  2457. psychopy/tests/data/test_form_combinations_radio_bigItem.png +0 -0
  2458. psychopy/tests/data/test_form_combinations_radio_bigItemOverflow.png +0 -0
  2459. psychopy/tests/data/test_form_combinations_radio_bigResp.png +0 -0
  2460. psychopy/tests/data/test_form_combinations_radio_bigRespOverflow.png +0 -0
  2461. psychopy/tests/data/test_form_combinations_rating_bigItem.png +0 -0
  2462. psychopy/tests/data/test_form_combinations_rating_bigItemOverflow.png +0 -0
  2463. psychopy/tests/data/test_form_combinations_rating_bigResp.png +0 -0
  2464. psychopy/tests/data/test_form_combinations_rating_bigRespOverflow.png +0 -0
  2465. psychopy/tests/data/test_form_combinations_slider_bigItem.png +0 -0
  2466. psychopy/tests/data/test_form_combinations_slider_bigItemOverflow.png +0 -0
  2467. psychopy/tests/data/test_form_combinations_slider_bigResp.png +0 -0
  2468. psychopy/tests/data/test_form_combinations_slider_bigRespOverflow.png +0 -0
  2469. psychopy/tests/data/test_get_resources/blue.png +0 -0
  2470. psychopy/tests/data/test_get_resources/groupA.csv +3 -0
  2471. psychopy/tests/data/test_get_resources/groupB.csv +3 -0
  2472. psychopy/tests/data/test_get_resources/groups.csv +3 -0
  2473. psychopy/tests/data/test_get_resources/handledbyrm_constrloop.psyexp +143 -0
  2474. psychopy/tests/data/test_get_resources/handledbyrm_noloop.psyexp +114 -0
  2475. psychopy/tests/data/test_get_resources/handledbyrm_recurloop.psyexp +138 -0
  2476. psychopy/tests/data/test_get_resources/handledbyrm_strloop.psyexp +126 -0
  2477. psychopy/tests/data/test_get_resources/handledbystatic_constrloop.psyexp +141 -0
  2478. psychopy/tests/data/test_get_resources/handledbystatic_noloop.psyexp +112 -0
  2479. psychopy/tests/data/test_get_resources/handledbystatic_recurloop.psyexp +136 -0
  2480. psychopy/tests/data/test_get_resources/handledbystatic_strloop.psyexp +124 -0
  2481. psychopy/tests/data/test_get_resources/unhandled_constrloop.psyexp +128 -0
  2482. psychopy/tests/data/test_get_resources/unhandled_noloop.psyexp +99 -0
  2483. psychopy/tests/data/test_get_resources/unhandled_recurloop.psyexp +123 -0
  2484. psychopy/tests/data/test_get_resources/unhandled_strloop.psyexp +111 -0
  2485. psychopy/tests/data/test_get_resources/white.png +0 -0
  2486. psychopy/tests/data/test_get_resources/yellow.png +0 -0
  2487. psychopy/tests/data/test_image_aspect_default_None.png +0 -0
  2488. psychopy/tests/data/test_image_aspect_default_xFull_yNone.png +0 -0
  2489. psychopy/tests/data/test_image_aspect_default_xNone_yFull.png +0 -0
  2490. psychopy/tests/data/test_image_aspect_default_xNone_yNone.png +0 -0
  2491. psychopy/tests/data/test_image_flip_anchor_horiz.png +0 -0
  2492. psychopy/tests/data/test_image_flip_anchor_vert.png +0 -0
  2493. psychopy/tests/data/test_loops/testLoopsBlocks.psyexp +161 -0
  2494. psychopy/tests/data/test_loops/testStaircase.psyexp +105 -0
  2495. psychopy/tests/data/test_loops/test_current_loop_attr.psyexp +185 -0
  2496. psychopy/tests/data/test_panorama/panoramaTestImage.png +0 -0
  2497. psychopy/tests/data/test_panorama/panoramaTestImage.svg +1 -0
  2498. psychopy/tests/data/test_panorama/testPanorama_mvmt_-0.3_-0.3.png +0 -0
  2499. psychopy/tests/data/test_panorama/testPanorama_mvmt_-0.3_0.3.png +0 -0
  2500. psychopy/tests/data/test_panorama/testPanorama_mvmt_-1.0_-0.3.png +0 -0
  2501. psychopy/tests/data/test_panorama/testPanorama_mvmt_-1.0_0.3.png +0 -0
  2502. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.0_-1.0.png +0 -0
  2503. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.0_1.0.png +0 -0
  2504. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.3_-0.3.png +0 -0
  2505. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.3_0.3.png +0 -0
  2506. psychopy/tests/data/test_resources.psyexp +491 -0
  2507. psychopy/tests/data/test_session/outside_root/externalExp.psyexp +116 -0
  2508. psychopy/tests/data/test_session/root/annotation/annotation.psyexp +161 -0
  2509. psychopy/tests/data/test_session/root/error/error.psyexp +93 -0
  2510. psychopy/tests/data/test_session/root/exp1/exp1.psyexp +133 -0
  2511. psychopy/tests/data/test_session/root/exp2/exp2.psyexp +133 -0
  2512. psychopy/tests/data/test_session/root/frameRate/frameRate.psyexp +114 -0
  2513. psychopy/tests/data/test_session/root/invUseVersion/invUseVersion.psyexp +133 -0
  2514. psychopy/tests/data/test_session/root/testClockFormat/testClockFormat.psyexp +122 -0
  2515. psychopy/tests/data/test_session/root/testCtrls/testCtrls.psyexp +115 -0
  2516. psychopy/tests/data/test_session/root/testEditExpInfo/testEditExpInfo.psyexp +135 -0
  2517. psychopy/tests/data/test_session/root/testNamedButtonBox/testNamedButtonBox.psyexp +145 -0
  2518. psychopy/tests/data/test_slider_horiz_accute_horiz.png +0 -0
  2519. psychopy/tests/data/test_slider_horiz_accute_vert.png +0 -0
  2520. psychopy/tests/data/test_slider_horiz_horiz.png +0 -0
  2521. psychopy/tests/data/test_slider_horiz_obtuse_horiz.png +0 -0
  2522. psychopy/tests/data/test_slider_horiz_obtuse_vert.png +0 -0
  2523. psychopy/tests/data/test_slider_horiz_vert.png +0 -0
  2524. psychopy/tests/data/test_slider_ticklabelloc_blanks.png +0 -0
  2525. psychopy/tests/data/test_slider_ticklabelloc_clustered.png +0 -0
  2526. psychopy/tests/data/test_slider_ticklabelloc_morelabels.png +0 -0
  2527. psychopy/tests/data/test_slider_ticklabelloc_morelabelsclustered.png +0 -0
  2528. psychopy/tests/data/test_slider_ticklabelloc_moreticks.png +0 -0
  2529. psychopy/tests/data/test_slider_ticklabelloc_moreticksclustered.png +0 -0
  2530. psychopy/tests/data/test_slider_ticklabelloc_nolabels.png +0 -0
  2531. psychopy/tests/data/test_slider_ticklabelloc_noticks.png +0 -0
  2532. psychopy/tests/data/test_slider_ticklabelloc_simple.png +0 -0
  2533. psychopy/tests/data/test_slider_triangle_horiz_False_flip_False.png +0 -0
  2534. psychopy/tests/data/test_slider_triangle_horiz_False_flip_True.png +0 -0
  2535. psychopy/tests/data/test_slider_triangle_horiz_True_flip_False.png +0 -0
  2536. psychopy/tests/data/test_slider_triangle_horiz_True_flip_True.png +0 -0
  2537. psychopy/tests/data/test_static_component_script.psyexp +76 -0
  2538. psychopy/tests/data/test_win_bg_large_256_default.png +0 -0
  2539. psychopy/tests/data/test_win_bg_large_500_default.png +0 -0
  2540. psychopy/tests/data/test_win_bg_small_200_default.png +0 -0
  2541. psychopy/tests/data/test_win_bg_small_256_default.png +0 -0
  2542. psychopy/tests/data/test_win_bg_tall_200_default.png +0 -0
  2543. psychopy/tests/data/test_win_bg_tall_256_default.png +0 -0
  2544. psychopy/tests/data/test_win_bg_tall_500_default.png +0 -0
  2545. psychopy/tests/data/test_win_bg_tall_fill_default.png +0 -0
  2546. psychopy/tests/data/test_win_bg_wide_200_default.png +0 -0
  2547. psychopy/tests/data/test_win_bg_wide_256_default.png +0 -0
  2548. psychopy/tests/data/test_win_bg_wide_500_default.png +0 -0
  2549. psychopy/tests/data/test_win_bg_wide_fill_default.png +0 -0
  2550. psychopy/tests/data/test_win_bgcolor_blue.png +0 -0
  2551. psychopy/tests/data/test_win_bgcolor_green.png +0 -0
  2552. psychopy/tests/data/test_win_bgcolor_red.png +0 -0
  2553. psychopy/tests/data/testimage.jpg +0 -0
  2554. psychopy/tests/data/testimagegray.jpg +0 -0
  2555. psychopy/tests/data/testpixels.png +0 -0
  2556. psychopy/tests/data/testwedges.png +0 -0
  2557. psychopy/tests/data/text1_cm.png +0 -0
  2558. psychopy/tests/data/text1_deg.png +0 -0
  2559. psychopy/tests/data/text1_degFlat.png +0 -0
  2560. psychopy/tests/data/text1_degFlatPos.png +0 -0
  2561. psychopy/tests/data/text1_height.png +0 -0
  2562. psychopy/tests/data/text1_norm.png +0 -0
  2563. psychopy/tests/data/text1_normAddBlend.png +0 -0
  2564. psychopy/tests/data/text1_normAddBlend_local.png +0 -0
  2565. psychopy/tests/data/text1_normHexbackground.png +0 -0
  2566. psychopy/tests/data/text1_normHexbackground_local.png +0 -0
  2567. psychopy/tests/data/text1_normNoShade.png +0 -0
  2568. psychopy/tests/data/text1_norm_local.png +0 -0
  2569. psychopy/tests/data/text1_pix.png +0 -0
  2570. psychopy/tests/data/text1_stencil.png +0 -0
  2571. psychopy/tests/data/text2_cm.png +0 -0
  2572. psychopy/tests/data/text2_deg.png +0 -0
  2573. psychopy/tests/data/text2_degFlat.png +0 -0
  2574. psychopy/tests/data/text2_degFlatPos.png +0 -0
  2575. psychopy/tests/data/text2_height.png +0 -0
  2576. psychopy/tests/data/text2_norm.png +0 -0
  2577. psychopy/tests/data/text2_normNoShade.png +0 -0
  2578. psychopy/tests/data/text2_pix.png +0 -0
  2579. psychopy/tests/data/text2_stencil.png +0 -0
  2580. psychopy/tests/data/textbox_charcolors_default_roygbiv.png +0 -0
  2581. psychopy/tests/data/textbox_charcolors_default_white_hello_black_there.png +0 -0
  2582. psychopy/tests/data/textbox_default_align_bottom_center.png +0 -0
  2583. psychopy/tests/data/textbox_default_align_bottom_left.png +0 -0
  2584. psychopy/tests/data/textbox_default_align_bottom_right.png +0 -0
  2585. psychopy/tests/data/textbox_default_align_center.png +0 -0
  2586. psychopy/tests/data/textbox_default_align_center_center.png +0 -0
  2587. psychopy/tests/data/textbox_default_align_center_left.png +0 -0
  2588. psychopy/tests/data/textbox_default_align_center_right.png +0 -0
  2589. psychopy/tests/data/textbox_default_align_centre.png +0 -0
  2590. psychopy/tests/data/textbox_default_align_centre_centre.png +0 -0
  2591. psychopy/tests/data/textbox_default_align_more_than_two_words.png +0 -0
  2592. psychopy/tests/data/textbox_default_align_someword.png +0 -0
  2593. psychopy/tests/data/textbox_default_align_top_center.png +0 -0
  2594. psychopy/tests/data/textbox_default_align_top_left.png +0 -0
  2595. psychopy/tests/data/textbox_default_align_top_right.png +0 -0
  2596. psychopy/tests/data/textbox_default_colors_WOB.png +0 -0
  2597. psychopy/tests/data/textbox_default_colors_exemplar1.png +0 -0
  2598. psychopy/tests/data/textbox_default_colors_exemplar2.png +0 -0
  2599. psychopy/tests/data/textbox_default_colors_exemplar3.png +0 -0
  2600. psychopy/tests/data/textbox_default_colors_tyke1.png +0 -0
  2601. psychopy/tests/data/textbox_default_colors_tyke2.png +0 -0
  2602. psychopy/tests/data/textbox_default_colors_tyke3.png +0 -0
  2603. psychopy/tests/data/textbox_default_cutoff_top.png +0 -0
  2604. psychopy/tests/data/textbox_default_exemplar_1.png +0 -0
  2605. psychopy/tests/data/textbox_default_exemplar_2.png +0 -0
  2606. psychopy/tests/data/textbox_default_exemplar_3.png +0 -0
  2607. psychopy/tests/data/textbox_default_exemplar_4.png +0 -0
  2608. psychopy/tests/data/textbox_default_tyke_1.png +0 -0
  2609. psychopy/tests/data/textbox_default_tyke_2.png +0 -0
  2610. psychopy/tests/data/textbox_typing_blank.png +0 -0
  2611. psychopy/tests/data/textbox_typing_longKoeran.png +0 -0
  2612. psychopy/tests/data/textbox_typing_longWord.png +0 -0
  2613. psychopy/tests/data/textbox_typing_navDel.png +0 -0
  2614. psychopy/tests/data/textbox_typing_navLR.png +0 -0
  2615. psychopy/tests/data/textbox_typing_newline.png +0 -0
  2616. psychopy/tests/data/textbox_typing_pangram.png +0 -0
  2617. psychopy/tests/data/textbox_uax14_align_bottom_center.png +0 -0
  2618. psychopy/tests/data/textbox_uax14_align_bottom_left.png +0 -0
  2619. psychopy/tests/data/textbox_uax14_align_bottom_right.png +0 -0
  2620. psychopy/tests/data/textbox_uax14_align_center.png +0 -0
  2621. psychopy/tests/data/textbox_uax14_align_center_center.png +0 -0
  2622. psychopy/tests/data/textbox_uax14_align_center_left.png +0 -0
  2623. psychopy/tests/data/textbox_uax14_align_center_right.png +0 -0
  2624. psychopy/tests/data/textbox_uax14_align_centre.png +0 -0
  2625. psychopy/tests/data/textbox_uax14_align_centre_centre.png +0 -0
  2626. psychopy/tests/data/textbox_uax14_align_more_than_two_words.png +0 -0
  2627. psychopy/tests/data/textbox_uax14_align_someword.png +0 -0
  2628. psychopy/tests/data/textbox_uax14_align_top_center.png +0 -0
  2629. psychopy/tests/data/textbox_uax14_align_top_left.png +0 -0
  2630. psychopy/tests/data/textbox_uax14_align_top_right.png +0 -0
  2631. psychopy/tests/data/textbox_uax14_colors_WOB.png +0 -0
  2632. psychopy/tests/data/textbox_uax14_colors_exemplar1.png +0 -0
  2633. psychopy/tests/data/textbox_uax14_colors_exemplar2.png +0 -0
  2634. psychopy/tests/data/textbox_uax14_colors_exemplar3.png +0 -0
  2635. psychopy/tests/data/textbox_uax14_colors_tyke1.png +0 -0
  2636. psychopy/tests/data/textbox_uax14_colors_tyke2.png +0 -0
  2637. psychopy/tests/data/textbox_uax14_colors_tyke3.png +0 -0
  2638. psychopy/tests/data/textbox_uax14_cutoff_top.png +0 -0
  2639. psychopy/tests/data/textbox_uax14_exemplar_1.png +0 -0
  2640. psychopy/tests/data/textbox_uax14_exemplar_2.png +0 -0
  2641. psychopy/tests/data/textbox_uax14_exemplar_3.png +0 -0
  2642. psychopy/tests/data/textbox_uax14_exemplar_4.png +0 -0
  2643. psychopy/tests/data/textbox_uax14_tyke_1.png +0 -0
  2644. psychopy/tests/data/textbox_uax14_tyke_2.png +0 -0
  2645. psychopy/tests/data/trialTypes.csv +1 -0
  2646. psychopy/tests/data/trialTypes.docx +0 -0
  2647. psychopy/tests/data/trialTypes.pkl +0 -0
  2648. psychopy/tests/data/trialTypes.tsv +7 -0
  2649. psychopy/tests/data/trialTypes.xls +0 -0
  2650. psychopy/tests/data/trialTypes.xlsx +0 -0
  2651. psychopy/tests/data/trialTypes_eu.csv +7 -0
  2652. psychopy/tests/data/trialsBlankCols.xlsx +0 -0
  2653. psychopy/tests/data/wedge1_cm.png +0 -0
  2654. psychopy/tests/data/wedge1_deg.png +0 -0
  2655. psychopy/tests/data/wedge1_degFlat.png +0 -0
  2656. psychopy/tests/data/wedge1_degFlatPos.png +0 -0
  2657. psychopy/tests/data/wedge1_height.png +0 -0
  2658. psychopy/tests/data/wedge1_norm.png +0 -0
  2659. psychopy/tests/data/wedge1_normAddBlend.png +0 -0
  2660. psychopy/tests/data/wedge1_normAddBlend_local.png +0 -0
  2661. psychopy/tests/data/wedge1_normHexbackground.png +0 -0
  2662. psychopy/tests/data/wedge1_normHexbackground_local.png +0 -0
  2663. psychopy/tests/data/wedge1_normNoShade.png +0 -0
  2664. psychopy/tests/data/wedge1_norm_local.png +0 -0
  2665. psychopy/tests/data/wedge1_pix.png +0 -0
  2666. psychopy/tests/data/wedge1_stencil.png +0 -0
  2667. psychopy/tests/data/wedge2_cm.png +0 -0
  2668. psychopy/tests/data/wedge2_deg.png +0 -0
  2669. psychopy/tests/data/wedge2_degFlat.png +0 -0
  2670. psychopy/tests/data/wedge2_degFlatPos.png +0 -0
  2671. psychopy/tests/data/wedge2_height.png +0 -0
  2672. psychopy/tests/data/wedge2_norm.png +0 -0
  2673. psychopy/tests/data/wedge2_normAddBlend.png +0 -0
  2674. psychopy/tests/data/wedge2_normHexbackground.png +0 -0
  2675. psychopy/tests/data/wedge2_normNoShade.png +0 -0
  2676. psychopy/tests/data/wedge2_pix.png +0 -0
  2677. psychopy/tests/data/wedge2_stencil.png +0 -0
  2678. psychopy/tests/data/winScalePos_ori0_scale-1_-1_pos-0.4_0.png +0 -0
  2679. psychopy/tests/data/winScalePos_ori0_scale-1_-1_pos0_0.png +0 -0
  2680. psychopy/tests/data/winScalePos_ori0_scale-1_1_pos-0.4_0.png +0 -0
  2681. psychopy/tests/data/winScalePos_ori0_scale-1_1_pos0_0.png +0 -0
  2682. psychopy/tests/data/winScalePos_ori0_scale-2_-2_pos-0.4_0.png +0 -0
  2683. psychopy/tests/data/winScalePos_ori0_scale-2_-2_pos0_0.png +0 -0
  2684. psychopy/tests/data/winScalePos_ori0_scale-2_2_pos-0.4_0.png +0 -0
  2685. psychopy/tests/data/winScalePos_ori0_scale-2_2_pos0_0.png +0 -0
  2686. psychopy/tests/data/winScalePos_ori0_scale1_-1_pos-0.4_0.png +0 -0
  2687. psychopy/tests/data/winScalePos_ori0_scale1_-1_pos0_0.png +0 -0
  2688. psychopy/tests/data/winScalePos_ori0_scale1_1_pos-0.4_0.png +0 -0
  2689. psychopy/tests/data/winScalePos_ori0_scale1_1_pos0_0.png +0 -0
  2690. psychopy/tests/data/winScalePos_ori0_scale2_-2_pos-0.4_0.png +0 -0
  2691. psychopy/tests/data/winScalePos_ori0_scale2_-2_pos0_0.png +0 -0
  2692. psychopy/tests/data/winScalePos_ori0_scale2_2_pos-0.4_0.png +0 -0
  2693. psychopy/tests/data/winScalePos_ori0_scale2_2_pos0_0.png +0 -0
  2694. psychopy/tests/data/winScalePos_ori45_scale-1_-1_pos0_0.png +0 -0
  2695. psychopy/tests/data/winScalePos_ori45_scale-1_1_pos0_0.png +0 -0
  2696. psychopy/tests/data/winScalePos_ori45_scale-2_-2_pos0_0.png +0 -0
  2697. psychopy/tests/data/winScalePos_ori45_scale-2_2_pos0_0.png +0 -0
  2698. psychopy/tests/data/winScalePos_ori45_scale1_-1_pos0_0.png +0 -0
  2699. psychopy/tests/data/winScalePos_ori45_scale1_1_pos0_0.png +0 -0
  2700. psychopy/tests/data/winScalePos_ori45_scale2_-2_pos0_0.png +0 -0
  2701. psychopy/tests/data/winScalePos_ori45_scale2_2_pos0_0.png +0 -0
  2702. psychopy/tests/doc/run_btn.png +0 -0
  2703. psychopy/tests/doc/test-suite-bugs.jpg +0 -0
  2704. psychopy/tests/doc/user-bugs.jpg +0 -0
  2705. psychopy/tests/dummy_xorg.conf +21 -0
  2706. psychopy/tests/run.py +50 -0
  2707. psychopy/tests/test_Installation.py +38 -0
  2708. psychopy/tests/test_alerts/test_alerts.py +37 -0
  2709. psychopy/tests/test_alerts/test_alerttools.py +131 -0
  2710. psychopy/tests/test_app/__init__.py +0 -0
  2711. psychopy/tests/test_app/conftest.py +41 -0
  2712. psychopy/tests/test_app/test_builder/__init__.py +0 -0
  2713. psychopy/tests/test_app/test_builder/test_BuilderFrame.py +151 -0
  2714. psychopy/tests/test_app/test_builder/test_CompileFromBuilder.py +135 -0
  2715. psychopy/tests/test_app/test_builder/test_ComponentDialogs.py +98 -0
  2716. psychopy/tests/test_app/test_runner/__init__.py +0 -0
  2717. psychopy/tests/test_app/test_runner/test_RunnerFrame.py +166 -0
  2718. psychopy/tests/test_app/test_speed.py +144 -0
  2719. psychopy/tests/test_app/test_themes/test_icons.py +79 -0
  2720. psychopy/tests/test_codecov.py +29 -0
  2721. psychopy/tests/test_colors/test_Color.py +41 -0
  2722. psychopy/tests/test_data/dataPrev.xlsx +0 -0
  2723. psychopy/tests/test_data/test_ExperimentHandler.py +171 -0
  2724. psychopy/tests/test_data/test_MultiStairHandler.py +174 -0
  2725. psychopy/tests/test_data/test_StairHandlers.py +1241 -0
  2726. psychopy/tests/test_data/test_TrialHandler.py +335 -0
  2727. psychopy/tests/test_data/test_TrialHandler2.py +408 -0
  2728. psychopy/tests/test_data/test_TrialHandlerExt.py +359 -0
  2729. psychopy/tests/test_data/test_fitFunctions.py +101 -0
  2730. psychopy/tests/test_data/test_utils.py +169 -0
  2731. psychopy/tests/test_data/test_xlsx.py +92 -0
  2732. psychopy/tests/test_demos/test_builder_demos.py +52 -0
  2733. psychopy/tests/test_experiment/__init__.py +0 -0
  2734. psychopy/tests/test_experiment/known_py_diffs.txt +47 -0
  2735. psychopy/tests/test_experiment/needs_wx/__init__.py +0 -0
  2736. psychopy/tests/test_experiment/needs_wx/componsTemplate.txt +13730 -0
  2737. psychopy/tests/test_experiment/needs_wx/genComponsTemplate.py +130 -0
  2738. psychopy/tests/test_experiment/needs_wx/test_Experiment.py +406 -0
  2739. psychopy/tests/test_experiment/needs_wx/test_components.py +170 -0
  2740. psychopy/tests/test_experiment/test_component_compile_js.py +59 -0
  2741. psychopy/tests/test_experiment/test_component_compile_python.py +165 -0
  2742. psychopy/tests/test_experiment/test_components/__init__.py +1 -0
  2743. psychopy/tests/test_experiment/test_components/test_ButtonBox.py +216 -0
  2744. psychopy/tests/test_experiment/test_components/test_Code.py +82 -0
  2745. psychopy/tests/test_experiment/test_components/test_Image.py +24 -0
  2746. psychopy/tests/test_experiment/test_components/test_Mouse.py +149 -0
  2747. psychopy/tests/test_experiment/test_components/test_Polygon.py +81 -0
  2748. psychopy/tests/test_experiment/test_components/test_ResourceManager.py +60 -0
  2749. psychopy/tests/test_experiment/test_components/test_Settings.py +82 -0
  2750. psychopy/tests/test_experiment/test_components/test_Static.py +60 -0
  2751. psychopy/tests/test_experiment/test_components/test_all_components.py +162 -0
  2752. psychopy/tests/test_experiment/test_components/test_base_components.py +323 -0
  2753. psychopy/tests/test_experiment/test_experiment.py +103 -0
  2754. psychopy/tests/test_experiment/test_loops.py +95 -0
  2755. psychopy/tests/test_experiment/test_params.py +350 -0
  2756. psychopy/tests/test_experiment/test_py2js.py +230 -0
  2757. psychopy/tests/test_experiment/test_routines/__init__.py +1 -0
  2758. psychopy/tests/test_experiment/test_routines/test_EyetrackerCalibrationRoutine.py +9 -0
  2759. psychopy/tests/test_experiment/test_routines/test_PhotodiodeValidationRoutine.py +9 -0
  2760. psychopy/tests/test_experiment/test_routines/test_all_routines.py +23 -0
  2761. psychopy/tests/test_experiment/test_routines/test_base_routine.py +154 -0
  2762. psychopy/tests/test_experiment/test_routines/test_standalone_routines.py +36 -0
  2763. psychopy/tests/test_gui/test_DlgFromDictQt.py +82 -0
  2764. psychopy/tests/test_gui/test_DlgFromDictWx.py +82 -0
  2765. psychopy/tests/test_hardware/__init__.py +0 -0
  2766. psychopy/tests/test_hardware/test_CRS_BitsSharp.py +67 -0
  2767. psychopy/tests/test_hardware/test_CRS_bitsShaders.py +110 -0
  2768. psychopy/tests/test_hardware/test_device_manager.py +36 -0
  2769. psychopy/tests/test_hardware/test_emulator.py +106 -0
  2770. psychopy/tests/test_hardware/test_gammasci.py +35 -0
  2771. psychopy/tests/test_hardware/test_keyboard.py +73 -0
  2772. psychopy/tests/test_hardware/test_keyboard_events.py +362 -0
  2773. psychopy/tests/test_hardware/test_ports.py +151 -0
  2774. psychopy/tests/test_iohub/__init__.py +1 -0
  2775. psychopy/tests/test_iohub/test_computer.py +124 -0
  2776. psychopy/tests/test_iohub/test_event_get_and_clear.py +94 -0
  2777. psychopy/tests/test_iohub/test_keyboard.py +91 -0
  2778. psychopy/tests/test_iohub/test_launch.py +19 -0
  2779. psychopy/tests/test_iohub/testutil.py +54 -0
  2780. psychopy/tests/test_liaison/test_Liaison.py +228 -0
  2781. psychopy/tests/test_misc/__init__.py +0 -0
  2782. psychopy/tests/test_misc/memory_usage.py +164 -0
  2783. psychopy/tests/test_misc/test_GammaFun.py +15 -0
  2784. psychopy/tests/test_misc/test_clock.py +61 -0
  2785. psychopy/tests/test_misc/test_color.py +203 -0
  2786. psychopy/tests/test_misc/test_core.py +446 -0
  2787. psychopy/tests/test_misc/test_event.py +307 -0
  2788. psychopy/tests/test_misc/test_info.py +18 -0
  2789. psychopy/tests/test_misc/test_layout.py +49 -0
  2790. psychopy/tests/test_misc/test_locale.py +38 -0
  2791. psychopy/tests/test_misc/test_web.py +22 -0
  2792. psychopy/tests/test_monitors/test_monitors.py +91 -0
  2793. psychopy/tests/test_preferences/__init__.py +0 -0
  2794. psychopy/tests/test_preferences/test_prefs.py +28 -0
  2795. psychopy/tests/test_session/test_Session.py +253 -0
  2796. psychopy/tests/test_sound/__init__.py +0 -0
  2797. psychopy/tests/test_sound/test_audioclip.py +331 -0
  2798. psychopy/tests/test_sound/test_hamming.py +45 -0
  2799. psychopy/tests/test_sound/test_microphone.py +217 -0
  2800. psychopy/tests/test_sound/test_sound.py +67 -0
  2801. psychopy/tests/test_sound/test_sound_pygame.py +67 -0
  2802. psychopy/tests/test_tools/test_animationtools.py +51 -0
  2803. psychopy/tests/test_tools/test_arraytools.py +130 -0
  2804. psychopy/tests/test_tools/test_attributetools.py +257 -0
  2805. psychopy/tests/test_tools/test_colorspacetools.py +149 -0
  2806. psychopy/tests/test_tools/test_environmenttools.py +52 -0
  2807. psychopy/tests/test_tools/test_fileerrortools.py +97 -0
  2808. psychopy/tests/test_tools/test_filetools.py +104 -0
  2809. psychopy/tests/test_tools/test_imagetools.py +57 -0
  2810. psychopy/tests/test_tools/test_mathtools.py +688 -0
  2811. psychopy/tests/test_tools/test_stringtools.py +143 -0
  2812. psychopy/tests/test_tools/test_versionchooser.py +178 -0
  2813. psychopy/tests/test_tools/test_viewtools.py +67 -0
  2814. psychopy/tests/test_visual/__init__.py +0 -0
  2815. psychopy/tests/test_visual/measure_parity.py +243 -0
  2816. psychopy/tests/test_visual/test_all_stimuli.py +752 -0
  2817. psychopy/tests/test_visual/test_basevisual.py +534 -0
  2818. psychopy/tests/test_visual/test_brush.py +68 -0
  2819. psychopy/tests/test_visual/test_button.py +15 -0
  2820. psychopy/tests/test_visual/test_circle.py +66 -0
  2821. psychopy/tests/test_visual/test_contains_overlaps.py +242 -0
  2822. psychopy/tests/test_visual/test_custommouse.py +47 -0
  2823. psychopy/tests/test_visual/test_dots.py +155 -0
  2824. psychopy/tests/test_visual/test_form.py +414 -0
  2825. psychopy/tests/test_visual/test_framepacking.py +41 -0
  2826. psychopy/tests/test_visual/test_gamma.py +152 -0
  2827. psychopy/tests/test_visual/test_glfw_backend.py +14 -0
  2828. psychopy/tests/test_visual/test_image.py +218 -0
  2829. psychopy/tests/test_visual/test_panorama.py +41 -0
  2830. psychopy/tests/test_visual/test_progress.py +96 -0
  2831. psychopy/tests/test_visual/test_projections.py +215 -0
  2832. psychopy/tests/test_visual/test_projections_interactive.py +163 -0
  2833. psychopy/tests/test_visual/test_ratingScale.py +299 -0
  2834. psychopy/tests/test_visual/test_roi.py +99 -0
  2835. psychopy/tests/test_visual/test_shape.py +23 -0
  2836. psychopy/tests/test_visual/test_slider.py +328 -0
  2837. psychopy/tests/test_visual/test_target.py +35 -0
  2838. psychopy/tests/test_visual/test_textbox.py +474 -0
  2839. psychopy/tests/test_visual/test_winFlipTiming.py +95 -0
  2840. psychopy/tests/test_visual/test_winScalePos.py +77 -0
  2841. psychopy/tests/test_visual/test_window.py +107 -0
  2842. psychopy/tests/utils.py +318 -0
  2843. psychopy/tools/LineBreak.txt +3597 -0
  2844. psychopy/tools/__init__.py +9 -0
  2845. psychopy/tools/animationtools.py +49 -0
  2846. psychopy/tools/apptools.py +32 -0
  2847. psychopy/tools/arraytools.py +514 -0
  2848. psychopy/tools/attributetools.py +205 -0
  2849. psychopy/tools/audiotools.py +358 -0
  2850. psychopy/tools/colorspacetools.py +715 -0
  2851. psychopy/tools/coordinatetools.py +104 -0
  2852. psychopy/tools/environmenttools.py +62 -0
  2853. psychopy/tools/fileerrortools.py +54 -0
  2854. psychopy/tools/filetools.py +406 -0
  2855. psychopy/tools/fontmanager.py +1041 -0
  2856. psychopy/tools/gltools.py +4959 -0
  2857. psychopy/tools/imagetools.py +65 -0
  2858. psychopy/tools/linebreak.py +322 -0
  2859. psychopy/tools/mathtools.py +4040 -0
  2860. psychopy/tools/monitorunittools.py +270 -0
  2861. psychopy/tools/movietools.py +1071 -0
  2862. psychopy/tools/pkgtools.py +601 -0
  2863. psychopy/tools/plottools.py +25 -0
  2864. psychopy/tools/rifttools.py +76 -0
  2865. psychopy/tools/stereotools.py +9 -0
  2866. psychopy/tools/stimulustools.py +28 -0
  2867. psychopy/tools/stringtools.py +421 -0
  2868. psychopy/tools/systemtools.py +1331 -0
  2869. psychopy/tools/typetools.py +52 -0
  2870. psychopy/tools/unittools.py +16 -0
  2871. psychopy/tools/versionchooser.py +602 -0
  2872. psychopy/tools/viewtools.py +1084 -0
  2873. psychopy/tools/wizard.py +804 -0
  2874. psychopy/visual/__init__.py +124 -0
  2875. psychopy/visual/aperture.py +330 -0
  2876. psychopy/visual/backends/__init__.py +77 -0
  2877. psychopy/visual/backends/_base.py +481 -0
  2878. psychopy/visual/backends/gamma.py +349 -0
  2879. psychopy/visual/backends/glfwbackend.py +28 -0
  2880. psychopy/visual/backends/pygamebackend.py +343 -0
  2881. psychopy/visual/backends/pygletbackend.py +920 -0
  2882. psychopy/visual/basevisual.py +1952 -0
  2883. psychopy/visual/brush.py +204 -0
  2884. psychopy/visual/bufferimage.py +231 -0
  2885. psychopy/visual/button.py +206 -0
  2886. psychopy/visual/circle.py +173 -0
  2887. psychopy/visual/custommouse.py +263 -0
  2888. psychopy/visual/dot.py +668 -0
  2889. psychopy/visual/dropdown.py +165 -0
  2890. psychopy/visual/elementarray.py +728 -0
  2891. psychopy/visual/filters.py +419 -0
  2892. psychopy/visual/form.py +1180 -0
  2893. psychopy/visual/globalVars.py +24 -0
  2894. psychopy/visual/grating.py +501 -0
  2895. psychopy/visual/helpers.py +334 -0
  2896. psychopy/visual/image.py +440 -0
  2897. psychopy/visual/line.py +238 -0
  2898. psychopy/visual/movie.py +12 -0
  2899. psychopy/visual/movie2.py +829 -0
  2900. psychopy/visual/movie3.py +599 -0
  2901. psychopy/visual/movies/__init__.py +850 -0
  2902. psychopy/visual/movies/frame.py +255 -0
  2903. psychopy/visual/movies/metadata.py +242 -0
  2904. psychopy/visual/movies/players/__init__.py +62 -0
  2905. psychopy/visual/movies/players/_base.py +364 -0
  2906. psychopy/visual/movies/players/ffpyplayer_player.py +1399 -0
  2907. psychopy/visual/nnlvs.py +827 -0
  2908. psychopy/visual/noise.py +34 -0
  2909. psychopy/visual/panorama.py +313 -0
  2910. psychopy/visual/patch.py +29 -0
  2911. psychopy/visual/pie.py +248 -0
  2912. psychopy/visual/polygon.py +229 -0
  2913. psychopy/visual/progress.py +313 -0
  2914. psychopy/visual/radial.py +33 -0
  2915. psychopy/visual/ratingscale.py +1424 -0
  2916. psychopy/visual/rect.py +204 -0
  2917. psychopy/visual/rift.py +2654 -0
  2918. psychopy/visual/roi.py +141 -0
  2919. psychopy/visual/secondorder.py +29 -0
  2920. psychopy/visual/shaders.py +453 -0
  2921. psychopy/visual/shape.py +701 -0
  2922. psychopy/visual/simpleimage.py +303 -0
  2923. psychopy/visual/slider.py +1169 -0
  2924. psychopy/visual/stim3d.py +2712 -0
  2925. psychopy/visual/target.py +278 -0
  2926. psychopy/visual/text.py +759 -0
  2927. psychopy/visual/textbox/__init__.py +1280 -0
  2928. psychopy/visual/textbox/fontmanager.py +574 -0
  2929. psychopy/visual/textbox/parsedtext.py +317 -0
  2930. psychopy/visual/textbox/textgrid.py +278 -0
  2931. psychopy/visual/textbox/textureatlas.py +248 -0
  2932. psychopy/visual/textbox2/__init__.py +4 -0
  2933. psychopy/visual/textbox2/textbox2.py +1817 -0
  2934. psychopy/visual/vlcmoviestim.py +1294 -0
  2935. psychopy/visual/window.py +3706 -0
  2936. psychopy/visual/windowframepack.py +86 -0
  2937. psychopy/visual/windowwarp.py +457 -0
  2938. psychopy/voicekey/__init__.py +684 -0
  2939. psychopy/voicekey/demo_vks.py +12 -0
  2940. psychopy/voicekey/labjack_vks.py +50 -0
  2941. psychopy/voicekey/parallel_vks.py +44 -0
  2942. psychopy/voicekey/signal.py +42 -0
  2943. psychopy/voicekey/vk_tools.py +280 -0
  2944. psychopy/web.py +286 -0
  2945. psychopy-2024.1.0.dist-info/METADATA +154 -0
  2946. psychopy-2024.1.0.dist-info/RECORD +2950 -0
  2947. psychopy-2024.1.0.dist-info/WHEEL +4 -0
  2948. psychopy-2024.1.0.dist-info/entry_points.txt +3 -0
  2949. psychopy-2024.1.0.dist-info/licenses/AUTHORS.md +138 -0
  2950. psychopy-2024.1.0.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,4959 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """OpenGL related helper functions.
4
+
5
+ """
6
+
7
+ # Part of the PsychoPy library
8
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
9
+ # Distributed under the terms of the GNU General Public License (GPL).
10
+
11
+ __all__ = [
12
+ 'createProgram',
13
+ 'createProgramObjectARB',
14
+ 'compileShader',
15
+ 'compileShaderObjectARB',
16
+ 'embedShaderSourceDefs',
17
+ 'deleteObject',
18
+ 'deleteObjectARB',
19
+ 'attachShader',
20
+ 'attachObjectARB',
21
+ 'detachShader',
22
+ 'detachObjectARB',
23
+ 'linkProgram',
24
+ 'linkProgramObjectARB',
25
+ 'validateProgram',
26
+ 'validateProgramARB',
27
+ 'useProgram',
28
+ 'useProgramObjectARB',
29
+ 'getInfoLog',
30
+ 'getUniformLocations',
31
+ 'getAttribLocations',
32
+ 'createQueryObject',
33
+ 'QueryObjectInfo',
34
+ 'beginQuery',
35
+ 'endQuery',
36
+ 'getQuery',
37
+ 'getAbsTimeGPU',
38
+ 'createFBO',
39
+ 'attach',
40
+ 'isComplete',
41
+ 'deleteFBO',
42
+ 'blitFBO',
43
+ 'useFBO',
44
+ 'createRenderbuffer',
45
+ 'deleteRenderbuffer',
46
+ 'createTexImage2D',
47
+ 'createTexImage2DMultisample',
48
+ 'deleteTexture',
49
+ 'VertexArrayInfo',
50
+ 'createVAO',
51
+ 'drawVAO',
52
+ 'deleteVAO',
53
+ 'VertexBufferInfo',
54
+ 'createVBO',
55
+ 'bindVBO',
56
+ 'unbindVBO',
57
+ 'mapBuffer',
58
+ 'unmapBuffer',
59
+ 'deleteVBO',
60
+ 'setVertexAttribPointer',
61
+ 'enableVertexAttribArray',
62
+ 'disableVertexAttribArray',
63
+ 'createMaterial',
64
+ 'useMaterial',
65
+ 'createLight',
66
+ 'useLights',
67
+ 'setAmbientLight',
68
+ 'ObjMeshInfo',
69
+ 'loadObjFile',
70
+ 'loadMtlFile',
71
+ 'createUVSphere',
72
+ 'createPlane',
73
+ 'createMeshGridFromArrays',
74
+ 'createMeshGrid',
75
+ 'createBox',
76
+ 'transformMeshPosOri',
77
+ 'calculateVertexNormals',
78
+ 'getIntegerv',
79
+ 'getFloatv',
80
+ 'getString',
81
+ 'getOpenGLInfo',
82
+ 'createTexImage2D',
83
+ 'createTexImage2dFromFile',
84
+ 'bindTexture',
85
+ 'unbindTexture',
86
+ 'createCubeMap',
87
+ 'TexCubeMap',
88
+ 'getModelViewMatrix',
89
+ 'getProjectionMatrix'
90
+ ]
91
+
92
+ import ctypes
93
+ from io import StringIO
94
+ from collections import namedtuple
95
+ import pyglet.gl as GL # using Pyglet for now
96
+ from contextlib import contextmanager
97
+ from PIL import Image
98
+ import numpy as np
99
+ import os
100
+ import sys
101
+ import platform
102
+ import warnings
103
+ import psychopy.tools.mathtools as mt
104
+ from psychopy.visual.helpers import setColor, findImageFile
105
+
106
+ _thisPlatform = platform.system()
107
+
108
+ # create a query counter to get absolute GPU time
109
+
110
+ QUERY_COUNTER = None # prevent genQueries from being called
111
+
112
+
113
+ # compatible Numpy and OpenGL types for common GL type enums
114
+ GL_COMPAT_TYPES = {
115
+ GL.GL_FLOAT: (np.float32, GL.GLfloat),
116
+ GL.GL_DOUBLE: (np.float64, GL.GLdouble),
117
+ GL.GL_UNSIGNED_SHORT: (np.uint16, GL.GLushort),
118
+ GL.GL_UNSIGNED_INT: (np.uint32, GL.GLuint),
119
+ GL.GL_INT: (np.int32, GL.GLint),
120
+ GL.GL_SHORT: (np.int16, GL.GLshort),
121
+ GL.GL_HALF_FLOAT: (np.float16, GL.GLhalfARB),
122
+ GL.GL_UNSIGNED_BYTE: (np.uint8, GL.GLubyte),
123
+ GL.GL_BYTE: (np.int8, GL.GLbyte),
124
+ np.float32: (GL.GL_FLOAT, GL.GLfloat),
125
+ np.float64: (GL.GL_DOUBLE, GL.GLdouble),
126
+ np.uint16: (GL.GL_UNSIGNED_SHORT, GL.GLushort),
127
+ np.uint32: (GL.GL_UNSIGNED_INT, GL.GLuint),
128
+ np.int32: (GL.GL_INT, GL.GLint),
129
+ np.int16: (GL.GL_SHORT, GL.GLshort),
130
+ np.float16: (GL.GL_HALF_FLOAT, GL.GLhalfARB),
131
+ np.uint8: (GL.GL_UNSIGNED_BYTE, GL.GLubyte),
132
+ np.int8: (GL.GL_BYTE, GL.GLbyte)
133
+ }
134
+
135
+
136
+ # -------------------------------
137
+ # Shader Program Helper Functions
138
+ # -------------------------------
139
+ #
140
+
141
+ def createProgram():
142
+ """Create an empty program object for shaders.
143
+
144
+ Returns
145
+ -------
146
+ int
147
+ OpenGL program object handle retrieved from a `glCreateProgram` call.
148
+
149
+ Examples
150
+ --------
151
+ Building a program with vertex and fragment shader attachments::
152
+
153
+ myProgram = createProgram() # new shader object
154
+
155
+ # compile vertex and fragment shader sources
156
+ vertexShader = compileShader(vertShaderSource, GL.GL_VERTEX_SHADER)
157
+ fragmentShader = compileShader(fragShaderSource, GL.GL_FRAGMENT_SHADER)
158
+
159
+ # attach shaders to program
160
+ attachShader(myProgram, vertexShader)
161
+ attachShader(myProgram, fragmentShader)
162
+
163
+ # link the shader, makes `myProgram` attachments executable by their
164
+ # respective processors and available for use
165
+ linkProgram(myProgram)
166
+
167
+ # optional, validate the program
168
+ validateProgram(myProgram)
169
+
170
+ # optional, detach and discard shader objects
171
+ detachShader(myProgram, vertexShader)
172
+ detachShader(myProgram, fragmentShader)
173
+
174
+ deleteObject(vertexShader)
175
+ deleteObject(fragmentShader)
176
+
177
+ You can install the program for use in the current rendering state by
178
+ calling::
179
+
180
+ useProgram(myShader) # OR glUseProgram(myShader)
181
+ # set uniforms/attributes and start drawing here ...
182
+
183
+ """
184
+ return GL.glCreateProgram()
185
+
186
+
187
+ def createProgramObjectARB():
188
+ """Create an empty program object for shaders.
189
+
190
+ This creates an *Architecture Review Board* (ARB) program variant which is
191
+ compatible with older GLSL versions and OpenGL coding practices (eg.
192
+ immediate mode) on some platforms. Use *ARB variants of shader helper
193
+ functions (eg. `compileShaderObjectARB` instead of `compileShader`) when
194
+ working with these ARB program objects. This was included for legacy support
195
+ of existing PsychoPy shaders. However, it is recommended that you use
196
+ :func:`createShader` and follow more recent OpenGL design patterns for new
197
+ code (if possible of course).
198
+
199
+ Returns
200
+ -------
201
+ int
202
+ OpenGL program object handle retrieved from a `glCreateProgramObjectARB`
203
+ call.
204
+
205
+ Examples
206
+ --------
207
+ Building a program with vertex and fragment shader attachments::
208
+
209
+ myProgram = createProgramObjectARB() # new shader object
210
+
211
+ # compile vertex and fragment shader sources
212
+ vertexShader = compileShaderObjectARB(
213
+ vertShaderSource, GL.GL_VERTEX_SHADER_ARB)
214
+ fragmentShader = compileShaderObjectARB(
215
+ fragShaderSource, GL.GL_FRAGMENT_SHADER_ARB)
216
+
217
+ # attach shaders to program
218
+ attachObjectARB(myProgram, vertexShader)
219
+ attachObjectARB(myProgram, fragmentShader)
220
+
221
+ # link the shader, makes `myProgram` attachments executable by their
222
+ # respective processors and available for use
223
+ linkProgramObjectARB(myProgram)
224
+
225
+ # optional, validate the program
226
+ validateProgramARB(myProgram)
227
+
228
+ # optional, detach and discard shader objects
229
+ detachObjectARB(myProgram, vertexShader)
230
+ detachObjectARB(myProgram, fragmentShader)
231
+
232
+ deleteObjectARB(vertexShader)
233
+ deleteObjectARB(fragmentShader)
234
+
235
+ Use the program in the current OpenGL state::
236
+
237
+ useProgramObjectARB(myProgram)
238
+
239
+ """
240
+ return GL.glCreateProgramObjectARB()
241
+
242
+
243
+ def compileShader(shaderSrc, shaderType):
244
+ """Compile shader GLSL code and return a shader object. Shader objects can
245
+ then be attached to programs an made executable on their respective
246
+ processors.
247
+
248
+ Parameters
249
+ ----------
250
+ shaderSrc : str, list of str
251
+ GLSL shader source code.
252
+ shaderType : GLenum
253
+ Shader program type (eg. `GL_VERTEX_SHADER`, `GL_FRAGMENT_SHADER`,
254
+ `GL_GEOMETRY_SHADER`, etc.)
255
+
256
+ Returns
257
+ -------
258
+ int
259
+ OpenGL shader object handle retrieved from a `glCreateShader` call.
260
+
261
+ Examples
262
+ --------
263
+ Compiling GLSL source code and attaching it to a program object::
264
+
265
+ # GLSL vertex shader source
266
+ vertexSource = \
267
+ '''
268
+ #version 330 core
269
+ layout (location = 0) in vec3 vertexPos;
270
+
271
+ void main()
272
+ {
273
+ gl_Position = vec4(vertexPos, 1.0);
274
+ }
275
+ '''
276
+ # compile it, specifying `GL_VERTEX_SHADER`
277
+ vertexShader = compileShader(vertexSource, GL.GL_VERTEX_SHADER)
278
+ attachShader(myProgram, vertexShader) # attach it to `myProgram`
279
+
280
+ """
281
+ shaderId = GL.glCreateShader(shaderType)
282
+
283
+ if isinstance(shaderSrc, (list, tuple,)):
284
+ nSources = len(shaderSrc)
285
+ srcPtr = (ctypes.c_char_p * nSources)()
286
+ srcPtr[:] = [i.encode() for i in shaderSrc]
287
+ else:
288
+ nSources = 1
289
+ srcPtr = ctypes.c_char_p(shaderSrc.encode())
290
+
291
+ GL.glShaderSource(
292
+ shaderId,
293
+ nSources,
294
+ ctypes.cast(
295
+ ctypes.byref(srcPtr),
296
+ ctypes.POINTER(ctypes.POINTER(ctypes.c_char))),
297
+ None)
298
+ GL.glCompileShader(shaderId)
299
+
300
+ result = GL.GLint()
301
+ GL.glGetShaderiv(
302
+ shaderId, GL.GL_COMPILE_STATUS, ctypes.byref(result))
303
+
304
+ if result.value == GL.GL_FALSE: # failed to compile for whatever reason
305
+ sys.stderr.write(getInfoLog(shaderId) + '\n')
306
+ deleteObject(shaderId)
307
+ raise RuntimeError("Shader compilation failed, check log output.")
308
+
309
+ return shaderId
310
+
311
+
312
+ def compileShaderObjectARB(shaderSrc, shaderType):
313
+ """Compile shader GLSL code and return a shader object. Shader objects can
314
+ then be attached to programs an made executable on their respective
315
+ processors.
316
+
317
+ Parameters
318
+ ----------
319
+ shaderSrc : str, list of str
320
+ GLSL shader source code text.
321
+ shaderType : GLenum
322
+ Shader program type. Must be `*_ARB` enums such as `GL_VERTEX_SHADER_ARB`,
323
+ `GL_FRAGMENT_SHADER_ARB`, `GL_GEOMETRY_SHADER_ARB`, etc.
324
+
325
+ Returns
326
+ -------
327
+ int
328
+ OpenGL shader object handle retrieved from a `glCreateShaderObjectARB`
329
+ call.
330
+
331
+ """
332
+ shaderId = GL.glCreateShaderObjectARB(shaderType)
333
+
334
+ if isinstance(shaderSrc, (list, tuple,)):
335
+ nSources = len(shaderSrc)
336
+ srcPtr = (ctypes.c_char_p * nSources)()
337
+ srcPtr[:] = [i.encode() for i in shaderSrc]
338
+ else:
339
+ nSources = 1
340
+ srcPtr = ctypes.c_char_p(shaderSrc.encode())
341
+
342
+ GL.glShaderSourceARB(
343
+ shaderId,
344
+ nSources,
345
+ ctypes.cast(
346
+ ctypes.byref(srcPtr),
347
+ ctypes.POINTER(ctypes.POINTER(ctypes.c_char))),
348
+ None)
349
+ GL.glCompileShaderARB(shaderId)
350
+
351
+ result = GL.GLint()
352
+ GL.glGetObjectParameterivARB(
353
+ shaderId, GL.GL_OBJECT_COMPILE_STATUS_ARB, ctypes.byref(result))
354
+
355
+ if result.value == GL.GL_FALSE: # failed to compile for whatever reason
356
+ sys.stderr.write(getInfoLog(shaderId) + '\n')
357
+ deleteObjectARB(shaderId)
358
+ raise RuntimeError("Shader compilation failed, check log output.")
359
+
360
+ return shaderId
361
+
362
+
363
+ def embedShaderSourceDefs(shaderSrc, defs):
364
+ """Embed preprocessor definitions into GLSL source code.
365
+
366
+ This function generates and inserts ``#define`` statements into existing
367
+ GLSL source code, allowing one to use GLSL preprocessor statements to alter
368
+ program source at compile time.
369
+
370
+ Passing ``{'MAX_LIGHTS': 8, 'NORMAL_MAP': False}`` to `defs` will create and
371
+ insert the following ``#define`` statements into `shaderSrc`::
372
+
373
+ #define MAX_LIGHTS 8
374
+ #define NORMAL_MAP 0
375
+
376
+ As per the GLSL specification, the ``#version`` directive must be specified
377
+ at the top of the file before any other statement (with the exception of
378
+ comments). If a ``#version`` directive is present, generated ``#define``
379
+ statements will be inserted starting at the following line. If no
380
+ ``#version`` directive is found in `shaderSrc`, the statements will be
381
+ prepended to `shaderSrc`.
382
+
383
+ Using preprocessor directives, multiple shader program routines can reside
384
+ in the same source text if enclosed by ``#ifdef`` and ``#endif`` statements
385
+ as shown here::
386
+
387
+ #ifdef VERTEX
388
+ // vertex shader code here ...
389
+ #endif
390
+
391
+ #ifdef FRAGMENT
392
+ // pixel shader code here ...
393
+ #endif
394
+
395
+ Both the vertex and fragment shader can be built from the same GLSL code
396
+ listing by setting either ``VERTEX`` or ``FRAGMENT`` as `True`::
397
+
398
+ vertexShader = gltools.compileShaderObjectARB(
399
+ gltools.embedShaderSourceDefs(glslSource, {'VERTEX': True}),
400
+ GL.GL_VERTEX_SHADER_ARB)
401
+ fragmentShader = gltools.compileShaderObjectARB(
402
+ gltools.embedShaderSourceDefs(glslSource, {'FRAGMENT': True}),
403
+ GL.GL_FRAGMENT_SHADER_ARB)
404
+
405
+ In addition, ``#ifdef`` blocks can be used to prune render code paths. Here,
406
+ this GLSL snippet shows a shader having diffuse color sampled from a texture
407
+ is conditional on ``DIFFUSE_TEXTURE`` being `True`, if not, the material
408
+ color is used instead::
409
+
410
+ #ifdef DIFFUSE_TEXTURE
411
+ uniform sampler2D diffuseTexture;
412
+ #endif
413
+ ...
414
+ #ifdef DIFFUSE_TEXTURE
415
+ // sample color from texture
416
+ vec4 diffuseColor = texture2D(diffuseTexture, gl_TexCoord[0].st);
417
+ #else
418
+ // code path for no textures, just output material color
419
+ vec4 diffuseColor = gl_FrontMaterial.diffuse;
420
+ #endif
421
+
422
+ This avoids needing to provide two separate GLSL program sources to build
423
+ shaders to handle cases where a diffuse texture is or isn't used.
424
+
425
+ Parameters
426
+ ----------
427
+ shaderSrc : str
428
+ GLSL shader source code.
429
+ defs : dict
430
+ Names and values to generate ``#define`` statements. Keys must all be
431
+ valid GLSL preprocessor variable names of type `str`. Values can only be
432
+ `int`, `float`, `str`, `bytes`, or `bool` types. Boolean values `True`
433
+ and `False` are converted to integers `1` and `0`, respectively.
434
+
435
+ Returns
436
+ -------
437
+ str
438
+ GLSL source code with ``#define`` statements inserted.
439
+
440
+ Examples
441
+ --------
442
+ Defining ``MAX_LIGHTS`` as `8` in a fragment shader program at runtime::
443
+
444
+ fragSrc = embedShaderSourceDefs(fragSrc, {'MAX_LIGHTS': 8})
445
+ fragShader = compileShaderObjectARB(fragSrc, GL_FRAGMENT_SHADER_ARB)
446
+
447
+ """
448
+ # generate GLSL `#define` statements
449
+ glslDefSrc = ""
450
+ for varName, varValue in defs.items():
451
+ if not isinstance(varName, str):
452
+ raise ValueError("Definition name must be type `str`.")
453
+
454
+ if isinstance(varValue, (int, bool,)):
455
+ varValue = int(varValue)
456
+ elif isinstance(varValue, (float,)):
457
+ pass
458
+ #varValue = varValue
459
+ elif isinstance(varValue, bytes):
460
+ varValue = '"{}"'.format(varValue.decode('UTF-8'))
461
+ elif isinstance(varValue, str):
462
+ varValue = '"{}"'.format(varValue)
463
+ else:
464
+ raise TypeError("Invalid type for value of `{}`.".format(varName))
465
+
466
+ glslDefSrc += '#define {n} {v}\n'.format(n=varName, v=varValue)
467
+
468
+ # find where the `#version` directive occurs
469
+ versionDirIdx = shaderSrc.find("#version")
470
+ if versionDirIdx != -1:
471
+ srcSplitIdx = shaderSrc.find("\n", versionDirIdx) + 1 # after newline
472
+ srcOut = shaderSrc[:srcSplitIdx] + glslDefSrc + shaderSrc[srcSplitIdx:]
473
+ else:
474
+ # no version directive in source, just prepend defines
475
+ srcOut = glslDefSrc + shaderSrc
476
+
477
+ return srcOut
478
+
479
+
480
+ def deleteObject(obj):
481
+ """Delete a shader or program object.
482
+
483
+ Parameters
484
+ ----------
485
+ obj : int
486
+ Shader or program object handle. Must have originated from a
487
+ :func:`createProgram`, :func:`compileShader`, `glCreateProgram` or
488
+ `glCreateShader` call.
489
+
490
+ """
491
+ if GL.glIsShader(obj):
492
+ GL.glDeleteShader(obj)
493
+ elif GL.glIsProgram(obj):
494
+ GL.glDeleteProgram(obj)
495
+ else:
496
+ raise ValueError('Cannot delete, not a program or shader object.')
497
+
498
+
499
+ def deleteObjectARB(obj):
500
+ """Delete a program or shader object.
501
+
502
+ Parameters
503
+ ----------
504
+ obj : int
505
+ Program handle to attach `shader` to. Must have originated from a
506
+ :func:`createProgramObjectARB`, :func:`compileShaderObjectARB,
507
+ `glCreateProgramObjectARB` or `glCreateShaderObjectARB` call.
508
+
509
+ """
510
+ GL.glDeleteObjectARB(obj)
511
+
512
+
513
+ def attachShader(program, shader):
514
+ """Attach a shader to a program.
515
+
516
+ Parameters
517
+ ----------
518
+ program : int
519
+ Program handle to attach `shader` to. Must have originated from a
520
+ :func:`createProgram` or `glCreateProgram` call.
521
+ shader : int
522
+ Handle of shader object to attach. Must have originated from a
523
+ :func:`compileShader` or `glCreateShader` call.
524
+
525
+ """
526
+ if not GL.glIsProgram(program):
527
+ raise ValueError("Value `program` is not a program object.")
528
+ elif not GL.glIsShader(shader):
529
+ raise ValueError("Value `shader` is not a shader object.")
530
+ else:
531
+ GL.glAttachShader(program, shader)
532
+
533
+
534
+ def attachObjectARB(program, shader):
535
+ """Attach a shader object to a program.
536
+
537
+ Parameters
538
+ ----------
539
+ program : int
540
+ Program handle to attach `shader` to. Must have originated from a
541
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB` call.
542
+ shader : int
543
+ Handle of shader object to attach. Must have originated from a
544
+ :func:`compileShaderObjectARB` or `glCreateShaderObjectARB` call.
545
+
546
+ """
547
+ if not GL.glIsProgram(program):
548
+ raise ValueError("Value `program` is not a program object.")
549
+ elif not GL.glIsShader(shader):
550
+ raise ValueError("Value `shader` is not a shader object.")
551
+ else:
552
+ GL.glAttachObjectARB(program, shader)
553
+
554
+
555
+ def detachShader(program, shader):
556
+ """Detach a shader object from a program.
557
+
558
+ Parameters
559
+ ----------
560
+ program : int
561
+ Program handle to detach `shader` from. Must have originated from a
562
+ :func:`createProgram` or `glCreateProgram` call.
563
+ shader : int
564
+ Handle of shader object to detach. Must have been previously attached
565
+ to `program`.
566
+
567
+ """
568
+ if not GL.glIsProgram(program):
569
+ raise ValueError("Value `program` is not a program.")
570
+ elif not GL.glIsShader(shader):
571
+ raise ValueError("Value `shader` is not a shader object.")
572
+ else:
573
+ GL.glDetachShader(program, shader)
574
+
575
+
576
+ def detachObjectARB(program, shader):
577
+ """Detach a shader object from a program.
578
+
579
+ Parameters
580
+ ----------
581
+ program : int
582
+ Program handle to detach `shader` from. Must have originated from a
583
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB` call.
584
+ shader : int
585
+ Handle of shader object to detach. Must have been previously attached
586
+ to `program`.
587
+
588
+ """
589
+ if not GL.glIsProgram(program):
590
+ raise ValueError("Value `program` is not a program.")
591
+ elif not GL.glIsShader(shader):
592
+ raise ValueError("Value `shader` is not a shader object.")
593
+ else:
594
+ GL.glDetachObjectARB(program, shader)
595
+
596
+
597
+ def linkProgram(program):
598
+ """Link a shader program. Any attached shader objects will be made
599
+ executable to run on associated GPU processor units when the program is
600
+ used.
601
+
602
+ Parameters
603
+ ----------
604
+ program : int
605
+ Program handle to link. Must have originated from a
606
+ :func:`createProgram` or `glCreateProgram` call.
607
+
608
+ Raises
609
+ ------
610
+ ValueError
611
+ Specified `program` handle is invalid.
612
+ RuntimeError
613
+ Program failed to link. Log will be dumped to `sterr`.
614
+
615
+ """
616
+ if GL.glIsProgram(program):
617
+ GL.glLinkProgram(program)
618
+ else:
619
+ raise ValueError("Value `program` is not a shader program.")
620
+
621
+ # check for errors
622
+ result = GL.GLint()
623
+ GL.glGetProgramiv(program, GL.GL_LINK_STATUS, ctypes.byref(result))
624
+
625
+ if result.value == GL.GL_FALSE: # failed to link for whatever reason
626
+ sys.stderr.write(getInfoLog(program) + '\n')
627
+ raise RuntimeError(
628
+ 'Failed to link shader program. Check log output.')
629
+
630
+
631
+ def linkProgramObjectARB(program):
632
+ """Link a shader program object. Any attached shader objects will be made
633
+ executable to run on associated GPU processor units when the program is
634
+ used.
635
+
636
+ Parameters
637
+ ----------
638
+ program : int
639
+ Program handle to link. Must have originated from a
640
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB` call.
641
+
642
+ Raises
643
+ ------
644
+ ValueError
645
+ Specified `program` handle is invalid.
646
+ RuntimeError
647
+ Program failed to link. Log will be dumped to `sterr`.
648
+
649
+ """
650
+ if GL.glIsProgram(program):
651
+ GL.glLinkProgramARB(program)
652
+ else:
653
+ raise ValueError("Value `program` is not a shader program.")
654
+
655
+ # check for errors
656
+ result = GL.GLint()
657
+ GL.glGetObjectParameterivARB(
658
+ program,
659
+ GL.GL_OBJECT_LINK_STATUS_ARB,
660
+ ctypes.byref(result))
661
+
662
+ if result.value == GL.GL_FALSE: # failed to link for whatever reason
663
+ sys.stderr.write(getInfoLog(program) + '\n')
664
+ raise RuntimeError(
665
+ 'Failed to link shader program. Check log output.')
666
+
667
+
668
+ def validateProgram(program):
669
+ """Check if the program can execute given the current OpenGL state.
670
+
671
+ Parameters
672
+ ----------
673
+ program : int
674
+ Handle of program to validate. Must have originated from a
675
+ :func:`createProgram` or `glCreateProgram` call.
676
+
677
+ """
678
+ # check validation info
679
+ result = GL.GLint()
680
+ GL.glValidateProgram(program)
681
+ GL.glGetProgramiv(program, GL.GL_VALIDATE_STATUS, ctypes.byref(result))
682
+
683
+ if result.value == GL.GL_FALSE:
684
+ sys.stderr.write(getInfoLog(program) + '\n')
685
+ raise RuntimeError('Shader program validation failed.')
686
+
687
+
688
+ def validateProgramARB(program):
689
+ """Check if the program can execute given the current OpenGL state. If
690
+ validation fails, information from the driver is dumped giving the reason.
691
+
692
+ Parameters
693
+ ----------
694
+ program : int
695
+ Handle of program object to validate. Must have originated from a
696
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB` call.
697
+
698
+ """
699
+ # check validation info
700
+ result = GL.GLint()
701
+ GL.glValidateProgramARB(program)
702
+ GL.glGetObjectParameterivARB(
703
+ program,
704
+ GL.GL_OBJECT_VALIDATE_STATUS_ARB,
705
+ ctypes.byref(result))
706
+
707
+ if result.value == GL.GL_FALSE:
708
+ sys.stderr.write(getInfoLog(program) + '\n')
709
+ raise RuntimeError('Shader program validation failed.')
710
+
711
+
712
+ def useProgram(program):
713
+ """Use a program object's executable shader attachments in the current
714
+ OpenGL rendering state.
715
+
716
+ In order to install the program object in the current rendering state, a
717
+ program must have been successfully linked by calling :func:`linkProgram` or
718
+ `glLinkProgram`.
719
+
720
+ Parameters
721
+ ----------
722
+ program : int
723
+ Handle of program to use. Must have originated from a
724
+ :func:`createProgram` or `glCreateProgram` call and was successfully
725
+ linked. Passing `0` or `None` disables shader programs.
726
+
727
+ Examples
728
+ --------
729
+ Install a program for use in the current rendering state::
730
+
731
+ useProgram(myShader)
732
+
733
+ Disable the current shader program by specifying `0`::
734
+
735
+ useProgram(0)
736
+
737
+ """
738
+ if program is None:
739
+ program = 0
740
+
741
+ if GL.glIsProgram(program) or program == 0:
742
+ GL.glUseProgram(program)
743
+ else:
744
+ raise ValueError('Specified `program` is not a program object.')
745
+
746
+
747
+ def useProgramObjectARB(program):
748
+ """Use a program object's executable shader attachments in the current
749
+ OpenGL rendering state.
750
+
751
+ In order to install the program object in the current rendering state, a
752
+ program must have been successfully linked by calling
753
+ :func:`linkProgramObjectARB` or `glLinkProgramObjectARB`.
754
+
755
+ Parameters
756
+ ----------
757
+ program : int
758
+ Handle of program object to use. Must have originated from a
759
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB` call and
760
+ was successfully linked. Passing `0` or `None` disables shader programs.
761
+
762
+ Examples
763
+ --------
764
+ Install a program for use in the current rendering state::
765
+
766
+ useProgramObjectARB(myShader)
767
+
768
+ Disable the current shader program by specifying `0`::
769
+
770
+ useProgramObjectARB(0)
771
+
772
+ Notes
773
+ -----
774
+ Some drivers may support using `glUseProgram` for objects created by calling
775
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB`.
776
+
777
+ """
778
+ if program is None:
779
+ program = 0
780
+
781
+ if GL.glIsProgram(program) or program == 0:
782
+ GL.glUseProgramObjectARB(program)
783
+ else:
784
+ raise ValueError('Specified `program` is not a program object.')
785
+
786
+
787
+ def getInfoLog(obj):
788
+ """Get the information log from a shader or program.
789
+
790
+ This retrieves a text log from the driver pertaining to the shader or
791
+ program. For instance, a log can report shader compiler output or validation
792
+ results. The verbosity and formatting of the logs are platform-dependent,
793
+ where one driver may provide more information than another.
794
+
795
+ This function works with both standard and ARB program object variants.
796
+
797
+ Parameters
798
+ ----------
799
+ obj : int
800
+ Program or shader to retrieve a log from. If a shader, the handle must
801
+ have originated from a :func:`compileShader`, `glCreateShader`,
802
+ :func:`createProgramObjectARB` or `glCreateProgramObjectARB` call. If a
803
+ program, the handle must have came from a :func:`createProgram`,
804
+ :func:`createProgramObjectARB`, `glCreateProgram` or
805
+ `glCreateProgramObjectARB` call.
806
+
807
+ Returns
808
+ -------
809
+ str
810
+ Information log data. Logs can be empty strings if the driver has no
811
+ information available.
812
+
813
+ """
814
+ logLength = GL.GLint()
815
+ if GL.glIsShader(obj) == GL.GL_TRUE:
816
+ GL.glGetShaderiv(
817
+ obj, GL.GL_INFO_LOG_LENGTH, ctypes.byref(logLength))
818
+ elif GL.glIsProgram(obj) == GL.GL_TRUE:
819
+ GL.glGetProgramiv(
820
+ obj, GL.GL_INFO_LOG_LENGTH, ctypes.byref(logLength))
821
+ else:
822
+ raise ValueError(
823
+ "Specified value of `obj` is not a shader or program.")
824
+
825
+ logBuffer = ctypes.create_string_buffer(logLength.value)
826
+ GL.glGetShaderInfoLog(obj, logLength, None, logBuffer)
827
+
828
+ return logBuffer.value.decode('UTF-8')
829
+
830
+
831
+ def getUniformLocations(program, builtins=False):
832
+ """Get uniform names and locations from a given shader program object.
833
+
834
+ This function works with both standard and ARB program object variants.
835
+
836
+ Parameters
837
+ ----------
838
+ program : int
839
+ Handle of program to retrieve uniforms. Must have originated from a
840
+ :func:`createProgram`, :func:`createProgramObjectARB`, `glCreateProgram`
841
+ or `glCreateProgramObjectARB` call.
842
+ builtins : bool, optional
843
+ Include built-in GLSL uniforms (eg. `gl_ModelViewProjectionMatrix`).
844
+ Default is `False`.
845
+
846
+ Returns
847
+ -------
848
+ dict
849
+ Uniform names and locations.
850
+
851
+ """
852
+ if not GL.glIsProgram(program):
853
+ raise ValueError(
854
+ "Specified value of `program` is not a program object handle.")
855
+
856
+ arraySize = GL.GLint()
857
+ nameLength = GL.GLsizei()
858
+
859
+ # cache uniform locations to avoid looking them up before setting them
860
+ nUniforms = GL.GLint()
861
+ GL.glGetProgramiv(program, GL.GL_ACTIVE_UNIFORMS, ctypes.byref(nUniforms))
862
+
863
+ unifLoc = None
864
+ if nUniforms.value > 0:
865
+ maxUniformLength = GL.GLint()
866
+ GL.glGetProgramiv(
867
+ program,
868
+ GL.GL_ACTIVE_UNIFORM_MAX_LENGTH,
869
+ ctypes.byref(maxUniformLength))
870
+
871
+ unifLoc = {}
872
+ for uniformIdx in range(nUniforms.value):
873
+ unifType = GL.GLenum()
874
+ unifName = (GL.GLchar * maxUniformLength.value)()
875
+
876
+ GL.glGetActiveUniform(
877
+ program,
878
+ uniformIdx,
879
+ maxUniformLength,
880
+ ctypes.byref(nameLength),
881
+ ctypes.byref(arraySize),
882
+ ctypes.byref(unifType),
883
+ unifName)
884
+
885
+ # get location
886
+ loc = GL.glGetUniformLocation(program, unifName)
887
+ # don't include if -1, these are internal types like 'gl_Vertex'
888
+ if not builtins:
889
+ if loc != -1:
890
+ unifLoc[unifName.value] = loc
891
+ else:
892
+ unifLoc[unifName.value] = loc
893
+
894
+ return unifLoc
895
+
896
+
897
+ def getAttribLocations(program, builtins=False):
898
+ """Get attribute names and locations from the specified program object.
899
+
900
+ This function works with both standard and ARB program object variants.
901
+
902
+ Parameters
903
+ ----------
904
+ program : int
905
+ Handle of program to retrieve attributes. Must have originated from a
906
+ :func:`createProgram`, :func:`createProgramObjectARB`, `glCreateProgram`
907
+ or `glCreateProgramObjectARB` call.
908
+ builtins : bool, optional
909
+ Include built-in GLSL attributes (eg. `gl_Vertex`). Default is `False`.
910
+
911
+ Returns
912
+ -------
913
+ dict
914
+ Attribute names and locations.
915
+
916
+ """
917
+ if not GL.glIsProgram(program):
918
+ raise ValueError(
919
+ "Specified value of `program` is not a program object handle.")
920
+
921
+ arraySize = GL.GLint()
922
+ nameLength = GL.GLsizei()
923
+
924
+ nAttribs = GL.GLint()
925
+ GL.glGetProgramiv(program, GL.GL_ACTIVE_ATTRIBUTES, ctypes.byref(nAttribs))
926
+
927
+ attribLoc = None
928
+ if nAttribs.value > 0:
929
+ maxAttribLength = GL.GLint()
930
+ GL.glGetProgramiv(
931
+ program,
932
+ GL.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
933
+ ctypes.byref(maxAttribLength))
934
+
935
+ attribLoc = {}
936
+ for attribIdx in range(nAttribs.value):
937
+ attribType = GL.GLenum()
938
+ attribName = (GL.GLchar * maxAttribLength.value)()
939
+
940
+ GL.glGetActiveAttrib(
941
+ program,
942
+ attribIdx,
943
+ maxAttribLength,
944
+ ctypes.byref(nameLength),
945
+ ctypes.byref(arraySize),
946
+ ctypes.byref(attribType),
947
+ attribName)
948
+
949
+ # get location
950
+ loc = GL.glGetAttribLocation(program, attribName.value)
951
+ # don't include if -1, these are internal types like 'gl_Vertex'
952
+ if not builtins:
953
+ if loc != -1:
954
+ attribLoc[attribName.value] = loc
955
+ else:
956
+ attribLoc[attribName.value] = loc
957
+
958
+ return attribLoc
959
+
960
+ # -----------------------------------
961
+ # GL Query Objects
962
+ # -----------------------------------
963
+
964
+
965
+ class QueryObjectInfo:
966
+ """Object for querying information. This includes GPU timing information."""
967
+ __slots__ = ['name', 'target']
968
+
969
+ def __init__(self, name, target):
970
+ self.name = name
971
+ self.target = target
972
+
973
+ def isValid(self):
974
+ """Check if the name associated with this object is valid."""
975
+ return GL.glIsQuery(self.name) == GL.GL_TRUE
976
+
977
+
978
+ def createQueryObject(target=GL.GL_TIME_ELAPSED):
979
+ """Create a GL query object.
980
+
981
+ Parameters
982
+ ----------
983
+ target : Glenum or int
984
+ Target for the query.
985
+
986
+ Returns
987
+ -------
988
+ QueryObjectInfo
989
+ Query object.
990
+
991
+ Examples
992
+ --------
993
+
994
+ Get GPU time elapsed executing rendering/GL calls associated with some
995
+ stimuli (this is not the difference in absolute time between consecutive
996
+ `beginQuery` and `endQuery` calls!)::
997
+
998
+ # create a new query object
999
+ qGPU = createQueryObject(GL_TIME_ELAPSED)
1000
+
1001
+ beginQuery(query)
1002
+ myStim.draw() # OpenGL calls here
1003
+ endQuery(query)
1004
+
1005
+ # get time elapsed in seconds spent on the GPU
1006
+ timeRendering = getQueryValue(qGPU) * 1e-9
1007
+
1008
+ You can also use queries to test if vertices are occluded, as their samples
1009
+ would be rejected during depth testing::
1010
+
1011
+ drawVAO(shape0, GL_TRIANGLES) # draw the first object
1012
+
1013
+ # check if the object was completely occluded
1014
+ qOcclusion = createQueryObject(GL_ANY_SAMPLES_PASSED)
1015
+
1016
+ # draw the next shape within query context
1017
+ beginQuery(qOcclusion)
1018
+ drawVAO(shape1, GL_TRIANGLES) # draw the second object
1019
+ endQuery(qOcclusion)
1020
+
1021
+ isOccluded = getQueryValue(qOcclusion) == 1
1022
+
1023
+ This can be leveraged to perform occlusion testing/culling, where you can
1024
+ render a `cheap` version of your mesh/shape, then the more expensive version
1025
+ if samples were passed.
1026
+
1027
+ """
1028
+ result = GL.GLuint()
1029
+ GL.glGenQueries(1, ctypes.byref(result))
1030
+
1031
+ return QueryObjectInfo(result, target)
1032
+
1033
+
1034
+ def beginQuery(query):
1035
+ """Begin query.
1036
+
1037
+ Parameters
1038
+ ----------
1039
+ query : QueryObjectInfo
1040
+ Query object descriptor returned by :func:`createQueryObject`.
1041
+
1042
+ """
1043
+ if isinstance(query, (QueryObjectInfo,)):
1044
+ GL.glBeginQuery(query.target, query.name)
1045
+ else:
1046
+ raise TypeError('Type of `query` must be `QueryObjectInfo`.')
1047
+
1048
+
1049
+ def endQuery(query):
1050
+ """End a query.
1051
+
1052
+ Parameters
1053
+ ----------
1054
+ query : QueryObjectInfo
1055
+ Query object descriptor returned by :func:`createQueryObject`,
1056
+ previously passed to :func:`beginQuery`.
1057
+
1058
+ """
1059
+ if isinstance(query, (QueryObjectInfo,)):
1060
+ GL.glEndQuery(query.target)
1061
+ else:
1062
+ raise TypeError('Type of `query` must be `QueryObjectInfo`.')
1063
+
1064
+
1065
+ def getQuery(query):
1066
+ """Get the value stored in a query object.
1067
+
1068
+ Parameters
1069
+ ----------
1070
+ query : QueryObjectInfo
1071
+ Query object descriptor returned by :func:`createQueryObject`,
1072
+ previously passed to :func:`endQuery`.
1073
+
1074
+ """
1075
+ params = GL.GLuint64(0)
1076
+ if isinstance(query, QueryObjectInfo):
1077
+ GL.glGetQueryObjectui64v(
1078
+ query.name,
1079
+ GL.GL_QUERY_RESULT,
1080
+ ctypes.byref(params))
1081
+
1082
+ return params.value
1083
+ else:
1084
+ raise TypeError('Argument `query` must be `QueryObjectInfo` instance.')
1085
+
1086
+
1087
+ def getAbsTimeGPU():
1088
+ """Get the absolute GPU time in nanoseconds.
1089
+
1090
+ Returns
1091
+ -------
1092
+ int
1093
+ Time elapsed in nanoseconds since the OpenGL context was fully realized.
1094
+
1095
+ Examples
1096
+ --------
1097
+ Get the current GPU time in seconds::
1098
+
1099
+ timeInSeconds = getAbsTimeGPU() * 1e-9
1100
+
1101
+ Get the GPU time elapsed::
1102
+
1103
+ t0 = getAbsTimeGPU()
1104
+ # some drawing commands here ...
1105
+ t1 = getAbsTimeGPU()
1106
+ timeElapsed = (t1 - t0) * 1e-9 # take difference, convert to seconds
1107
+
1108
+ """
1109
+ global QUERY_COUNTER
1110
+ if QUERY_COUNTER is None:
1111
+ GL.glGenQueries(1, ctypes.byref(QUERY_COUNTER))
1112
+
1113
+ GL.glQueryCounter(QUERY_COUNTER, GL.GL_TIMESTAMP)
1114
+
1115
+ params = GL.GLuint64(0)
1116
+ GL.glGetQueryObjectui64v(
1117
+ QUERY_COUNTER,
1118
+ GL.GL_QUERY_RESULT,
1119
+ ctypes.byref(params))
1120
+
1121
+ return params.value
1122
+
1123
+
1124
+ # -----------------------------------
1125
+ # Framebuffer Objects (FBO) Functions
1126
+ # -----------------------------------
1127
+ #
1128
+ # The functions below simplify the creation and management of Framebuffer
1129
+ # Objects (FBOs). FBO are containers for image buffers (textures or
1130
+ # renderbuffers) frequently used for off-screen rendering.
1131
+ #
1132
+
1133
+ # FBO descriptor
1134
+ Framebuffer = namedtuple(
1135
+ 'Framebuffer',
1136
+ ['id',
1137
+ 'target',
1138
+ 'userData']
1139
+ )
1140
+
1141
+
1142
+ def createFBO(attachments=()):
1143
+ """Create a Framebuffer Object.
1144
+
1145
+ Parameters
1146
+ ----------
1147
+ attachments : :obj:`list` or :obj:`tuple` of :obj:`tuple`
1148
+ Optional attachments to initialize the Framebuffer with. Attachments are
1149
+ specified as a list of tuples. Each tuple must contain an attachment
1150
+ point (e.g. GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, etc.) and a
1151
+ buffer descriptor type (Renderbuffer or TexImage2D). If using a combined
1152
+ depth/stencil format such as GL_DEPTH24_STENCIL8, GL_DEPTH_ATTACHMENT
1153
+ and GL_STENCIL_ATTACHMENT must be passed the same buffer. Alternatively,
1154
+ one can use GL_DEPTH_STENCIL_ATTACHMENT instead. If using multisample
1155
+ buffers, all attachment images must use the same number of samples!. As
1156
+ an example, one may specify attachments as 'attachments=((
1157
+ GL.GL_COLOR_ATTACHMENT0, frameTexture), (GL.GL_DEPTH_STENCIL_ATTACHMENT,
1158
+ depthRenderBuffer))'.
1159
+
1160
+ Returns
1161
+ -------
1162
+ Framebuffer
1163
+ Framebuffer descriptor.
1164
+
1165
+ Notes
1166
+ -----
1167
+ - All buffers must have the same number of samples.
1168
+ - The 'userData' field of the returned descriptor is a dictionary that
1169
+ can be used to store arbitrary data associated with the FBO.
1170
+ - Framebuffers need a single attachment to be complete.
1171
+
1172
+ Examples
1173
+ --------
1174
+ Create an empty framebuffer with no attachments::
1175
+
1176
+ fbo = createFBO() # invalid until attachments are added
1177
+
1178
+ Create a render target with multiple color texture attachments::
1179
+
1180
+ colorTex = createTexImage2D(1024,1024) # empty texture
1181
+ depthRb = createRenderbuffer(800,600,internalFormat=GL.GL_DEPTH24_STENCIL8)
1182
+
1183
+ # attach images
1184
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo.id)
1185
+ attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
1186
+ attach(GL.GL_DEPTH_ATTACHMENT, depthRb)
1187
+ attach(GL.GL_STENCIL_ATTACHMENT, depthRb)
1188
+ # or attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb)
1189
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
1190
+
1191
+ # above is the same as
1192
+ with useFBO(fbo):
1193
+ attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
1194
+ attach(GL.GL_DEPTH_ATTACHMENT, depthRb)
1195
+ attach(GL.GL_STENCIL_ATTACHMENT, depthRb)
1196
+
1197
+ Examples of userData some custom function might access::
1198
+
1199
+ fbo.userData['flags'] = ['left_eye', 'clear_before_use']
1200
+
1201
+ Using a depth only texture (for shadow mapping?)::
1202
+
1203
+ depthTex = createTexImage2D(800, 600,
1204
+ internalFormat=GL.GL_DEPTH_COMPONENT24,
1205
+ pixelFormat=GL.GL_DEPTH_COMPONENT)
1206
+ fbo = createFBO([(GL.GL_DEPTH_ATTACHMENT, depthTex)]) # is valid
1207
+
1208
+ # discard FBO descriptor, just give me the ID
1209
+ frameBuffer = createFBO().id
1210
+
1211
+ """
1212
+ fboId = GL.GLuint()
1213
+ GL.glGenFramebuffers(1, ctypes.byref(fboId))
1214
+
1215
+ # create a framebuffer descriptor
1216
+ fboDesc = Framebuffer(fboId, GL.GL_FRAMEBUFFER, dict())
1217
+
1218
+ # initial attachments for this framebuffer
1219
+ if attachments:
1220
+ with useFBO(fboDesc):
1221
+ for attachPoint, imageBuffer in attachments:
1222
+ attach(attachPoint, imageBuffer)
1223
+
1224
+ return fboDesc
1225
+
1226
+
1227
+ def attach(attachPoint, imageBuffer):
1228
+ """Attach an image to a specified attachment point on the presently bound
1229
+ FBO.
1230
+
1231
+ Parameters
1232
+ ----------
1233
+ attachPoint :obj:`int`
1234
+ Attachment point for 'imageBuffer' (e.g. GL.GL_COLOR_ATTACHMENT0).
1235
+ imageBuffer : :obj:`TexImage2D` or :obj:`Renderbuffer`
1236
+ Framebuffer-attachable buffer descriptor.
1237
+
1238
+ Examples
1239
+ --------
1240
+ Attach an image to attachment points on the framebuffer::
1241
+
1242
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo)
1243
+ attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
1244
+ attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb)
1245
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, lastBoundFbo)
1246
+
1247
+ # same as above, but using a context manager
1248
+ with useFBO(fbo):
1249
+ attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
1250
+ attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb)
1251
+
1252
+ """
1253
+ # We should also support binding GL names specified as integers. Right now
1254
+ # you need as descriptor which contains the target and name for the buffer.
1255
+ #
1256
+ if isinstance(imageBuffer, (TexImage2D, TexImage2DMultisample)):
1257
+ GL.glFramebufferTexture2D(
1258
+ GL.GL_FRAMEBUFFER,
1259
+ attachPoint,
1260
+ imageBuffer.target,
1261
+ imageBuffer.id, 0)
1262
+ elif isinstance(imageBuffer, Renderbuffer):
1263
+ GL.glFramebufferRenderbuffer(
1264
+ GL.GL_FRAMEBUFFER,
1265
+ attachPoint,
1266
+ imageBuffer.target,
1267
+ imageBuffer.id)
1268
+
1269
+
1270
+ def isComplete():
1271
+ """Check if the currently bound framebuffer is complete.
1272
+
1273
+ Returns
1274
+ -------
1275
+ bool
1276
+ `True` if the presently bound FBO is complete.
1277
+
1278
+ """
1279
+ return GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) == \
1280
+ GL.GL_FRAMEBUFFER_COMPLETE
1281
+
1282
+
1283
+ def deleteFBO(fbo):
1284
+ """Delete a framebuffer.
1285
+
1286
+ """
1287
+ GL.glDeleteFramebuffers(
1288
+ 1, fbo.id if isinstance(fbo, Framebuffer) else int(fbo))
1289
+
1290
+
1291
+ def blitFBO(srcRect, dstRect=None, filter=GL.GL_LINEAR):
1292
+ """Copy a block of pixels between framebuffers via blitting. Read and draw
1293
+ framebuffers must be bound prior to calling this function. Beware, the
1294
+ scissor box and viewport are changed when this is called to dstRect.
1295
+
1296
+ Parameters
1297
+ ----------
1298
+ srcRect : :obj:`list` of :obj:`int`
1299
+ List specifying the top-left and bottom-right coordinates of the region
1300
+ to copy from (<X0>, <Y0>, <X1>, <Y1>).
1301
+ dstRect : :obj:`list` of :obj:`int` or :obj:`None`
1302
+ List specifying the top-left and bottom-right coordinates of the region
1303
+ to copy to (<X0>, <Y0>, <X1>, <Y1>). If None, srcRect is used for
1304
+ dstRect.
1305
+ filter : :obj:`int`
1306
+ Interpolation method to use if the image is stretched, default is
1307
+ GL_LINEAR, but can also be GL_NEAREST.
1308
+
1309
+ Returns
1310
+ -------
1311
+ None
1312
+
1313
+ Examples
1314
+ --------
1315
+ Blitting pixels from on FBO to another::
1316
+
1317
+ # bind framebuffer to read pixels from
1318
+ GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, srcFbo)
1319
+
1320
+ # bind framebuffer to draw pixels to
1321
+ GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, dstFbo)
1322
+
1323
+ gltools.blitFBO((0,0,800,600), (0,0,800,600))
1324
+
1325
+ # unbind both read and draw buffers
1326
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
1327
+
1328
+ """
1329
+ # in most cases srcRect and dstRect will be the same.
1330
+ if dstRect is None:
1331
+ dstRect = srcRect
1332
+
1333
+ # GL.glViewport(*dstRect)
1334
+ # GL.glEnable(GL.GL_SCISSOR_TEST)
1335
+ # GL.glScissor(*dstRect)
1336
+ GL.glBlitFramebuffer(srcRect[0], srcRect[1], srcRect[2], srcRect[3],
1337
+ dstRect[0], dstRect[1], dstRect[2], dstRect[3],
1338
+ GL.GL_COLOR_BUFFER_BIT, # colors only for now
1339
+ filter)
1340
+
1341
+ # GL.glDisable(GL.GL_SCISSOR_TEST)
1342
+
1343
+
1344
+ @contextmanager
1345
+ def useFBO(fbo):
1346
+ """Context manager for Framebuffer Object bindings. This function yields
1347
+ the framebuffer name as an integer.
1348
+
1349
+ Parameters
1350
+ ----------
1351
+ fbo :obj:`int` or :obj:`Framebuffer`
1352
+ OpenGL Framebuffer Object name/ID or descriptor.
1353
+
1354
+ Yields
1355
+ -------
1356
+ int
1357
+ OpenGL name of the framebuffer bound in the context.
1358
+
1359
+ Examples
1360
+ --------
1361
+ Using a framebuffer context manager::
1362
+
1363
+ # FBO bound somewhere deep in our code
1364
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, someOtherFBO)
1365
+
1366
+ ...
1367
+
1368
+ # create a new FBO, but we have no idea what the currently bound FBO is
1369
+ fbo = createFBO()
1370
+
1371
+ # use a context to bind attachments
1372
+ with bindFBO(fbo):
1373
+ attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
1374
+ attach(GL.GL_DEPTH_ATTACHMENT, depthRb)
1375
+ attach(GL.GL_STENCIL_ATTACHMENT, depthRb)
1376
+ isComplete = gltools.isComplete()
1377
+
1378
+ # someOtherFBO is still bound!
1379
+
1380
+ """
1381
+ prevFBO = GL.GLint()
1382
+ GL.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, ctypes.byref(prevFBO))
1383
+ toBind = fbo.id if isinstance(fbo, Framebuffer) else int(fbo)
1384
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, toBind)
1385
+ try:
1386
+ yield toBind
1387
+ finally:
1388
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, prevFBO.value)
1389
+
1390
+
1391
+ # ------------------------------
1392
+ # Renderbuffer Objects Functions
1393
+ # ------------------------------
1394
+ #
1395
+ # The functions below handle the creation and management of Renderbuffers
1396
+ # Objects.
1397
+ #
1398
+
1399
+ # Renderbuffer descriptor type
1400
+ Renderbuffer = namedtuple(
1401
+ 'Renderbuffer',
1402
+ ['id',
1403
+ 'target',
1404
+ 'width',
1405
+ 'height',
1406
+ 'internalFormat',
1407
+ 'samples',
1408
+ 'multiSample', # boolean, check if a texture is multisample
1409
+ 'userData'] # dictionary for user defined data
1410
+ )
1411
+
1412
+
1413
+ def createRenderbuffer(width, height, internalFormat=GL.GL_RGBA8, samples=1):
1414
+ """Create a new Renderbuffer Object with a specified internal format. A
1415
+ multisample storage buffer is created if samples > 1.
1416
+
1417
+ Renderbuffers contain image data and are optimized for use as render
1418
+ targets. See https://www.khronos.org/opengl/wiki/Renderbuffer_Object for
1419
+ more information.
1420
+
1421
+ Parameters
1422
+ ----------
1423
+ width : :obj:`int`
1424
+ Buffer width in pixels.
1425
+ height : :obj:`int`
1426
+ Buffer height in pixels.
1427
+ internalFormat : :obj:`int`
1428
+ Format for renderbuffer data (e.g. GL_RGBA8, GL_DEPTH24_STENCIL8).
1429
+ samples : :obj:`int`
1430
+ Number of samples for multi-sampling, should be >1 and power-of-two.
1431
+ Work with one sample, but will raise a warning.
1432
+
1433
+ Returns
1434
+ -------
1435
+ Renderbuffer
1436
+ A descriptor of the created renderbuffer.
1437
+
1438
+ Notes
1439
+ -----
1440
+ The 'userData' field of the returned descriptor is a dictionary that can
1441
+ be used to store arbitrary data associated with the buffer.
1442
+
1443
+ """
1444
+ width = int(width)
1445
+ height = int(height)
1446
+
1447
+ # create a new renderbuffer ID
1448
+ rbId = GL.GLuint()
1449
+ GL.glGenRenderbuffers(1, ctypes.byref(rbId))
1450
+ GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, rbId)
1451
+
1452
+ if samples > 1:
1453
+ # determine if the 'samples' value is valid
1454
+ maxSamples = getIntegerv(GL.GL_MAX_SAMPLES)
1455
+ if (samples & (samples - 1)) != 0:
1456
+ raise ValueError('Invalid number of samples, must be power-of-two.')
1457
+ elif samples > maxSamples:
1458
+ raise ValueError('Invalid number of samples, must be <{}.'.format(
1459
+ maxSamples))
1460
+
1461
+ # create a multisample render buffer storage
1462
+ GL.glRenderbufferStorageMultisample(
1463
+ GL.GL_RENDERBUFFER,
1464
+ samples,
1465
+ internalFormat,
1466
+ width,
1467
+ height)
1468
+
1469
+ else:
1470
+ GL.glRenderbufferStorage(
1471
+ GL.GL_RENDERBUFFER,
1472
+ internalFormat,
1473
+ width,
1474
+ height)
1475
+
1476
+ # done, unbind it
1477
+ GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0)
1478
+
1479
+ return Renderbuffer(rbId,
1480
+ GL.GL_RENDERBUFFER,
1481
+ width,
1482
+ height,
1483
+ internalFormat,
1484
+ samples,
1485
+ samples > 1,
1486
+ dict())
1487
+
1488
+
1489
+ def deleteRenderbuffer(renderBuffer):
1490
+ """Free the resources associated with a renderbuffer. This invalidates the
1491
+ renderbuffer's ID.
1492
+
1493
+ """
1494
+ GL.glDeleteRenderbuffers(1, renderBuffer.id)
1495
+
1496
+
1497
+ # -----------------
1498
+ # Texture Functions
1499
+ # -----------------
1500
+
1501
+ # 2D texture descriptor. You can 'wrap' existing texture IDs with TexImage2D to
1502
+ # use them with functions that require that type as input.
1503
+ #
1504
+
1505
+ class TexImage2D:
1506
+ """Descriptor for a 2D texture.
1507
+
1508
+ This class is used for bookkeeping 2D textures stored in video memory.
1509
+ Information about the texture (eg. `width` and `height`) is available via
1510
+ class attributes. Attributes should never be modified directly.
1511
+
1512
+ """
1513
+ __slots__ = ['width',
1514
+ 'height',
1515
+ 'target',
1516
+ '_name',
1517
+ 'level',
1518
+ 'internalFormat',
1519
+ 'pixelFormat',
1520
+ 'dataType',
1521
+ 'unpackAlignment',
1522
+ '_texParams',
1523
+ '_isBound',
1524
+ '_unit',
1525
+ '_texParamsNeedUpdate']
1526
+
1527
+ def __init__(self,
1528
+ name=0,
1529
+ target=GL.GL_TEXTURE_2D,
1530
+ width=64,
1531
+ height=64,
1532
+ level=0,
1533
+ internalFormat=GL.GL_RGBA,
1534
+ pixelFormat=GL.GL_RGBA,
1535
+ dataType=GL.GL_FLOAT,
1536
+ unpackAlignment=4,
1537
+ texParams=None):
1538
+ """
1539
+ Parameters
1540
+ ----------
1541
+ name : `int` or `GLuint`
1542
+ OpenGL handle for texture. Is `0` if uninitialized.
1543
+ target : :obj:`int`
1544
+ The target texture should only be either GL_TEXTURE_2D or
1545
+ GL_TEXTURE_RECTANGLE.
1546
+ width : :obj:`int`
1547
+ Texture width in pixels.
1548
+ height : :obj:`int`
1549
+ Texture height in pixels.
1550
+ level : :obj:`int`
1551
+ LOD number of the texture, should be 0 if GL_TEXTURE_RECTANGLE is
1552
+ the target.
1553
+ internalFormat : :obj:`int`
1554
+ Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
1555
+ pixelFormat : :obj:`int`
1556
+ Pixel data format (e.g. GL_RGBA, GL_DEPTH_STENCIL)
1557
+ dataType : :obj:`int`
1558
+ Data type for pixel data (e.g. GL_FLOAT, GL_UNSIGNED_BYTE).
1559
+ unpackAlignment : :obj:`int`
1560
+ Alignment requirements of each row in memory. Default is 4.
1561
+ texParams : :obj:`list` of :obj:`tuple` of :obj:`int`
1562
+ Optional texture parameters specified as `dict`. These values are
1563
+ passed to `glTexParameteri`. Each tuple must contain a parameter
1564
+ name and value. For example, `texParameters={
1565
+ GL.GL_TEXTURE_MIN_FILTER: GL.GL_LINEAR, GL.GL_TEXTURE_MAG_FILTER:
1566
+ GL.GL_LINEAR}`. These can be changed and will be updated the next
1567
+ time this instance is passed to :func:`bindTexture`.
1568
+
1569
+ """
1570
+ # fields for texture information
1571
+ self.name = name
1572
+ self.width = width
1573
+ self.height = height
1574
+ self.target = target
1575
+ self.level = level
1576
+ self.internalFormat = internalFormat
1577
+ self.pixelFormat = pixelFormat
1578
+ self.dataType = dataType
1579
+ self.unpackAlignment = unpackAlignment
1580
+ self._texParams = {}
1581
+
1582
+ # set texture parameters
1583
+ if texParams is not None:
1584
+ for key, val in texParams.items():
1585
+ self._texParams[key] = val
1586
+
1587
+ # internal data
1588
+ self._isBound = False # True if the texture has been bound
1589
+ self._unit = None # texture unit assigned to this texture
1590
+ self._texParamsNeedUpdate = True # update texture parameters
1591
+
1592
+ @property
1593
+ def name(self):
1594
+ return self._name
1595
+
1596
+ @name.setter
1597
+ def name(self, value):
1598
+ if not isinstance(value, GL.GLuint):
1599
+ self._name = GL.GLuint(int(value))
1600
+ else:
1601
+ self._name = value
1602
+
1603
+ @property
1604
+ def size(self):
1605
+ """Size of the texture [w, h] in pixels (`int`, `int`)."""
1606
+ return self.width, self.height
1607
+
1608
+ @property
1609
+ def texParams(self):
1610
+ """Texture parameters."""
1611
+ self._texParamsNeedUpdate = True
1612
+ return self._texParams
1613
+
1614
+ @texParams.setter
1615
+ def texParams(self, value):
1616
+ """Texture parameters."""
1617
+ self._texParamsNeedUpdate = True
1618
+ self._texParams = value
1619
+
1620
+
1621
+ def createTexImage2D(width, height, target=GL.GL_TEXTURE_2D, level=0,
1622
+ internalFormat=GL.GL_RGBA8, pixelFormat=GL.GL_RGBA,
1623
+ dataType=GL.GL_FLOAT, data=None, unpackAlignment=4,
1624
+ texParams=None):
1625
+ """Create a 2D texture in video memory. This can only create a single 2D
1626
+ texture with targets `GL_TEXTURE_2D` or `GL_TEXTURE_RECTANGLE`.
1627
+
1628
+ Parameters
1629
+ ----------
1630
+ width : :obj:`int`
1631
+ Texture width in pixels.
1632
+ height : :obj:`int`
1633
+ Texture height in pixels.
1634
+ target : :obj:`int`
1635
+ The target texture should only be either GL_TEXTURE_2D or
1636
+ GL_TEXTURE_RECTANGLE.
1637
+ level : :obj:`int`
1638
+ LOD number of the texture, should be 0 if GL_TEXTURE_RECTANGLE is the
1639
+ target.
1640
+ internalFormat : :obj:`int`
1641
+ Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
1642
+ pixelFormat : :obj:`int`
1643
+ Pixel data format (e.g. GL_RGBA, GL_DEPTH_STENCIL)
1644
+ dataType : :obj:`int`
1645
+ Data type for pixel data (e.g. GL_FLOAT, GL_UNSIGNED_BYTE).
1646
+ data : :obj:`ctypes` or :obj:`None`
1647
+ Ctypes pointer to image data. If None is specified, the texture will be
1648
+ created but pixel data will be uninitialized.
1649
+ unpackAlignment : :obj:`int`
1650
+ Alignment requirements of each row in memory. Default is 4.
1651
+ texParams : :obj:`dict`
1652
+ Optional texture parameters specified as `dict`. These values are passed
1653
+ to `glTexParameteri`. Each tuple must contain a parameter name and
1654
+ value. For example, `texParameters={GL.GL_TEXTURE_MIN_FILTER:
1655
+ GL.GL_LINEAR, GL.GL_TEXTURE_MAG_FILTER: GL.GL_LINEAR}`.
1656
+
1657
+ Returns
1658
+ -------
1659
+ TexImage2D
1660
+ A `TexImage2D` descriptor.
1661
+
1662
+ Notes
1663
+ -----
1664
+ The 'userData' field of the returned descriptor is a dictionary that can
1665
+ be used to store arbitrary data associated with the texture.
1666
+
1667
+ Previous textures are unbound after calling 'createTexImage2D'.
1668
+
1669
+ Examples
1670
+ --------
1671
+ Creating a texture from an image file::
1672
+
1673
+ import pyglet.gl as GL # using Pyglet for now
1674
+
1675
+ # empty texture
1676
+ textureDesc = createTexImage2D(1024, 1024, internalFormat=GL.GL_RGBA8)
1677
+
1678
+ # load texture data from an image file using Pillow and NumPy
1679
+ from PIL import Image
1680
+ import numpy as np
1681
+ im = Image.open(imageFile) # 8bpp!
1682
+ im = im.transpose(Image.FLIP_TOP_BOTTOM) # OpenGL origin is at bottom
1683
+ im = im.convert("RGBA")
1684
+ pixelData = np.array(im).ctypes # convert to ctypes!
1685
+
1686
+ width = pixelData.shape[1]
1687
+ height = pixelData.shape[0]
1688
+ textureDesc = gltools.createTexImage2D(
1689
+ width,
1690
+ height,
1691
+ internalFormat=GL.GL_RGBA,
1692
+ pixelFormat=GL.GL_RGBA,
1693
+ dataType=GL.GL_UNSIGNED_BYTE,
1694
+ data=pixelData,
1695
+ unpackAlignment=1,
1696
+ texParameters=[(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR),
1697
+ (GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)])
1698
+
1699
+ GL.glBindTexture(GL.GL_TEXTURE_2D, textureDesc.id)
1700
+
1701
+ """
1702
+ width = int(width)
1703
+ height = int(height)
1704
+
1705
+ if width <= 0 or height <= 0:
1706
+ raise ValueError("Invalid image dimensions {} x {}.".format(
1707
+ width, height))
1708
+
1709
+ if target == GL.GL_TEXTURE_RECTANGLE:
1710
+ if level != 0:
1711
+ raise ValueError("Invalid level for target GL_TEXTURE_RECTANGLE, "
1712
+ "must be 0.")
1713
+ GL.glEnable(GL.GL_TEXTURE_RECTANGLE)
1714
+
1715
+ texId = GL.GLuint()
1716
+ GL.glGenTextures(1, ctypes.byref(texId))
1717
+
1718
+ GL.glBindTexture(target, texId)
1719
+ GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, int(unpackAlignment))
1720
+ GL.glTexImage2D(target, level, internalFormat,
1721
+ width, height, 0,
1722
+ pixelFormat, dataType, data)
1723
+
1724
+ # apply texture parameters
1725
+ if texParams is not None:
1726
+ for pname, param in texParams.items():
1727
+ GL.glTexParameteri(target, pname, param)
1728
+
1729
+ # new texture descriptor
1730
+ tex = TexImage2D(name=texId,
1731
+ target=target,
1732
+ width=width,
1733
+ height=height,
1734
+ internalFormat=internalFormat,
1735
+ level=level,
1736
+ pixelFormat=pixelFormat,
1737
+ dataType=dataType,
1738
+ unpackAlignment=unpackAlignment,
1739
+ texParams=texParams)
1740
+
1741
+ tex._texParamsNeedUpdate = False
1742
+
1743
+ GL.glBindTexture(target, 0)
1744
+
1745
+ return tex
1746
+
1747
+
1748
+ def createTexImage2dFromFile(imgFile, transpose=True):
1749
+ """Load an image from file directly into a texture.
1750
+
1751
+ This is a convenience function to quickly get an image file loaded into a
1752
+ 2D texture. The image is converted to RGBA format. Texture parameters are
1753
+ set for linear interpolation.
1754
+
1755
+ Parameters
1756
+ ----------
1757
+ imgFile : str
1758
+ Path to the image file.
1759
+ transpose : bool
1760
+ Flip the image so it appears upright when displayed in OpenGL image
1761
+ coordinates.
1762
+
1763
+ Returns
1764
+ -------
1765
+ TexImage2D
1766
+ Texture descriptor.
1767
+
1768
+ """
1769
+ # Attempt to find file with substitution (handles e.g. default.png)
1770
+ tryImg = findImageFile(imgFile, checkResources=True)
1771
+ if tryImg is not None:
1772
+ imgFile = tryImg
1773
+ im = Image.open(imgFile) # 8bpp!
1774
+ if transpose:
1775
+ im = im.transpose(Image.FLIP_TOP_BOTTOM) # OpenGL origin is at bottom
1776
+
1777
+ im = im.convert("RGBA")
1778
+ pixelData = np.array(im).ctypes # convert to ctypes!
1779
+
1780
+ width = pixelData.shape[1]
1781
+ height = pixelData.shape[0]
1782
+ textureDesc = createTexImage2D(
1783
+ width,
1784
+ height,
1785
+ internalFormat=GL.GL_RGBA,
1786
+ pixelFormat=GL.GL_RGBA,
1787
+ dataType=GL.GL_UNSIGNED_BYTE,
1788
+ data=pixelData,
1789
+ unpackAlignment=1,
1790
+ texParams={GL.GL_TEXTURE_MAG_FILTER: GL.GL_LINEAR,
1791
+ GL.GL_TEXTURE_MIN_FILTER: GL.GL_LINEAR})
1792
+
1793
+ return textureDesc
1794
+
1795
+
1796
+ class TexCubeMap:
1797
+ """Descriptor for a cube map texture..
1798
+
1799
+ This class is used for bookkeeping cube maps stored in video memory.
1800
+ Information about the texture (eg. `width` and `height`) is available via
1801
+ class attributes. Attributes should never be modified directly.
1802
+
1803
+ """
1804
+ __slots__ = ['width',
1805
+ 'height',
1806
+ 'target',
1807
+ '_name',
1808
+ 'level',
1809
+ 'internalFormat',
1810
+ 'pixelFormat',
1811
+ 'dataType',
1812
+ 'unpackAlignment',
1813
+ '_texParams',
1814
+ '_isBound',
1815
+ '_unit',
1816
+ '_texParamsNeedUpdate']
1817
+
1818
+ def __init__(self,
1819
+ name=0,
1820
+ target=GL.GL_TEXTURE_CUBE_MAP,
1821
+ width=64,
1822
+ height=64,
1823
+ level=0,
1824
+ internalFormat=GL.GL_RGBA,
1825
+ pixelFormat=GL.GL_RGBA,
1826
+ dataType=GL.GL_FLOAT,
1827
+ unpackAlignment=4,
1828
+ texParams=None):
1829
+ """
1830
+ Parameters
1831
+ ----------
1832
+ name : `int` or `GLuint`
1833
+ OpenGL handle for texture. Is `0` if uninitialized.
1834
+ target : :obj:`int`
1835
+ The target texture should only be `GL_TEXTURE_CUBE_MAP`.
1836
+ width : :obj:`int`
1837
+ Texture width in pixels.
1838
+ height : :obj:`int`
1839
+ Texture height in pixels.
1840
+ level : :obj:`int`
1841
+ LOD number of the texture.
1842
+ internalFormat : :obj:`int`
1843
+ Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
1844
+ pixelFormat : :obj:`int`
1845
+ Pixel data format (e.g. GL_RGBA, GL_DEPTH_STENCIL)
1846
+ dataType : :obj:`int`
1847
+ Data type for pixel data (e.g. GL_FLOAT, GL_UNSIGNED_BYTE).
1848
+ unpackAlignment : :obj:`int`
1849
+ Alignment requirements of each row in memory. Default is 4.
1850
+ texParams : :obj:`list` of :obj:`tuple` of :obj:`int`
1851
+ Optional texture parameters specified as `dict`. These values are
1852
+ passed to `glTexParameteri`. Each tuple must contain a parameter
1853
+ name and value. For example, `texParameters={
1854
+ GL.GL_TEXTURE_MIN_FILTER: GL.GL_LINEAR, GL.GL_TEXTURE_MAG_FILTER:
1855
+ GL.GL_LINEAR}`. These can be changed and will be updated the next
1856
+ time this instance is passed to :func:`bindTexture`.
1857
+
1858
+ """
1859
+ # fields for texture information
1860
+ self.name = name
1861
+ self.width = width
1862
+ self.height = height
1863
+ self.target = target
1864
+ self.level = level
1865
+ self.internalFormat = internalFormat
1866
+ self.pixelFormat = pixelFormat
1867
+ self.dataType = dataType
1868
+ self.unpackAlignment = unpackAlignment
1869
+ self._texParams = {}
1870
+
1871
+ # set texture parameters
1872
+ if texParams is not None:
1873
+ for key, val in texParams.items():
1874
+ self._texParams[key] = val
1875
+
1876
+ # internal data
1877
+ self._isBound = False # True if the texture has been bound
1878
+ self._unit = None # texture unit assigned to this texture
1879
+ self._texParamsNeedUpdate = True # update texture parameters
1880
+
1881
+ @property
1882
+ def name(self):
1883
+ return self._name
1884
+
1885
+ @name.setter
1886
+ def name(self, value):
1887
+ if not isinstance(value, GL.GLuint):
1888
+ self._name = GL.GLuint(int(value))
1889
+ else:
1890
+ self._name = value
1891
+
1892
+ @property
1893
+ def size(self):
1894
+ """Size of a single cubemap face [w, h] in pixels (`int`, `int`)."""
1895
+ return self.width, self.height
1896
+
1897
+ @property
1898
+ def texParams(self):
1899
+ """Texture parameters."""
1900
+ self._texParamsNeedUpdate = True
1901
+ return self._texParams
1902
+
1903
+ @texParams.setter
1904
+ def texParams(self, value):
1905
+ """Texture parameters."""
1906
+ self._texParamsNeedUpdate = True
1907
+ self._texParams = value
1908
+
1909
+
1910
+ def createCubeMap(width, height, target=GL.GL_TEXTURE_CUBE_MAP, level=0,
1911
+ internalFormat=GL.GL_RGBA, pixelFormat=GL.GL_RGBA,
1912
+ dataType=GL.GL_UNSIGNED_BYTE, data=None, unpackAlignment=4,
1913
+ texParams=None):
1914
+ """Create a cubemap.
1915
+
1916
+ Parameters
1917
+ ----------
1918
+ name : `int` or `GLuint`
1919
+ OpenGL handle for the cube map. Is `0` if uninitialized.
1920
+ target : :obj:`int`
1921
+ The target texture should only be `GL_TEXTURE_CUBE_MAP`.
1922
+ width : :obj:`int`
1923
+ Texture width in pixels.
1924
+ height : :obj:`int`
1925
+ Texture height in pixels.
1926
+ level : :obj:`int`
1927
+ LOD number of the texture.
1928
+ internalFormat : :obj:`int`
1929
+ Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
1930
+ pixelFormat : :obj:`int`
1931
+ Pixel data format (e.g. GL_RGBA, GL_DEPTH_STENCIL)
1932
+ dataType : :obj:`int`
1933
+ Data type for pixel data (e.g. GL_FLOAT, GL_UNSIGNED_BYTE).
1934
+ data : list or tuple
1935
+ List of six ctypes pointers to image data for each cubemap face. Image
1936
+ data is assigned to a face by index [+X, -X, +Y, -Y, +Z, -Z]. All images
1937
+ must have the same size as specified by `width` and `height`.
1938
+ unpackAlignment : :obj:`int`
1939
+ Alignment requirements of each row in memory. Default is 4.
1940
+ texParams : :obj:`list` of :obj:`tuple` of :obj:`int`
1941
+ Optional texture parameters specified as `dict`. These values are
1942
+ passed to `glTexParameteri`. Each tuple must contain a parameter
1943
+ name and value. For example, `texParameters={
1944
+ GL.GL_TEXTURE_MIN_FILTER: GL.GL_LINEAR, GL.GL_TEXTURE_MAG_FILTER:
1945
+ GL.GL_LINEAR}`. These can be changed and will be updated the next
1946
+ time this instance is passed to :func:`bindTexture`.
1947
+
1948
+ """
1949
+ texId = GL.GLuint()
1950
+ GL.glGenTextures(1, ctypes.byref(texId))
1951
+ GL.glBindTexture(target, texId)
1952
+
1953
+ # create faces of the cube map
1954
+ for face in range(6):
1955
+ GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, int(unpackAlignment))
1956
+ GL.glTexImage2D(GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level,
1957
+ internalFormat, width, height, 0, pixelFormat, dataType,
1958
+ data[face] if data is not None else data)
1959
+
1960
+ # apply texture parameters
1961
+ if texParams is not None:
1962
+ for pname, param in texParams.items():
1963
+ GL.glTexParameteri(target, pname, param)
1964
+
1965
+ GL.glBindTexture(target, 0)
1966
+
1967
+ tex = TexCubeMap(name=texId,
1968
+ target=target,
1969
+ width=width,
1970
+ height=height,
1971
+ internalFormat=internalFormat,
1972
+ level=level,
1973
+ pixelFormat=pixelFormat,
1974
+ dataType=dataType,
1975
+ unpackAlignment=unpackAlignment,
1976
+ texParams=texParams)
1977
+
1978
+ return tex
1979
+
1980
+
1981
+ def bindTexture(texture, unit=None, enable=True):
1982
+ """Bind a texture.
1983
+
1984
+ Function binds `texture` to `unit` (if specified). If `unit` is `None`, the
1985
+ texture will be bound but not assigned to a texture unit.
1986
+
1987
+ Parameters
1988
+ ----------
1989
+ texture : TexImage2D
1990
+ Texture descriptor to bind.
1991
+ unit : int, optional
1992
+ Texture unit to associated the texture with.
1993
+ enable : bool
1994
+ Enable textures upon binding.
1995
+
1996
+ """
1997
+ if not texture._isBound:
1998
+ if enable:
1999
+ GL.glEnable(texture.target)
2000
+
2001
+ GL.glBindTexture(texture.target, texture.name)
2002
+ texture._isBound = True
2003
+
2004
+ if unit is not None:
2005
+ texture._unit = unit
2006
+ GL.glActiveTexture(GL.GL_TEXTURE0 + unit)
2007
+
2008
+ # update texture parameters if they have been accessed (changed?)
2009
+ if texture._texParamsNeedUpdate:
2010
+ for pname, param in texture._texParams.items():
2011
+ GL.glTexParameteri(texture.target, pname, param)
2012
+ texture._texParamsNeedUpdate = False
2013
+
2014
+
2015
+ def unbindTexture(texture=None):
2016
+ """Unbind a texture.
2017
+
2018
+ Parameters
2019
+ ----------
2020
+ texture : TexImage2D
2021
+ Texture descriptor to unbind.
2022
+
2023
+ """
2024
+ if texture._isBound:
2025
+ # set the texture unit
2026
+ if texture._unit is not None:
2027
+ GL.glActiveTexture(GL.GL_TEXTURE0 + texture._unit)
2028
+ texture._unit = None
2029
+
2030
+ GL.glBindTexture(texture.target, 0)
2031
+ texture._isBound = False
2032
+
2033
+ GL.glDisable(texture.target)
2034
+ else:
2035
+ raise RuntimeError('Trying to unbind a texture that was not previously'
2036
+ 'bound.')
2037
+
2038
+
2039
+ # Descriptor for 2D mutlisampled texture
2040
+ TexImage2DMultisample = namedtuple(
2041
+ 'TexImage2D',
2042
+ ['id',
2043
+ 'target',
2044
+ 'width',
2045
+ 'height',
2046
+ 'internalFormat',
2047
+ 'samples',
2048
+ 'multisample',
2049
+ 'userData'])
2050
+
2051
+
2052
+ def createTexImage2DMultisample(width, height,
2053
+ target=GL.GL_TEXTURE_2D_MULTISAMPLE, samples=1,
2054
+ internalFormat=GL.GL_RGBA8, texParameters=()):
2055
+ """Create a 2D multisampled texture.
2056
+
2057
+ Parameters
2058
+ ----------
2059
+ width : :obj:`int`
2060
+ Texture width in pixels.
2061
+ height : :obj:`int`
2062
+ Texture height in pixels.
2063
+ target : :obj:`int`
2064
+ The target texture (e.g. GL_TEXTURE_2D_MULTISAMPLE).
2065
+ samples : :obj:`int`
2066
+ Number of samples for multi-sampling, should be >1 and power-of-two.
2067
+ Work with one sample, but will raise a warning.
2068
+ internalFormat : :obj:`int`
2069
+ Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
2070
+ texParameters : :obj:`list` of :obj:`tuple` of :obj:`int`
2071
+ Optional texture parameters specified as a list of tuples. These values
2072
+ are passed to 'glTexParameteri'. Each tuple must contain a parameter
2073
+ name and value. For example, texParameters=[(GL.GL_TEXTURE_MIN_FILTER,
2074
+ GL.GL_LINEAR), (GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)]
2075
+
2076
+ Returns
2077
+ -------
2078
+ TexImage2DMultisample
2079
+ A TexImage2DMultisample descriptor.
2080
+
2081
+ """
2082
+ width = int(width)
2083
+ height = int(height)
2084
+
2085
+ if width <= 0 or height <= 0:
2086
+ raise ValueError("Invalid image dimensions {} x {}.".format(
2087
+ width, height))
2088
+
2089
+ # determine if the 'samples' value is valid
2090
+ maxSamples = getIntegerv(GL.GL_MAX_SAMPLES)
2091
+ if (samples & (samples - 1)) != 0:
2092
+ raise ValueError('Invalid number of samples, must be power-of-two.')
2093
+ elif samples <= 0 or samples > maxSamples:
2094
+ raise ValueError('Invalid number of samples, must be <{}.'.format(
2095
+ maxSamples))
2096
+
2097
+ colorTexId = GL.GLuint()
2098
+ GL.glGenTextures(1, ctypes.byref(colorTexId))
2099
+ GL.glBindTexture(target, colorTexId)
2100
+ GL.glTexImage2DMultisample(
2101
+ target, samples, internalFormat, width, height, GL.GL_TRUE)
2102
+
2103
+ # apply texture parameters
2104
+ if texParameters:
2105
+ for pname, param in texParameters:
2106
+ GL.glTexParameteri(target, pname, param)
2107
+
2108
+ GL.glBindTexture(target, 0)
2109
+
2110
+ return TexImage2DMultisample(colorTexId,
2111
+ target,
2112
+ width,
2113
+ height,
2114
+ internalFormat,
2115
+ samples,
2116
+ True,
2117
+ dict())
2118
+
2119
+
2120
+ def deleteTexture(texture):
2121
+ """Free the resources associated with a texture. This invalidates the
2122
+ texture's ID.
2123
+
2124
+ """
2125
+ if not texture._isBound:
2126
+ GL.glDeleteTextures(1, texture.name)
2127
+ texture.name = 0 # invalidate
2128
+ else:
2129
+ raise RuntimeError("Attempting to delete texture which is presently "
2130
+ "bound.")
2131
+
2132
+
2133
+ # --------------------------
2134
+ # Vertex Array Objects (VAO)
2135
+ #
2136
+
2137
+ class VertexArrayInfo:
2138
+ """Vertex array object (VAO) descriptor.
2139
+
2140
+ This class only stores information about the VAO it refers to, it does not
2141
+ contain any actual array data associated with the VAO. Calling
2142
+ :func:`createVAO` returns instances of this class.
2143
+
2144
+ If `isLegacy` is `True`, attribute binding states are using deprecated (but
2145
+ still supported) pointer definition calls (eg. `glVertexPointer`). This is
2146
+ to ensure backwards compatibility. The keys stored in `activeAttribs` must
2147
+ be `GLenum` types such as `GL_VERTEX_ARRAY`.
2148
+
2149
+ Parameters
2150
+ ----------
2151
+ name : int
2152
+ OpenGL handle for the VAO.
2153
+ count : int
2154
+ Number of vertex elements. If `indexBuffer` is not `None`, count
2155
+ corresponds to the number of elements in the index buffer.
2156
+ activeAttribs : dict
2157
+ Attributes and buffers defined as part of this VAO state. Keys are
2158
+ attribute pointer indices or capabilities (ie. GL_VERTEX_ARRAY).
2159
+ Modifying these values will not update the VAO state.
2160
+ indexBuffer : VertexBufferInfo, optional
2161
+ Buffer object for indices.
2162
+ attribDivisors : dict, optional
2163
+ Divisors for each attribute.
2164
+ isLegacy : bool
2165
+ Array pointers were defined using the deprecated OpenGL API. If `True`,
2166
+ the VAO may work with older GLSL shaders versions and the fixed-function
2167
+ pipeline.
2168
+ userData : dict or None, optional
2169
+ Optional user defined data associated with this VAO.
2170
+
2171
+ """
2172
+ __slots__ = ['name', 'count', 'activeAttribs', 'indexBuffer', 'isLegacy',
2173
+ 'userData', 'attribDivisors']
2174
+
2175
+ def __init__(self,
2176
+ name=0,
2177
+ count=0,
2178
+ activeAttribs=None,
2179
+ indexBuffer=None,
2180
+ attribDivisors=None,
2181
+ isLegacy=False,
2182
+ userData=None):
2183
+ self.name = name
2184
+ self.activeAttribs = activeAttribs
2185
+ self.count = count
2186
+ self.indexBuffer = indexBuffer
2187
+ self.attribDivisors = attribDivisors
2188
+ self.isLegacy = isLegacy
2189
+
2190
+ if userData is None:
2191
+ self.userData = {}
2192
+ elif isinstance(userData, dict):
2193
+ self.userData = userData
2194
+ else:
2195
+ raise TypeError('Invalid type for `userData`.')
2196
+
2197
+ def __hash__(self):
2198
+ return hash((self.name, self.isLegacy))
2199
+
2200
+ def __eq__(self, other):
2201
+ """Equality test between VAO object names."""
2202
+ return self.name == other.name
2203
+
2204
+ def __ne__(self, other):
2205
+ """Inequality test between VAO object names."""
2206
+ return self.name != other.name
2207
+
2208
+
2209
+ def createVAO(attribBuffers, indexBuffer=None, attribDivisors=None, legacy=False):
2210
+ """Create a Vertex Array object (VAO). VAOs store buffer binding states,
2211
+ reducing CPU overhead when drawing objects with vertex data stored in VBOs.
2212
+
2213
+ Define vertex attributes within a VAO state by passing a mapping for
2214
+ generic attribute indices and VBO buffers.
2215
+
2216
+ Parameters
2217
+ ----------
2218
+ attribBuffers : dict
2219
+ Attributes and associated VBOs to add to the VAO state. Keys are
2220
+ vertex attribute pointer indices, values are VBO descriptors to define.
2221
+ Values can be `tuples` where the first value is the buffer descriptor,
2222
+ the second is the number of attribute components (`int`, either 2, 3 or
2223
+ 4), the third is the offset (`int`), and the last is whether to
2224
+ normalize the array (`bool`).
2225
+ indexBuffer : VertexBufferInfo
2226
+ Optional index buffer.
2227
+ attribDivisors : dict
2228
+ Attribute divisors to set. Keys are vertex attribute pointer indices,
2229
+ values are the number of instances that will pass between updates of an
2230
+ attribute. Setting attribute divisors is only permitted if `legacy` is
2231
+ `False`.
2232
+ legacy : bool, optional
2233
+ Use legacy attribute pointer functions when setting the VAO state. This
2234
+ is for compatibility with older GL implementations. Key specified to
2235
+ `attribBuffers` must be `GLenum` types such as `GL_VERTEX_ARRAY` to
2236
+ indicate the capability to use.
2237
+
2238
+ Examples
2239
+ --------
2240
+ Create a vertex array object and enable buffer states within it::
2241
+
2242
+ vao = createVAO({0: vertexPos, 1: texCoords, 2: vertexNormals})
2243
+
2244
+ Using an interleaved vertex buffer, all attributes are in the same buffer
2245
+ (`vertexAttr`). We need to specify offsets for each attribute by passing a
2246
+ buffer in a `tuple` with the second value specifying the offset::
2247
+
2248
+ # buffer with interleaved layout `00011222` per-attribute
2249
+ vao = createVAO(
2250
+ {0: (vertexAttr, 3), # size 3, offset 0
2251
+ 1: (vertexAttr, 2, 3), # size 2, offset 3
2252
+ 2: (vertexAttr, 3, 5, True)}) # size 3, offset 5, normalize
2253
+
2254
+ You can mix interleaved and single-use buffers::
2255
+
2256
+ vao = createVAO(
2257
+ {0: (vertexAttr, 3, 0), 1: (vertexAttr, 3, 3), 2: vertexColors})
2258
+
2259
+ Specifying an optional index array, this is used for indexed drawing of
2260
+ primitives::
2261
+
2262
+ vao = createVAO({0: vertexPos}, indexBuffer=indices)
2263
+
2264
+ The returned `VertexArrayInfo` instance will have attribute
2265
+ ``isIndexed==True``.
2266
+
2267
+ Drawing vertex arrays using a VAO, will use the `indexBuffer` if available::
2268
+
2269
+ # draw the array
2270
+ drawVAO(vao, mode=GL.GL_TRIANGLES)
2271
+
2272
+ Use legacy attribute pointer bindings when building a VAO for compatibility
2273
+ with the fixed-function pipeline and older GLSL versions::
2274
+
2275
+ attribBuffers = {GL_VERTEX_ARRAY: vertexPos, GL_NORMAL_ARRAY: normals}
2276
+ vao = createVAO(attribBuffers, legacy=True)
2277
+
2278
+ If you wish to used instanced drawing, you can specify attribute divisors
2279
+ this way::
2280
+
2281
+ vao = createVAO(
2282
+ {0: (vertexAttr, 3, 0), 1: (vertexAttr, 3, 3), 2: vertexColors},
2283
+ attribDivisors={2: 1})
2284
+
2285
+ """
2286
+ if not attribBuffers: # in case an empty list is passed
2287
+ raise ValueError("No buffers specified.")
2288
+
2289
+ # create a vertex buffer ID
2290
+ vaoId = GL.GLuint()
2291
+
2292
+ if _thisPlatform != 'Darwin':
2293
+ GL.glGenVertexArrays(1, ctypes.byref(vaoId))
2294
+ GL.glBindVertexArray(vaoId)
2295
+ else:
2296
+ GL.glGenVertexArraysAPPLE(1, ctypes.byref(vaoId))
2297
+ GL.glBindVertexArrayAPPLE(vaoId)
2298
+
2299
+ # add attribute pointers
2300
+ activeAttribs = {}
2301
+ bufferIndices = []
2302
+ for i, buffer in attribBuffers.items():
2303
+ if isinstance(buffer, (list, tuple,)):
2304
+ if len(buffer) == 1:
2305
+ buffer = buffer[0] # size 1 tuple or list eg. (buffer,)
2306
+ size = buffer.shape[1]
2307
+ offset = 0
2308
+ normalize = False
2309
+ elif len(buffer) == 2:
2310
+ buffer, size = buffer
2311
+ offset = 0
2312
+ normalize = False
2313
+ elif len(buffer) == 3:
2314
+ buffer, size, offset = buffer
2315
+ normalize = False
2316
+ elif len(buffer) == 4:
2317
+ buffer, size, offset, normalize = buffer
2318
+ else:
2319
+ raise ValueError('Invalid attribute values.')
2320
+ else:
2321
+ size = buffer.shape[1]
2322
+ offset = 0
2323
+ normalize = False
2324
+
2325
+ enableVertexAttribArray(i, legacy)
2326
+ setVertexAttribPointer(i, buffer, size, offset, normalize, legacy)
2327
+
2328
+ activeAttribs[i] = buffer
2329
+ bufferIndices.append(buffer.shape[0])
2330
+
2331
+ # bind the EBO if available
2332
+ if indexBuffer is not None:
2333
+ if indexBuffer.target == GL.GL_ELEMENT_ARRAY_BUFFER:
2334
+ GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.name)
2335
+ if len(indexBuffer.shape) > 1:
2336
+ count = indexBuffer.shape[0] * indexBuffer.shape[1]
2337
+ else:
2338
+ count = indexBuffer.shape[0]
2339
+ else:
2340
+ raise ValueError(
2341
+ 'Index buffer does not have target `GL_ELEMENT_ARRAY_BUFFER`.')
2342
+ else:
2343
+ if bufferIndices.count(bufferIndices[0]) != len(bufferIndices):
2344
+ warnings.warn(
2345
+ 'Input arrays have unequal number of rows, using shortest for '
2346
+ '`count`.')
2347
+ count = min(bufferIndices)
2348
+ else:
2349
+ count = bufferIndices[0]
2350
+
2351
+ # set attribute divisors
2352
+ if attribDivisors is not None:
2353
+ if legacy is True:
2354
+ raise ValueError(
2355
+ 'Cannot set attribute divisors when `legacy` is `True.')
2356
+
2357
+ for key, val in attribDivisors.items():
2358
+ GL.glVertexAttribDivisor(key, val)
2359
+
2360
+ if _thisPlatform != 'Darwin':
2361
+ GL.glBindVertexArray(0)
2362
+ else:
2363
+ GL.glBindVertexArrayAPPLE(0)
2364
+
2365
+ return VertexArrayInfo(vaoId.value,
2366
+ count,
2367
+ activeAttribs,
2368
+ indexBuffer,
2369
+ attribDivisors,
2370
+ legacy)
2371
+
2372
+
2373
+ def drawVAO(vao, mode=GL.GL_TRIANGLES, start=0, count=None, instanceCount=None,
2374
+ flush=False):
2375
+ """Draw a vertex array object. Uses `glDrawArrays` or `glDrawElements` if
2376
+ `instanceCount` is `None`, or else `glDrawArraysInstanced` or
2377
+ `glDrawElementsInstanced` is used.
2378
+
2379
+ Parameters
2380
+ ----------
2381
+ vao : VertexArrayObject
2382
+ Vertex Array Object (VAO) to draw.
2383
+ mode : int, optional
2384
+ Drawing mode to use (e.g. GL_TRIANGLES, GL_QUADS, GL_POINTS, etc.)
2385
+ start : int, optional
2386
+ Starting index for array elements. Default is `0` which is the beginning
2387
+ of the array.
2388
+ count : int, optional
2389
+ Number of indices to draw from `start`. Must not exceed `vao.count` -
2390
+ `start`.
2391
+ instanceCount : int or None
2392
+ Number of instances to draw. If >0 and not `None`, instanced drawing
2393
+ will be used.
2394
+ flush : bool, optional
2395
+ Flush queued drawing commands before returning.
2396
+
2397
+ Examples
2398
+ --------
2399
+ Creating a VAO and drawing it::
2400
+
2401
+ # draw the VAO, renders the mesh
2402
+ drawVAO(vaoDesc, GL.GL_TRIANGLES)
2403
+
2404
+ """
2405
+ # draw the array
2406
+ if _thisPlatform != 'Darwin':
2407
+ GL.glBindVertexArray(vao.name)
2408
+ else:
2409
+ GL.glBindVertexArrayAPPLE(vao.name)
2410
+
2411
+ if count is None:
2412
+ count = vao.count
2413
+ else:
2414
+ if count > vao.count - start:
2415
+ raise ValueError(
2416
+ "Value of `count` cannot exceed `{}`.".format(
2417
+ vao.count - start))
2418
+
2419
+ if vao.indexBuffer is not None:
2420
+ if instanceCount is None:
2421
+ GL.glDrawElements(mode, count, vao.indexBuffer.dataType, start)
2422
+ else:
2423
+ GL.glDrawElementsInstanced(mode, count, vao.indexBuffer.dataType,
2424
+ start, instanceCount)
2425
+ else:
2426
+ if instanceCount is None:
2427
+ GL.glDrawArrays(mode, start, count)
2428
+ else:
2429
+ GL.glDrawArraysInstanced(mode, start, count, instanceCount)
2430
+
2431
+ if flush:
2432
+ GL.glFlush()
2433
+
2434
+ # reset
2435
+ if _thisPlatform != 'Darwin':
2436
+ GL.glBindVertexArray(0)
2437
+ else:
2438
+ GL.glBindVertexArrayAPPLE(0)
2439
+
2440
+
2441
+ def deleteVAO(vao):
2442
+ """Delete a Vertex Array Object (VAO). This does not delete array buffers
2443
+ bound to the VAO.
2444
+
2445
+ Parameters
2446
+ ----------
2447
+ vao : VertexArrayInfo
2448
+ VAO to delete. All fields in the descriptor except `userData` will be
2449
+ reset.
2450
+
2451
+ """
2452
+ if isinstance(vao, VertexArrayInfo):
2453
+ if vao.name:
2454
+ GL.glDeleteVertexArrays(1, GL.GLuint(vao.name))
2455
+ vao.name = 0
2456
+ vao.isLegacy = False
2457
+ vao.indexBuffer = None
2458
+ vao.activeAttribs = {}
2459
+ vao.count = 0
2460
+
2461
+
2462
+ # ---------------------------
2463
+ # Vertex Buffer Objects (VBO)
2464
+ #
2465
+
2466
+
2467
+ class VertexBufferInfo:
2468
+ """Vertex buffer object (VBO) descriptor.
2469
+
2470
+ This class only stores information about the VBO it refers to, it does not
2471
+ contain any actual array data associated with the VBO. Calling
2472
+ :func:`createVBO` returns instances of this class.
2473
+
2474
+ It is recommended to use `gltools` functions :func:`bindVBO`,
2475
+ :func:`unbindVBO`, :func:`mapBuffer`, etc. when working with these objects.
2476
+
2477
+ Parameters
2478
+ ----------
2479
+ name : GLuint or int
2480
+ OpenGL handle for the buffer.
2481
+ target : GLenum or int, optional
2482
+ Target used when binding the buffer (e.g. `GL_VERTEX_ARRAY` or
2483
+ `GL_ELEMENT_ARRAY_BUFFER`). Default is `GL_VERTEX_ARRAY`)
2484
+ usage : GLenum or int, optional
2485
+ Usage type for the array (i.e. `GL_STATIC_DRAW`).
2486
+ dataType : Glenum, optional
2487
+ Data type of array. Default is `GL_FLOAT`.
2488
+ size : int, optional
2489
+ Size of the buffer in bytes.
2490
+ stride : int, optional
2491
+ Number of bytes between adjacent attributes. If `0`, values are assumed
2492
+ to be tightly packed.
2493
+ shape : tuple or list, optional
2494
+ Shape of the array used to create this VBO.
2495
+ userData : dict, optional
2496
+ Optional user defined data associated with the VBO. If `None`,
2497
+ `userData` will be initialized as an empty dictionary.
2498
+
2499
+ """
2500
+ __slots__ = ['name', 'target', 'usage', 'dataType',
2501
+ 'size', 'stride', 'shape', 'userData']
2502
+
2503
+ def __init__(self,
2504
+ name=0,
2505
+ target=GL.GL_ARRAY_BUFFER,
2506
+ usage=GL.GL_STATIC_DRAW,
2507
+ dataType=GL.GL_FLOAT,
2508
+ size=0,
2509
+ stride=0,
2510
+ shape=(0,),
2511
+ userData=None):
2512
+
2513
+ self.name = name
2514
+ self.target = target
2515
+ self.usage = usage
2516
+ self.dataType = dataType
2517
+ self.size = size
2518
+ self.stride = stride
2519
+ self.shape = shape
2520
+
2521
+ if userData is None:
2522
+ self.userData = {}
2523
+ elif isinstance(userData, dict):
2524
+ self.userData = userData
2525
+ else:
2526
+ raise TypeError('Invalid type for `userData`.')
2527
+
2528
+ def __hash__(self):
2529
+ return hash((self.name,
2530
+ self.target,
2531
+ self.dataType,
2532
+ self.usage,
2533
+ self.size,
2534
+ self.shape))
2535
+
2536
+ def __eq__(self, other):
2537
+ """Equality test between VBO object names."""
2538
+ return self.name == other.name
2539
+
2540
+ def __ne__(self, other):
2541
+ """Inequality test between VBO object names."""
2542
+ return self.name != other.name
2543
+
2544
+ @property
2545
+ def hasBuffer(self):
2546
+ """Check if the VBO assigned to `name` is a buffer."""
2547
+ if self.name != 0 and GL.glIsBuffer(self.name):
2548
+ return True
2549
+
2550
+ return False
2551
+
2552
+ @property
2553
+ def isIndex(self):
2554
+ """`True` if the buffer referred to by this object is an index array."""
2555
+ if self.name != 0 and GL.glIsBuffer(self.name):
2556
+ return self.target == GL.GL_ELEMENT_ARRAY_BUFFER
2557
+
2558
+ return False
2559
+
2560
+ def validate(self):
2561
+ """Check if the data contained in this descriptor matches what is
2562
+ actually present in the OpenGL state.
2563
+
2564
+ Returns
2565
+ -------
2566
+ bool
2567
+ `True` if the information contained in this descriptor matches the
2568
+ OpenGL state.
2569
+
2570
+ """
2571
+ # fail automatically if these conditions are true
2572
+ if self.name == 0 or GL.glIsBuffer(self.name) != GL.GL_TRUE:
2573
+ return False
2574
+
2575
+ if self.target == GL.GL_ARRAY_BUFFER:
2576
+ bindTarget = GL.GL_VERTEX_ARRAY_BUFFER_BINDING
2577
+ elif self.target == GL.GL_ELEMENT_ARRAY_BUFFER:
2578
+ bindTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING
2579
+ else:
2580
+ raise ValueError(
2581
+ 'Invalid `target` type, must be `GL_ARRAY_BUFFER` or '
2582
+ '`GL_ELEMENT_ARRAY_BUFFER`.')
2583
+
2584
+ # get current binding so we don't disturb the current state
2585
+ currentVBO = GL.GLint()
2586
+ GL.glGetIntegerv(bindTarget, ctypes.byref(currentVBO))
2587
+
2588
+ # bind buffer at name to validate
2589
+ GL.glBindBuffer(self.target, self.name)
2590
+
2591
+ # get buffer parameters
2592
+ actualSize = GL.GLint()
2593
+ GL.glGetBufferParameteriv(
2594
+ self.target, GL.GL_BUFFER_SIZE, ctypes.byref(actualSize))
2595
+ actualUsage = GL.GLint()
2596
+ GL.glGetBufferParameteriv(
2597
+ self.target, GL.GL_BUFFER_USAGE, ctypes.byref(actualUsage))
2598
+
2599
+ # check values against those in this object
2600
+ isValid = False
2601
+ if self.usage == actualUsage.value and self.size == actualSize.value:
2602
+ isValid = True
2603
+
2604
+ # return to the original binding
2605
+ GL.glBindBuffer(self.target, currentVBO.value)
2606
+
2607
+ return isValid
2608
+
2609
+
2610
+ def createVBO(data,
2611
+ target=GL.GL_ARRAY_BUFFER,
2612
+ dataType=GL.GL_FLOAT,
2613
+ usage=GL.GL_STATIC_DRAW):
2614
+ """Create an array buffer object (VBO).
2615
+
2616
+ Creates a VBO using input data, usually as a `ndarray` or `list`. Attributes
2617
+ common to one vertex should occupy a single row of the `data` array.
2618
+
2619
+ Parameters
2620
+ ----------
2621
+ data : array_like
2622
+ A 2D array of values to write to the array buffer. The data type of the
2623
+ VBO is inferred by the type of the array. If the input is a Python
2624
+ `list` or `tuple` type, the data type of the array will be `GL_FLOAT`.
2625
+ target : :obj:`int`
2626
+ Target used when binding the buffer (e.g. `GL_VERTEX_ARRAY` or
2627
+ `GL_ELEMENT_ARRAY_BUFFER`). Default is `GL_VERTEX_ARRAY`.
2628
+ dataType : Glenum, optional
2629
+ Data type of array. Input data will be recast to an appropriate type if
2630
+ necessary. Default is `GL_FLOAT`.
2631
+ usage : GLenum or int, optional
2632
+ Usage type for the array (i.e. `GL_STATIC_DRAW`).
2633
+
2634
+ Returns
2635
+ -------
2636
+ VertexBufferInfo
2637
+ A descriptor with vertex buffer information.
2638
+
2639
+ Examples
2640
+ --------
2641
+ Creating a vertex buffer object with vertex data::
2642
+
2643
+ # vertices of a triangle
2644
+ verts = [[ 1.0, 1.0, 0.0], # v0
2645
+ [ 0.0, -1.0, 0.0], # v1
2646
+ [-1.0, 1.0, 0.0]] # v2
2647
+
2648
+ # load vertices to graphics device, return a descriptor
2649
+ vboDesc = createVBO(verts)
2650
+
2651
+ Drawing triangles or quads using vertex buffer data::
2652
+
2653
+ nIndices, vSize = vboDesc.shape # element size
2654
+
2655
+ bindVBO(vboDesc)
2656
+ setVertexAttribPointer(
2657
+ GL_VERTEX_ARRAY, vSize, vboDesc.dataType, legacy=True)
2658
+ enableVertexAttribArray(GL_VERTEX_ARRAY, legacy=True)
2659
+
2660
+ if vSize == 3:
2661
+ drawMode = GL_TRIANGLES
2662
+ elif vSize == 4:
2663
+ drawMode = GL_QUADS
2664
+
2665
+ glDrawArrays(drawMode, 0, nIndices)
2666
+ glFlush()
2667
+
2668
+ disableVertexAttribArray(GL_VERTEX_ARRAY, legacy=True)
2669
+ unbindVBO()
2670
+
2671
+ Custom data can be associated with this vertex buffer by specifying
2672
+ `userData`::
2673
+
2674
+ myVBO = createVBO(data)
2675
+ myVBO.userData['startIdx'] = 14 # first index to draw with
2676
+
2677
+ # use it later
2678
+ nIndices, vSize = vboDesc.shape # element size
2679
+ startIdx = myVBO.userData['startIdx']
2680
+ endIdx = nIndices - startIdx
2681
+ glDrawArrays(GL_TRIANGLES, startIdx, endIdx)
2682
+ glFlush()
2683
+
2684
+ """
2685
+ # build input array
2686
+ npType, glType = GL_COMPAT_TYPES[dataType]
2687
+ data = np.asarray(data, dtype=npType)
2688
+
2689
+ # get buffer size and pointer
2690
+ bufferSize = data.size * ctypes.sizeof(glType)
2691
+ if data.ndim > 1:
2692
+ bufferStride = data.shape[1] * ctypes.sizeof(glType)
2693
+ else:
2694
+ bufferStride = 0
2695
+
2696
+ bufferPtr = data.ctypes.data_as(ctypes.POINTER(glType))
2697
+
2698
+ # create a vertex buffer ID
2699
+ bufferName = GL.GLuint()
2700
+ GL.glGenBuffers(1, ctypes.byref(bufferName))
2701
+
2702
+ # bind and upload
2703
+ GL.glBindBuffer(target, bufferName)
2704
+ GL.glBufferData(target, bufferSize, bufferPtr, usage)
2705
+ GL.glBindBuffer(target, 0)
2706
+
2707
+ vboInfo = VertexBufferInfo(
2708
+ bufferName,
2709
+ target,
2710
+ usage,
2711
+ dataType,
2712
+ bufferSize,
2713
+ bufferStride,
2714
+ data.shape) # leave userData empty
2715
+
2716
+ return vboInfo
2717
+
2718
+
2719
+ def bindVBO(vbo):
2720
+ """Bind a VBO to the current GL state.
2721
+
2722
+ Parameters
2723
+ ----------
2724
+ vbo : VertexBufferInfo
2725
+ VBO descriptor to bind.
2726
+
2727
+ Returns
2728
+ -------
2729
+ bool
2730
+ `True` is the binding state was changed. Returns `False` if the state
2731
+ was not changed due to the buffer already being bound.
2732
+
2733
+ """
2734
+ if isinstance(vbo, VertexBufferInfo):
2735
+ GL.glBindBuffer(vbo.target, vbo.name)
2736
+ else:
2737
+ raise TypeError('Specified `vbo` is not at `VertexBufferInfo`.')
2738
+
2739
+
2740
+ def unbindVBO(vbo):
2741
+ """Unbind a vertex buffer object (VBO).
2742
+
2743
+ Parameters
2744
+ ----------
2745
+ vbo : VertexBufferInfo
2746
+ VBO descriptor to unbind.
2747
+
2748
+ """
2749
+ if isinstance(vbo, VertexBufferInfo):
2750
+ GL.glBindBuffer(vbo.target, 0)
2751
+ else:
2752
+ raise TypeError('Specified `vbo` is not at `VertexBufferInfo`.')
2753
+
2754
+
2755
+ def mapBuffer(vbo, start=0, length=None, read=True, write=True, noSync=False):
2756
+ """Map a vertex buffer object to client memory. This allows you to modify
2757
+ its contents.
2758
+
2759
+ If planning to update VBO vertex data, make sure the VBO `usage` types are
2760
+ `GL_DYNAMIC_*` or `GL_STREAM_*` or else serious performance issues may
2761
+ arise.
2762
+
2763
+ Warnings
2764
+ --------
2765
+ Modifying buffer data must be done carefully, or else system stability may
2766
+ be affected. Do not use the returned view `ndarray` outside of successive
2767
+ :func:`mapBuffer` and :func:`unmapBuffer` calls. Do not use the mapped
2768
+ buffer for rendering until after :func:`unmapBuffer` is called.
2769
+
2770
+ Parameters
2771
+ ----------
2772
+ vbo : VertexBufferInfo
2773
+ Vertex buffer to map to client memory.
2774
+ start : int
2775
+ Initial index of the sub-range of the buffer to modify.
2776
+ length : int or None
2777
+ Number of elements of the sub-array to map from `offset`. If `None`, all
2778
+ elements to from `offset` to the end of the array are mapped.
2779
+ read : bool, optional
2780
+ Allow data to be read from the buffer (sets `GL_MAP_READ_BIT`). This is
2781
+ ignored if `noSync` is `True`.
2782
+ write : bool, optional
2783
+ Allow data to be written to the buffer (sets `GL_MAP_WRITE_BIT`).
2784
+ noSync : bool, optional
2785
+ If `True`, GL will not wait until the buffer is free (i.e. not being
2786
+ processed by the GPU) to map it (sets `GL_MAP_UNSYNCHRONIZED_BIT`). The
2787
+ contents of the previous storage buffer are discarded and the driver
2788
+ returns a new one. This prevents the CPU from stalling until the buffer
2789
+ is available.
2790
+
2791
+ Returns
2792
+ -------
2793
+ ndarray
2794
+ View of the data. The type of the returned array is one which best
2795
+ matches the data type of the buffer.
2796
+
2797
+ Examples
2798
+ --------
2799
+ Map a buffer and edit it::
2800
+
2801
+ arr = mapBuffer(vbo)
2802
+ arr[:, :] += 2.0 # add 2 to all values
2803
+ unmapBuffer(vbo) # call when done
2804
+ # Don't ever modify `arr` after calling `unmapBuffer`. Delete it if
2805
+ # necessary to prevent it form being used.
2806
+ del arr
2807
+
2808
+ Modify a sub-range of data by specifying `start` and `length`, indices
2809
+ correspond to values, not byte offsets::
2810
+
2811
+ arr = mapBuffer(vbo, start=12, end=24)
2812
+ arr[:, :] *= 10.0
2813
+ unmapBuffer(vbo)
2814
+
2815
+ """
2816
+ npType, glType = GL_COMPAT_TYPES[vbo.dataType]
2817
+ start *= ctypes.sizeof(glType)
2818
+
2819
+ if length is None:
2820
+ length = vbo.size
2821
+ else:
2822
+ length *= ctypes.sizeof(glType)
2823
+
2824
+ accessFlags = GL.GL_NONE
2825
+ if noSync: # if set, don't set GL_MAP_READ_BIT
2826
+ accessFlags |= GL.GL_MAP_UNSYNCHRONIZED_BIT
2827
+ elif read:
2828
+ accessFlags |= GL.GL_MAP_READ_BIT
2829
+
2830
+ if write:
2831
+ accessFlags |= GL.GL_MAP_WRITE_BIT
2832
+
2833
+ bindVBO(vbo) # bind the buffer for mapping
2834
+
2835
+ # get pointer to the buffer
2836
+ bufferPtr = GL.glMapBufferRange(
2837
+ vbo.target,
2838
+ GL.GLintptr(start),
2839
+ GL.GLintptr(length),
2840
+ accessFlags)
2841
+
2842
+ bufferArray = np.ctypeslib.as_array(
2843
+ ctypes.cast(bufferPtr, ctypes.POINTER(glType)),
2844
+ shape=vbo.shape)
2845
+
2846
+ return bufferArray
2847
+
2848
+
2849
+ def unmapBuffer(vbo):
2850
+ """Unmap a previously mapped buffer. Must be called after :func:`mapBuffer`
2851
+ is called and before any drawing operations which use the buffer are
2852
+ called. Failing to call this before using the buffer could result in a
2853
+ system error.
2854
+
2855
+ Parameters
2856
+ ----------
2857
+ vbo : VertexBufferInfo
2858
+ Vertex buffer descriptor.
2859
+
2860
+ Returns
2861
+ -------
2862
+ bool
2863
+ `True` if the buffer has been successfully modified. If `False`, the
2864
+ data was corrupted for some reason and needs to be resubmitted.
2865
+
2866
+ """
2867
+ return GL.glUnmapBuffer(vbo.target) == GL.GL_TRUE
2868
+
2869
+
2870
+ def deleteVBO(vbo):
2871
+ """Delete a vertex buffer object (VBO).
2872
+
2873
+ Parameters
2874
+ ----------
2875
+ vbo : VertexBufferInfo
2876
+ Descriptor of VBO to delete.
2877
+
2878
+ """
2879
+ if GL.glIsBuffer(vbo.name):
2880
+ GL.glDeleteBuffers(1, vbo.name)
2881
+ vbo.name = GL.GLuint(0)
2882
+
2883
+
2884
+ def setVertexAttribPointer(index,
2885
+ vbo,
2886
+ size=None,
2887
+ offset=0,
2888
+ normalize=False,
2889
+ legacy=False):
2890
+ """Define an array of vertex attribute data with a VBO descriptor.
2891
+
2892
+ In modern OpenGL implementations, attributes are 'generic', where an
2893
+ attribute pointer index does not correspond to any special vertex property.
2894
+ Usually the usage for an attribute is defined in the shader program. It is
2895
+ recommended that shader programs define attributes using the `layout`
2896
+ parameters::
2897
+
2898
+ layout (location = 0) in vec3 position;
2899
+ layout (location = 1) in vec2 texCoord;
2900
+ layout (location = 2) in vec3 normal;
2901
+
2902
+ Setting attribute pointers can be done like this::
2903
+
2904
+ setVertexAttribPointer(0, posVbo)
2905
+ setVertexAttribPointer(1, texVbo)
2906
+ setVertexAttribPointer(2, normVbo)
2907
+
2908
+ For compatibility with older OpenGL specifications, some drivers will alias
2909
+ vertex pointers unless they are explicitly defined in the shader. This
2910
+ allows VAOs the be used with the fixed-function pipeline or older GLSL
2911
+ versions.
2912
+
2913
+ On nVidia graphics drivers (and maybe others), the following attribute
2914
+ pointers indices are aliased with reserved GLSL names:
2915
+
2916
+ * gl_Vertex - 0
2917
+ * gl_Normal - 2
2918
+ * gl_Color - 3
2919
+ * gl_SecondaryColor - 4
2920
+ * gl_FogCoord - 5
2921
+ * gl_MultiTexCoord0 - 8
2922
+ * gl_MultiTexCoord1 - 9
2923
+ * gl_MultiTexCoord2 - 10
2924
+ * gl_MultiTexCoord3 - 11
2925
+ * gl_MultiTexCoord4 - 12
2926
+ * gl_MultiTexCoord5 - 13
2927
+ * gl_MultiTexCoord6 - 14
2928
+ * gl_MultiTexCoord7 - 15
2929
+
2930
+ Specifying `legacy` as `True` will allow for old-style pointer definitions.
2931
+ You must specify the capability as a `GLenum` associated with the pointer
2932
+ in this case::
2933
+
2934
+ setVertexAttribPointer(GL_VERTEX_ARRAY, posVbo, legacy=True)
2935
+ setVertexAttribPointer(GL_TEXTURE_COORD_ARRAY, texVbo, legacy=True)
2936
+ setVertexAttribPointer(GL_NORMAL_ARRAY, normVbo, legacy=True)
2937
+
2938
+ Parameters
2939
+ ----------
2940
+ index : int
2941
+ Index of the attribute to modify. If `legacy=True`, this value should
2942
+ be a `GLenum` type corresponding to the capability to bind the buffer
2943
+ to, such as `GL_VERTEX_ARRAY`, `GL_TEXTURE_COORD_ARRAY`,
2944
+ `GL_NORMAL_ARRAY`, etc.
2945
+ vbo : VertexBufferInfo
2946
+ VBO descriptor.
2947
+ size : int, optional
2948
+ Number of components per vertex attribute, can be either 1, 2, 3, or 4.
2949
+ If `None` is specified, the component size will be inferred from the
2950
+ `shape` of the VBO. You must specify this value if the VBO is
2951
+ interleaved.
2952
+ offset : int, optional
2953
+ Starting index of the attribute in the buffer.
2954
+ normalize : bool, optional
2955
+ Normalize fixed-point format values when accessed.
2956
+ legacy : bool, optional
2957
+ Use legacy vertex attributes (ie. `GL_VERTEX_ARRAY`,
2958
+ `GL_TEXTURE_COORD_ARRAY`, etc.) for backwards compatibility.
2959
+
2960
+ Examples
2961
+ --------
2962
+ Define a generic attribute from a vertex buffer descriptor::
2963
+
2964
+ # set the vertex location attribute
2965
+ setVertexAttribPointer(0, vboDesc) # 0 is vertex in our shader
2966
+ GL.glColor3f(1.0, 0.0, 0.0) # red triangle
2967
+
2968
+ # draw the triangle
2969
+ nIndices, vSize = vboDesc.shape # element size
2970
+ GL.glDrawArrays(GL.GL_TRIANGLES, 0, nIndices)
2971
+
2972
+ If our VBO has interleaved attributes, we can specify `offset` to account
2973
+ for that::
2974
+
2975
+ # define interleaved vertex attributes
2976
+ # | Position | Texture | Normals |
2977
+ vQuad = [[ -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], # v0
2978
+ [ -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], # v1
2979
+ [ 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0], # v2
2980
+ [ 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0]] # v3
2981
+
2982
+ # create a VBO with interleaved attributes
2983
+ vboInterleaved = createVBO(np.asarray(vQuad, dtype=np.float32))
2984
+
2985
+ # ... before rendering, set the attribute pointers
2986
+ GL.glBindBuffer(vboInterleaved.target, vboInterleaved.name)
2987
+ gltools.setVertexAttribPointer(
2988
+ 0, vboInterleaved, size=3, offset=0) # vertex pointer
2989
+ gltools.setVertexAttribPointer(
2990
+ 8, vboInterleaved, size=2, offset=3) # texture pointer
2991
+ gltools.setVertexAttribPointer(
2992
+ 3, vboInterleaved, size=3, offset=5) # normals pointer
2993
+
2994
+ # Note, we specified `bind=False` since we are managing the binding
2995
+ # state. It is recommended that you do this when setting up interleaved
2996
+ # buffers to avoid re-binding the same buffer.
2997
+
2998
+ # draw red, full screen quad
2999
+ GL.glColor3f(1.0, 0.0, 0.0)
3000
+ GL.glDrawArrays(GL.GL_QUADS, 0, vboInterleaved.shape[1])
3001
+
3002
+ # call these when done if `enable=True`
3003
+ gltools.disableVertexAttribArray(0)
3004
+ gltools.disableVertexAttribArray(8)
3005
+ gltools.disableVertexAttribArray(1)
3006
+
3007
+ # unbind the buffer
3008
+ GL.glBindBuffer(vboInterleaved.target, 0)
3009
+
3010
+ """
3011
+ if vbo.target != GL.GL_ARRAY_BUFFER:
3012
+ raise ValueError('VBO must have `target` type `GL_ARRAY_BUFFER`.')
3013
+
3014
+ _, glType = GL_COMPAT_TYPES[vbo.dataType]
3015
+
3016
+ if size is None:
3017
+ size = vbo.shape[1]
3018
+
3019
+ offset *= ctypes.sizeof(glType)
3020
+
3021
+ bindVBO(vbo)
3022
+
3023
+ if not legacy:
3024
+ GL.glEnableVertexAttribArray(index)
3025
+ GL.glVertexAttribPointer(
3026
+ index,
3027
+ size,
3028
+ vbo.dataType,
3029
+ GL.GL_TRUE if normalize else GL.GL_FALSE,
3030
+ vbo.stride,
3031
+ offset)
3032
+ else:
3033
+ GL.glEnableClientState(index)
3034
+ if index == GL.GL_VERTEX_ARRAY:
3035
+ GL.glVertexPointer(size, vbo.dataType, vbo.stride, offset)
3036
+ elif index == GL.GL_NORMAL_ARRAY:
3037
+ GL.glNormalPointer(vbo.dataType, vbo.stride, offset)
3038
+ elif index == GL.GL_TEXTURE_COORD_ARRAY:
3039
+ GL.glTexCoordPointer(size, vbo.dataType, vbo.stride, offset)
3040
+ elif index == GL.GL_COLOR_ARRAY:
3041
+ GL.glColorPointer(size, vbo.dataType, vbo.stride, offset)
3042
+ elif index == GL.GL_SECONDARY_COLOR_ARRAY:
3043
+ GL.glSecondaryColorPointer(size, vbo.dataType, vbo.stride, offset)
3044
+ elif index == GL.GL_FOG_COORD_ARRAY:
3045
+ GL.glFogCoordPointer(vbo.dataType, vbo.stride, offset)
3046
+ else:
3047
+ raise ValueError('Invalid `index` enum specified.')
3048
+
3049
+ unbindVBO(vbo)
3050
+
3051
+
3052
+ def enableVertexAttribArray(index, legacy=False):
3053
+ """Enable a vertex attribute array. Attributes will be used for use by
3054
+ subsequent draw operations. Be sure to call :func:`disableVertexAttribArray`
3055
+ on the same attribute to prevent currently enabled attributes from affecting
3056
+ later rendering.
3057
+
3058
+ Parameters
3059
+ ----------
3060
+ index : int
3061
+ Index of the attribute to enable. If `legacy=True`, this value should
3062
+ be a `GLenum` type corresponding to the capability to bind the buffer
3063
+ to, such as `GL_VERTEX_ARRAY`, `GL_TEXTURE_COORD_ARRAY`,
3064
+ `GL_NORMAL_ARRAY`, etc.
3065
+ legacy : bool, optional
3066
+ Use legacy vertex attributes (ie. `GL_VERTEX_ARRAY`,
3067
+ `GL_TEXTURE_COORD_ARRAY`, etc.) for backwards compatibility.
3068
+
3069
+ """
3070
+ if not legacy:
3071
+ GL.glEnableVertexAttribArray(index)
3072
+ else:
3073
+ GL.glEnableClientState(index)
3074
+
3075
+
3076
+ def disableVertexAttribArray(index, legacy=False):
3077
+ """Disable a vertex attribute array.
3078
+
3079
+ Parameters
3080
+ ----------
3081
+ index : int
3082
+ Index of the attribute to enable. If `legacy=True`, this value should
3083
+ be a `GLenum` type corresponding to the capability to bind the buffer
3084
+ to, such as `GL_VERTEX_ARRAY`, `GL_TEXTURE_COORD_ARRAY`,
3085
+ `GL_NORMAL_ARRAY`, etc.
3086
+ legacy : bool, optional
3087
+ Use legacy vertex attributes (ie. `GL_VERTEX_ARRAY`,
3088
+ `GL_TEXTURE_COORD_ARRAY`, etc.) for backwards compatibility.
3089
+
3090
+ """
3091
+ if not legacy:
3092
+ GL.glDisableVertexAttribArray(index)
3093
+ else:
3094
+ GL.glDisableClientState(index)
3095
+
3096
+
3097
+ # -------------------------
3098
+ # Material Helper Functions
3099
+ # -------------------------
3100
+ #
3101
+ # Materials affect the appearance of rendered faces. These helper functions and
3102
+ # datatypes simplify the creation of materials for rendering stimuli.
3103
+ #
3104
+
3105
+ Material = namedtuple('Material', ['face', 'params', 'textures', 'userData'])
3106
+
3107
+
3108
+ def createMaterial(params=(), textures=(), face=GL.GL_FRONT_AND_BACK):
3109
+ """Create a new material.
3110
+
3111
+ Parameters
3112
+ ----------
3113
+
3114
+ params : :obj:`list` of :obj:`tuple`, optional
3115
+ List of material modes and values. Each mode is assigned a value as
3116
+ (mode, color). Modes can be GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR,
3117
+ GL_EMISSION, GL_SHININESS or GL_AMBIENT_AND_DIFFUSE. Colors must be
3118
+ a tuple of 4 floats which specify reflectance values for each RGBA
3119
+ component. The value of GL_SHININESS should be a single float. If no
3120
+ values are specified, an empty material will be created.
3121
+ textures : :obj:`list` of :obj:`tuple`, optional
3122
+ List of texture units and TexImage2D descriptors. These will be written
3123
+ to the 'textures' field of the returned descriptor. For example,
3124
+ [(GL.GL_TEXTURE0, texDesc0), (GL.GL_TEXTURE1, texDesc1)]. The number of
3125
+ texture units per-material is GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.
3126
+ face : :obj:`int`, optional
3127
+ Faces to apply material to. Values can be GL_FRONT_AND_BACK, GL_FRONT
3128
+ and GL_BACK. The default is GL_FRONT_AND_BACK.
3129
+
3130
+ Returns
3131
+ -------
3132
+ Material :
3133
+ A descriptor with material properties.
3134
+
3135
+ Examples
3136
+ --------
3137
+ Creating a new material with given properties::
3138
+
3139
+ # The values for the material below can be found at
3140
+ # http://devernay.free.fr/cours/opengl/materials.html
3141
+
3142
+ # create a gold material
3143
+ gold = createMaterial([
3144
+ (GL.GL_AMBIENT, (0.24725, 0.19950, 0.07450, 1.0)),
3145
+ (GL.GL_DIFFUSE, (0.75164, 0.60648, 0.22648, 1.0)),
3146
+ (GL.GL_SPECULAR, (0.628281, 0.555802, 0.366065, 1.0)),
3147
+ (GL.GL_SHININESS, 0.4 * 128.0)])
3148
+
3149
+ Use the material when drawing::
3150
+
3151
+ useMaterial(gold)
3152
+ drawVAO( ... ) # all meshes will be gold
3153
+ useMaterial(None) # turn off material when done
3154
+
3155
+ Create a red plastic material, but define reflectance and shine later::
3156
+
3157
+ red_plastic = createMaterial()
3158
+
3159
+ # you need to convert values to ctypes!
3160
+ red_plastic.values[GL_AMBIENT] = (GLfloat * 4)(0.0, 0.0, 0.0, 1.0)
3161
+ red_plastic.values[GL_DIFFUSE] = (GLfloat * 4)(0.5, 0.0, 0.0, 1.0)
3162
+ red_plastic.values[GL_SPECULAR] = (GLfloat * 4)(0.7, 0.6, 0.6, 1.0)
3163
+ red_plastic.values[GL_SHININESS] = 0.25 * 128.0
3164
+
3165
+ # set and draw
3166
+ useMaterial(red_plastic)
3167
+ drawVertexbuffers( ... ) # all meshes will be red plastic
3168
+ useMaterial(None)
3169
+
3170
+ """
3171
+ # setup material mode/value slots
3172
+ matDesc = Material(
3173
+ face,
3174
+ {mode: None for mode in (
3175
+ GL.GL_AMBIENT,
3176
+ GL.GL_DIFFUSE,
3177
+ GL.GL_SPECULAR,
3178
+ GL.GL_EMISSION,
3179
+ GL.GL_SHININESS)},
3180
+ dict(),
3181
+ dict())
3182
+ if params:
3183
+ for mode, param in params:
3184
+ matDesc.params[mode] = \
3185
+ (GL.GLfloat * 4)(*param) \
3186
+ if mode != GL.GL_SHININESS else GL.GLfloat(param)
3187
+ if textures:
3188
+ maxTexUnits = getIntegerv(GL.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3189
+ for unit, texDesc in textures:
3190
+ if unit <= GL.GL_TEXTURE0 + (maxTexUnits - 1):
3191
+ matDesc.textures[unit] = texDesc
3192
+ else:
3193
+ raise ValueError("Invalid texture unit enum.")
3194
+
3195
+ return matDesc
3196
+
3197
+
3198
+ class SimpleMaterial:
3199
+ """Class representing a simple material.
3200
+
3201
+ This class stores material information to modify the appearance of drawn
3202
+ primitives with respect to lighting, such as color (diffuse, specular,
3203
+ ambient, and emission), shininess, and textures. Simple materials are
3204
+ intended to work with features supported by the fixed-function OpenGL
3205
+ pipeline.
3206
+
3207
+ """
3208
+ def __init__(self,
3209
+ win=None,
3210
+ diffuseColor=(.5, .5, .5),
3211
+ specularColor=(-1., -1., -1.),
3212
+ ambientColor=(-1., -1., -1.),
3213
+ emissionColor=(-1., -1., -1.),
3214
+ shininess=10.0,
3215
+ colorSpace='rgb',
3216
+ diffuseTexture=None,
3217
+ specularTexture=None,
3218
+ opacity=1.0,
3219
+ contrast=1.0,
3220
+ face='front'):
3221
+ """
3222
+ Parameters
3223
+ ----------
3224
+ win : `~psychopy.visual.Window` or `None`
3225
+ Window this material is associated with, required for shaders and
3226
+ some color space conversions.
3227
+ diffuseColor : array_like
3228
+ Diffuse material color (r, g, b, a) with values between 0.0 and 1.0.
3229
+ specularColor : array_like
3230
+ Specular material color (r, g, b, a) with values between 0.0 and
3231
+ 1.0.
3232
+ ambientColor : array_like
3233
+ Ambient material color (r, g, b, a) with values between 0.0 and 1.0.
3234
+ emissionColor : array_like
3235
+ Emission material color (r, g, b, a) with values between 0.0 and
3236
+ 1.0.
3237
+ shininess : float
3238
+ Material shininess, usually ranges from 0.0 to 128.0.
3239
+ colorSpace : float
3240
+ Color space for `diffuseColor`, `specularColor`, `ambientColor`, and
3241
+ `emissionColor`.
3242
+ diffuseTexture : TexImage2D
3243
+ specularTexture : TexImage2D
3244
+ opacity : float
3245
+ Opacity of the material. Ranges from 0.0 to 1.0 where 1.0 is fully
3246
+ opaque.
3247
+ contrast : float
3248
+ Contrast of the material colors.
3249
+ face : str
3250
+ Face to apply material to. Values are `front`, `back` or `both`.
3251
+ """
3252
+ self.win = win
3253
+
3254
+ self._diffuseColor = np.zeros((3,), np.float32)
3255
+ self._specularColor = np.zeros((3,), np.float32)
3256
+ self._ambientColor = np.zeros((3,), np.float32)
3257
+ self._emissionColor = np.zeros((3,), np.float32)
3258
+ self._shininess = float(shininess)
3259
+
3260
+ # internal RGB values post colorspace conversion
3261
+ self._diffuseRGB = np.array((0., 0., 0., 1.), np.float32)
3262
+ self._specularRGB = np.array((0., 0., 0., 1.), np.float32)
3263
+ self._ambientRGB = np.array((0., 0., 0., 1.), np.float32)
3264
+ self._emissionRGB = np.array((0., 0., 0., 1.), np.float32)
3265
+
3266
+ # which faces to apply the material
3267
+
3268
+ if face == 'front':
3269
+ self._face = GL.GL_FRONT
3270
+ elif face == 'back':
3271
+ self._face = GL.GL_BACK
3272
+ elif face == 'both':
3273
+ self._face = GL.GL_FRONT_AND_BACK
3274
+ else:
3275
+ raise ValueError("Invalid `face` specified, must be 'front', "
3276
+ "'back' or 'both'.")
3277
+
3278
+ self.colorSpace = colorSpace
3279
+ self.opacity = opacity
3280
+ self.contrast = contrast
3281
+
3282
+ self.diffuseColor = diffuseColor
3283
+ self.specularColor = specularColor
3284
+ self.ambientColor = ambientColor
3285
+ self.emissionColor = emissionColor
3286
+
3287
+ self._diffuseTexture = diffuseTexture
3288
+ self._normalTexture = None
3289
+
3290
+ self._useTextures = False # keeps track if textures are being used
3291
+
3292
+ @property
3293
+ def diffuseTexture(self):
3294
+ """Diffuse color of the material."""
3295
+ return self._diffuseTexture
3296
+
3297
+ @diffuseTexture.setter
3298
+ def diffuseTexture(self, value):
3299
+ self._diffuseTexture = value
3300
+
3301
+ @property
3302
+ def diffuseColor(self):
3303
+ """Diffuse color of the material."""
3304
+ return self._diffuseColor
3305
+
3306
+ @diffuseColor.setter
3307
+ def diffuseColor(self, value):
3308
+ self._diffuseColor = np.asarray(value, np.float32)
3309
+ setColor(self, value, colorSpace=self.colorSpace, operation=None,
3310
+ rgbAttrib='diffuseRGB', colorAttrib='diffuseColor',
3311
+ colorSpaceAttrib='colorSpace')
3312
+
3313
+ @property
3314
+ def diffuseRGB(self):
3315
+ """Diffuse color of the material."""
3316
+ return self._diffuseRGB[:3]
3317
+
3318
+ @diffuseRGB.setter
3319
+ def diffuseRGB(self, value):
3320
+ # make sure the color we got is 32-bit float
3321
+ self._diffuseRGB = np.zeros((4,), np.float32)
3322
+ self._diffuseRGB[:3] = (value * self.contrast + 1) / 2.0
3323
+ self._diffuseRGB[3] = self.opacity
3324
+
3325
+ @property
3326
+ def specularColor(self):
3327
+ """Specular color of the material."""
3328
+ return self._specularColor
3329
+
3330
+ @specularColor.setter
3331
+ def specularColor(self, value):
3332
+ self._specularColor = np.asarray(value, np.float32)
3333
+ setColor(self, value, colorSpace=self.colorSpace, operation=None,
3334
+ rgbAttrib='specularRGB', colorAttrib='specularColor',
3335
+ colorSpaceAttrib='colorSpace')
3336
+
3337
+ @property
3338
+ def specularRGB(self):
3339
+ """Diffuse color of the material."""
3340
+ return self._specularRGB[:3]
3341
+
3342
+ @specularRGB.setter
3343
+ def specularRGB(self, value):
3344
+ # make sure the color we got is 32-bit float
3345
+ self._specularRGB = np.zeros((4,), np.float32)
3346
+ self._specularRGB[:3] = (value * self.contrast + 1) / 2.0
3347
+ self._specularRGB[3] = self.opacity
3348
+
3349
+ @property
3350
+ def ambientColor(self):
3351
+ """Ambient color of the material."""
3352
+ return self._ambientColor
3353
+
3354
+ @ambientColor.setter
3355
+ def ambientColor(self, value):
3356
+ self._ambientColor = np.asarray(value, np.float32)
3357
+ setColor(self, value, colorSpace=self.colorSpace, operation=None,
3358
+ rgbAttrib='ambientRGB', colorAttrib='ambientColor',
3359
+ colorSpaceAttrib='colorSpace')
3360
+
3361
+ @property
3362
+ def ambientRGB(self):
3363
+ """Diffuse color of the material."""
3364
+ return self._ambientRGB[:3]
3365
+
3366
+ @ambientRGB.setter
3367
+ def ambientRGB(self, value):
3368
+ # make sure the color we got is 32-bit float
3369
+ self._ambientRGB = np.zeros((4,), np.float32)
3370
+ self._ambientRGB[:3] = (value * self.contrast + 1) / 2.0
3371
+ self._ambientRGB[3] = self.opacity
3372
+
3373
+ @property
3374
+ def emissionColor(self):
3375
+ """Emission color of the material."""
3376
+ return self._emissionColor
3377
+
3378
+ @emissionColor.setter
3379
+ def emissionColor(self, value):
3380
+ self._emissionColor = np.asarray(value, np.float32)
3381
+ setColor(self, value, colorSpace=self.colorSpace, operation=None,
3382
+ rgbAttrib='emissionRGB', colorAttrib='emissionColor',
3383
+ colorSpaceAttrib='colorSpace')
3384
+
3385
+ @property
3386
+ def emissionRGB(self):
3387
+ """Diffuse color of the material."""
3388
+ return self._emissionRGB[:3]
3389
+
3390
+ @emissionRGB.setter
3391
+ def emissionRGB(self, value):
3392
+ # make sure the color we got is 32-bit float
3393
+ self._emissionRGB = np.zeros((4,), np.float32)
3394
+ self._emissionRGB[:3] = (value * self.contrast + 1) / 2.0
3395
+ self._emissionRGB[3] = self.opacity
3396
+
3397
+ @property
3398
+ def shininess(self):
3399
+ return self._shininess
3400
+
3401
+ @shininess.setter
3402
+ def shininess(self, value):
3403
+ self._shininess = float(value)
3404
+
3405
+
3406
+ def useMaterial(material, useTextures=True):
3407
+ """Use a material for proceeding vertex draws.
3408
+
3409
+ Parameters
3410
+ ----------
3411
+ material : :obj:`Material` or None
3412
+ Material descriptor to use. Default material properties are set if None
3413
+ is specified. This is equivalent to disabling materials.
3414
+ useTextures : :obj:`bool`
3415
+ Enable textures. Textures specified in a material descriptor's 'texture'
3416
+ attribute will be bound and their respective texture units will be
3417
+ enabled. Note, when disabling materials, the value of useTextures must
3418
+ match the previous call. If there are no textures attached to the
3419
+ material, useTexture will be silently ignored.
3420
+
3421
+ Returns
3422
+ -------
3423
+ None
3424
+
3425
+ Notes
3426
+ -----
3427
+ 1. If a material mode has a value of None, a color with all components 0.0
3428
+ will be assigned.
3429
+ 2. Material colors and shininess values are accessible from shader programs
3430
+ after calling 'useMaterial'. Values can be accessed via built-in
3431
+ 'gl_FrontMaterial' and 'gl_BackMaterial' structures (e.g.
3432
+ gl_FrontMaterial.diffuse).
3433
+
3434
+ Examples
3435
+ --------
3436
+ Use a material when drawing::
3437
+
3438
+ useMaterial(metalMaterials.gold)
3439
+ drawVAO( ... ) # all meshes drawn will be gold
3440
+ useMaterial(None) # turn off material when done
3441
+
3442
+ """
3443
+ if material is not None:
3444
+ GL.glDisable(GL.GL_COLOR_MATERIAL) # disable color tracking
3445
+ face = material._face
3446
+ GL.glColorMaterial(face, GL.GL_AMBIENT_AND_DIFFUSE)
3447
+
3448
+ # convert data in light class to ctypes
3449
+ diffuse = np.ctypeslib.as_ctypes(material._diffuseRGB)
3450
+ specular = np.ctypeslib.as_ctypes(material._specularRGB)
3451
+ ambient = np.ctypeslib.as_ctypes(material._ambientRGB)
3452
+ emission = np.ctypeslib.as_ctypes(material._emissionRGB)
3453
+
3454
+ # pass values to OpenGL
3455
+ GL.glMaterialfv(face, GL.GL_DIFFUSE, diffuse)
3456
+ GL.glMaterialfv(face, GL.GL_SPECULAR, specular)
3457
+ GL.glMaterialfv(face, GL.GL_AMBIENT, ambient)
3458
+ GL.glMaterialfv(face, GL.GL_EMISSION, emission)
3459
+ GL.glMaterialf(face, GL.GL_SHININESS, material.shininess)
3460
+
3461
+ # setup textures
3462
+ if useTextures and material.diffuseTexture is not None:
3463
+ material._useTextures = True
3464
+ GL.glEnable(GL.GL_TEXTURE_2D)
3465
+ if material.diffuseTexture is not None:
3466
+ bindTexture(material.diffuseTexture, 0)
3467
+ else:
3468
+ material._useTextures = False
3469
+ GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
3470
+ GL.glDisable(GL.GL_TEXTURE_2D)
3471
+ else:
3472
+ for mode, param in defaultMaterial.params.items():
3473
+ GL.glEnable(GL.GL_COLOR_MATERIAL)
3474
+ GL.glMaterialfv(GL.GL_FRONT_AND_BACK, mode, param)
3475
+
3476
+
3477
+ def clearMaterial(material):
3478
+ """Stop using a material."""
3479
+ for mode, param in defaultMaterial.params.items():
3480
+ GL.glMaterialfv(GL.GL_FRONT_AND_BACK, mode, param)
3481
+
3482
+ if material._useTextures:
3483
+ if material.diffuseTexture is not None:
3484
+ unbindTexture(material.diffuseTexture)
3485
+
3486
+ GL.glDisable(GL.GL_TEXTURE_2D)
3487
+
3488
+ GL.glDisable(GL.GL_COLOR_MATERIAL) # disable color tracking
3489
+
3490
+
3491
+ # -------------------------
3492
+ # Lighting Helper Functions
3493
+ # -------------------------
3494
+
3495
+ Light = namedtuple('Light', ['params', 'userData'])
3496
+
3497
+
3498
+ def createLight(params=()):
3499
+ """Create a point light source.
3500
+
3501
+ """
3502
+ # setup light mode/value slots
3503
+ lightDesc = Light({mode: None for mode in (
3504
+ GL.GL_AMBIENT,
3505
+ GL.GL_DIFFUSE,
3506
+ GL.GL_SPECULAR,
3507
+ GL.GL_POSITION,
3508
+ GL.GL_SPOT_CUTOFF,
3509
+ GL.GL_SPOT_DIRECTION,
3510
+ GL.GL_SPOT_EXPONENT,
3511
+ GL.GL_CONSTANT_ATTENUATION,
3512
+ GL.GL_LINEAR_ATTENUATION,
3513
+ GL.GL_QUADRATIC_ATTENUATION)}, dict())
3514
+
3515
+ # configure lights
3516
+ if params:
3517
+ for mode, value in params:
3518
+ if value is not None:
3519
+ if mode in [GL.GL_AMBIENT, GL.GL_DIFFUSE, GL.GL_SPECULAR,
3520
+ GL.GL_POSITION]:
3521
+ lightDesc.params[mode] = (GL.GLfloat * 4)(*value)
3522
+ elif mode == GL.GL_SPOT_DIRECTION:
3523
+ lightDesc.params[mode] = (GL.GLfloat * 3)(*value)
3524
+ else:
3525
+ lightDesc.params[mode] = GL.GLfloat(value)
3526
+
3527
+ return lightDesc
3528
+
3529
+
3530
+ def useLights(lights, setupOnly=False):
3531
+ """Use specified lights in successive rendering operations. All lights will
3532
+ be transformed using the present modelview matrix.
3533
+
3534
+ Parameters
3535
+ ----------
3536
+ lights : :obj:`List` of :obj:`Light` or None
3537
+ Descriptor of a light source. If None, lighting is disabled.
3538
+ setupOnly : :obj:`bool`, optional
3539
+ Do not enable lighting or lights. Specify True if lighting is being
3540
+ computed via fragment shaders.
3541
+
3542
+ """
3543
+ if lights is not None:
3544
+ if len(lights) > getIntegerv(GL.GL_MAX_LIGHTS):
3545
+ raise IndexError("Number of lights specified > GL_MAX_LIGHTS.")
3546
+
3547
+ GL.glEnable(GL.GL_NORMALIZE)
3548
+
3549
+ for index, light in enumerate(lights):
3550
+ enumLight = GL.GL_LIGHT0 + index
3551
+ # light properties
3552
+ for mode, value in light.params.items():
3553
+ if value is not None:
3554
+ GL.glLightfv(enumLight, mode, value)
3555
+
3556
+ if not setupOnly:
3557
+ GL.glEnable(enumLight)
3558
+
3559
+ if not setupOnly:
3560
+ GL.glEnable(GL.GL_LIGHTING)
3561
+ else:
3562
+ # disable lights
3563
+ if not setupOnly:
3564
+ for enumLight in range(getIntegerv(GL.GL_MAX_LIGHTS)):
3565
+ GL.glDisable(GL.GL_LIGHT0 + enumLight)
3566
+
3567
+ GL.glDisable(GL.GL_NORMALIZE)
3568
+ GL.glDisable(GL.GL_LIGHTING)
3569
+
3570
+
3571
+ def setAmbientLight(color):
3572
+ """Set the global ambient lighting for the scene when lighting is enabled.
3573
+ This is equivalent to GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, color)
3574
+ and does not contribute to the GL_MAX_LIGHTS limit.
3575
+
3576
+ Parameters
3577
+ ----------
3578
+ color : :obj:`tuple`
3579
+ Ambient lighting RGBA intensity for the whole scene.
3580
+
3581
+ Notes
3582
+ -----
3583
+ If unset, the default value is (0.2, 0.2, 0.2, 1.0) when GL_LIGHTING is
3584
+ enabled.
3585
+
3586
+ """
3587
+ GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, (GL.GLfloat * 4)(*color))
3588
+
3589
+
3590
+ # -------------------------
3591
+ # 3D Model Helper Functions
3592
+ # -------------------------
3593
+ #
3594
+ # These functions are used in the creation, manipulation and rendering of 3D
3595
+ # model data.
3596
+ #
3597
+
3598
+
3599
+ class ObjMeshInfo:
3600
+ """Descriptor for mesh data loaded from a Wavefront OBJ file.
3601
+
3602
+ """
3603
+ __slots__ = [
3604
+ 'vertexPos',
3605
+ 'texCoords',
3606
+ 'normals',
3607
+ 'faces',
3608
+ 'extents',
3609
+ 'mtlFile']
3610
+
3611
+ def __init__(self,
3612
+ vertexPos=None,
3613
+ texCoords=None,
3614
+ normals=None,
3615
+ faces=None,
3616
+ extents=None,
3617
+ mtlFile=None):
3618
+
3619
+ self.vertexPos = vertexPos
3620
+ self.texCoords = texCoords
3621
+ self.normals = normals
3622
+ self.faces = faces
3623
+ self.extents = extents
3624
+ self.mtlFile = mtlFile
3625
+
3626
+
3627
+ def loadObjFile(objFile):
3628
+ """Load a Wavefront OBJ file (*.obj).
3629
+
3630
+ Loads vertex, normals, and texture coordinates from the provided `*.obj` file
3631
+ into arrays. These arrays can be processed then loaded into vertex buffer
3632
+ objects (VBOs) for rendering. The `*.obj` file must at least specify vertex
3633
+ position data to be loaded successfully. Normals and texture coordinates are
3634
+ optional.
3635
+
3636
+ Faces can be either triangles or quads, but not both. Faces are grouped by
3637
+ their materials. Index arrays are generated for each material present in the
3638
+ file.
3639
+
3640
+ Data from the returned `ObjMeshInfo` object can be used to create vertex
3641
+ buffer objects and arrays for rendering. See `Examples` below for details on
3642
+ how to do this.
3643
+
3644
+ Parameters
3645
+ ----------
3646
+ objFile : :obj:`str`
3647
+ Path to the `*.OBJ` file to load.
3648
+
3649
+ Returns
3650
+ -------
3651
+ ObjMeshInfo
3652
+ Mesh data.
3653
+
3654
+ See Also
3655
+ --------
3656
+ loadMtlFile : Load a `*.mtl` file.
3657
+
3658
+ Notes
3659
+ -----
3660
+ 1. This importer should work fine for most sanely generated files. Export
3661
+ your model with Blender for best results, even if you used some other
3662
+ package to create it.
3663
+ 2. The mesh cannot contain both triangles and quads.
3664
+
3665
+ Examples
3666
+ --------
3667
+ Loading a `*.obj` mode from file::
3668
+
3669
+ objModel = loadObjFile('/path/to/file.obj')
3670
+ # load the material (*.mtl) file, textures are also loaded
3671
+ mtllib = loadMtl('/path/to/' + objModel.mtlFile)
3672
+
3673
+ Creating separate vertex buffer objects (VBOs) for each vertex attribute::
3674
+
3675
+ vertexPosVBO = createVBO(objModel.vertexPos)
3676
+ texCoordVBO = createVBO(objModel.texCoords)
3677
+ normalsVBO = createVBO(objModel.normals)
3678
+
3679
+ Create vertex array objects (VAOs) to draw the mesh. We create VAOs for each
3680
+ face material::
3681
+
3682
+ objVAOs = {} # dictionary for VAOs
3683
+ # for each material create a VAO
3684
+ # keys are material names, values are index buffers
3685
+ for material, faces in objModel.faces.items():
3686
+ # convert index buffer to VAO
3687
+ indexBuffer = \
3688
+ gltools.createVBO(
3689
+ faces.flatten(), # flatten face index for element array
3690
+ target=GL.GL_ELEMENT_ARRAY_BUFFER,
3691
+ dataType=GL.GL_UNSIGNED_INT)
3692
+
3693
+ # see `setVertexAttribPointer` for more information about attribute
3694
+ # pointer indices
3695
+ objVAOs[material] = gltools.createVAO(
3696
+ {0: vertexPosVBO, # 0 = gl_Vertex
3697
+ 8: texCoordVBO, # 8 = gl_MultiTexCoord0
3698
+ 2: normalsVBO}, # 2 = gl_Normal
3699
+ indexBuffer=indexBuffer)
3700
+
3701
+ # if using legacy attribute pointers, do this instead ...
3702
+ # objVAOs[key] = createVAO({GL_VERTEX_ARRAY: vertexPosVBO,
3703
+ # GL_TEXTURE_COORD_ARRAY: texCoordVBO,
3704
+ # GL_NORMAL_ARRAY: normalsVBO},
3705
+ # indexBuffer=indexBuffer,
3706
+ # legacy=True) # this needs to be `True`
3707
+
3708
+ To render the VAOs using `objVAOs` created above, do the following::
3709
+
3710
+ for material, vao in objVAOs.items():
3711
+ useMaterial(mtllib[material])
3712
+ drawVAO(vao)
3713
+
3714
+ useMaterial(None) # disable materials when done
3715
+
3716
+ Optionally, you can create a single-storage, interleaved VBO by using
3717
+ `numpy.hstack`. On some GL implementations, using single-storage buffers
3718
+ offers better performance::
3719
+
3720
+ interleavedData = numpy.hstack(
3721
+ (objModel.vertexPos, objModel.texCoords, objModel.normals))
3722
+ vertexData = createVBO(interleavedData)
3723
+
3724
+ Creating VAOs with interleaved, single-storage buffers require specifying
3725
+ additional information, such as `size` and `offset`::
3726
+
3727
+ objVAOs = {}
3728
+ for key, val in objModel.faces.items():
3729
+ indexBuffer = \
3730
+ gltools.createVBO(
3731
+ faces.flatten(),
3732
+ target=GL.GL_ELEMENT_ARRAY_BUFFER,
3733
+ dataType=GL.GL_UNSIGNED_INT)
3734
+
3735
+ objVAOs[key] = createVAO({0: (vertexData, 3, 0), # size=3, offset=0
3736
+ 8: (vertexData, 2, 3), # size=2, offset=3
3737
+ 2: (vertexData, 3, 5), # size=3, offset=5
3738
+ indexBuffer=val)
3739
+
3740
+ Drawing VAOs with interleaved buffers is exactly the same as shown before
3741
+ with separate buffers.
3742
+
3743
+ """
3744
+ # open the file, read it into memory
3745
+ with open(objFile, 'r') as f:
3746
+ objBuffer = StringIO(f.read())
3747
+
3748
+ mtlFile = None
3749
+
3750
+ # unsorted attribute data lists
3751
+ positionDefs = []
3752
+ texCoordDefs = []
3753
+ normalDefs = []
3754
+ vertexAttrs = {}
3755
+
3756
+ # material groups
3757
+ materialGroup = None
3758
+ materialGroups = {}
3759
+
3760
+ nVertices = nTextureCoords = nNormals = nFaces = 0
3761
+ vertexIdx = 0
3762
+ # first pass, examine the file and load up vertex attributes
3763
+ for line in objBuffer.readlines():
3764
+ line = line.strip() # clean up like
3765
+ if line.startswith('v '):
3766
+ positionDefs.append(tuple(map(float, line[2:].split(' '))))
3767
+ nVertices += 1
3768
+ elif line.startswith('vt '):
3769
+ texCoordDefs.append(tuple(map(float, line[3:].split(' '))))
3770
+ nTextureCoords += 1
3771
+ elif line.startswith('vn '):
3772
+ normalDefs.append(tuple(map(float, line[3:].split(' '))))
3773
+ nNormals += 1
3774
+ elif line.startswith('f '):
3775
+ faceAttrs = [] # attributes this face
3776
+ for attrs in line[2:].split(' '): # triangle vertex attrs
3777
+ if attrs not in vertexAttrs.keys():
3778
+ vertexAttrs[attrs] = vertexIdx
3779
+ vertexIdx += 1
3780
+ faceAttrs.append(vertexAttrs[attrs])
3781
+ materialGroups[materialGroup].append(faceAttrs)
3782
+ nFaces += 1
3783
+ elif line.startswith('o '): # ignored for now
3784
+ pass
3785
+ elif line.startswith('g '): # ignored for now
3786
+ pass
3787
+ elif line.startswith('usemtl '):
3788
+ foundMaterial = line[7:]
3789
+ if foundMaterial not in materialGroups.keys():
3790
+ materialGroups[foundMaterial] = []
3791
+ materialGroup = foundMaterial
3792
+ elif line.startswith('mtllib '):
3793
+ mtlFile = line.strip()[7:]
3794
+
3795
+ # at the very least, we need vertices and facedefs
3796
+ if nVertices == 0 or nFaces == 0:
3797
+ raise RuntimeError(
3798
+ "Failed to load OBJ file, file contains no vertices or faces.")
3799
+
3800
+ # convert indices for materials to numpy arrays
3801
+ for key, val in materialGroups.items():
3802
+ materialGroups[key] = np.asarray(val, dtype=int)
3803
+
3804
+ # indicate if file has any texture coordinates of normals
3805
+ hasTexCoords = nTextureCoords > 0
3806
+ hasNormals = nNormals > 0
3807
+
3808
+ # lists for vertex attributes
3809
+ vertexPos = []
3810
+ vertexTexCoord = []
3811
+ vertexNormal = []
3812
+
3813
+ # populate vertex attribute arrays
3814
+ for attrs, idx in vertexAttrs.items():
3815
+ attr = attrs.split('/')
3816
+ vertexPos.append(positionDefs[int(attr[0]) - 1])
3817
+ if len(attr) > 1: # has texture coords
3818
+ if hasTexCoords:
3819
+ if attr[1] != '': # texcoord field not empty
3820
+ vertexTexCoord.append(texCoordDefs[int(attr[1]) - 1])
3821
+ else:
3822
+ vertexTexCoord.append([0., 0.]) # fill with zeros
3823
+ if len(attr) > 2: # has normals too
3824
+ if hasNormals:
3825
+ vertexNormal.append(normalDefs[int(attr[2]) - 1])
3826
+ else:
3827
+ vertexNormal.append([0., 0., 0.]) # fill with zeros
3828
+
3829
+ # convert vertex attribute lists to numeric arrays
3830
+ vertexPos = np.asarray(vertexPos)
3831
+ vertexTexCoord = np.asarray(vertexTexCoord)
3832
+ vertexNormal = np.asarray(vertexNormal)
3833
+
3834
+ # compute the extents of the model, needed for axis-aligned bounding boxes
3835
+ extents = (vertexPos.min(axis=0), vertexPos.max(axis=0))
3836
+
3837
+ # resolve the path to the material file associated with the mesh
3838
+ if mtlFile is not None:
3839
+ mtlFile = os.path.join(os.path.split(objFile)[0], mtlFile)
3840
+
3841
+ return ObjMeshInfo(vertexPos,
3842
+ vertexTexCoord,
3843
+ vertexNormal,
3844
+ materialGroups,
3845
+ extents,
3846
+ mtlFile)
3847
+
3848
+
3849
+ def loadMtlFile(mtllib, texParams=None):
3850
+ """Load a material library file (*.mtl).
3851
+
3852
+ Parameters
3853
+ ----------
3854
+ mtllib : str
3855
+ Path to the material library file.
3856
+ texParams : list or tuple
3857
+ Optional texture parameters for loaded textures. Texture parameters are
3858
+ specified as a list of tuples. Each item specifies the option and
3859
+ parameter. For instance,
3860
+ `[(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR), ...]`. By default, linear
3861
+ filtering is used for both the minifying and magnification filter
3862
+ functions. This is adequate for most uses.
3863
+
3864
+ Returns
3865
+ -------
3866
+ dict
3867
+ Dictionary of materials. Where each key is the material name found in
3868
+ the file, and values are `Material` namedtuple objects.
3869
+
3870
+ See Also
3871
+ --------
3872
+ loadObjFile : Load an `*.OBJ` file.
3873
+
3874
+ Examples
3875
+ --------
3876
+ Load material associated with an `*.OBJ` file::
3877
+
3878
+ objModel = loadObjFile('/path/to/file.obj')
3879
+ # load the material (*.mtl) file, textures are also loaded
3880
+ mtllib = loadMtl('/path/to/' + objModel.mtlFile)
3881
+
3882
+ Use a material when rendering vertex arrays::
3883
+
3884
+ useMaterial(mtllib[material])
3885
+ drawVAO(vao)
3886
+ useMaterial(None) # disable materials when done
3887
+
3888
+ """
3889
+ # open the file, read it into memory
3890
+ with open(mtllib, 'r') as mtlFile:
3891
+ mtlBuffer = StringIO(mtlFile.read())
3892
+
3893
+ # default texture parameters
3894
+ if texParams is None:
3895
+ texParams = {GL.GL_TEXTURE_MAG_FILTER: GL.GL_LINEAR,
3896
+ GL.GL_TEXTURE_MIN_FILTER: GL.GL_LINEAR}
3897
+
3898
+ foundMaterials = {}
3899
+ foundTextures = {}
3900
+ thisMaterial = 0
3901
+ for line in mtlBuffer.readlines():
3902
+ line = line.strip()
3903
+ if line.startswith('newmtl '): # new material
3904
+ thisMaterial = line[7:]
3905
+ foundMaterials[thisMaterial] = SimpleMaterial()
3906
+ elif line.startswith('Ns '): # specular exponent
3907
+ foundMaterials[thisMaterial].shininess = line[3:]
3908
+ elif line.startswith('Ks '): # specular color
3909
+ specularColor = np.asarray(list(map(float, line[3:].split(' '))))
3910
+ specularColor = 2.0 * specularColor - 1
3911
+ foundMaterials[thisMaterial].specularColor = specularColor
3912
+ elif line.startswith('Kd '): # diffuse color
3913
+ diffuseColor = np.asarray(list(map(float, line[3:].split(' '))))
3914
+ diffuseColor = 2.0 * diffuseColor - 1
3915
+ foundMaterials[thisMaterial].diffuseColor = diffuseColor
3916
+ elif line.startswith('Ka '): # ambient color
3917
+ ambientColor = np.asarray(list(map(float, line[3:].split(' '))))
3918
+ ambientColor = 2.0 * ambientColor - 1
3919
+ foundMaterials[thisMaterial].ambientColor = ambientColor
3920
+ elif line.startswith('map_Kd '): # diffuse color map
3921
+ # load a diffuse texture from file
3922
+ textureName = line[7:]
3923
+ if textureName not in foundTextures.keys():
3924
+ im = Image.open(
3925
+ os.path.join(os.path.split(mtllib)[0], textureName))
3926
+ im = im.transpose(Image.FLIP_TOP_BOTTOM)
3927
+ im = im.convert("RGBA")
3928
+ pixelData = np.array(im).ctypes
3929
+ width = pixelData.shape[1]
3930
+ height = pixelData.shape[0]
3931
+ foundTextures[textureName] = createTexImage2D(
3932
+ width,
3933
+ height,
3934
+ internalFormat=GL.GL_RGBA,
3935
+ pixelFormat=GL.GL_RGBA,
3936
+ dataType=GL.GL_UNSIGNED_BYTE,
3937
+ data=pixelData,
3938
+ unpackAlignment=1,
3939
+ texParams=texParams)
3940
+ foundMaterials[thisMaterial].diffuseTexture = \
3941
+ foundTextures[textureName]
3942
+
3943
+ return foundMaterials
3944
+
3945
+
3946
+ def createUVSphere(radius=0.5, sectors=16, stacks=16, flipFaces=False):
3947
+ """Create a UV sphere.
3948
+
3949
+ Procedurally generate a UV sphere by specifying its radius, and number of
3950
+ stacks and sectors. The poles of the resulting sphere will be aligned with
3951
+ the Z-axis.
3952
+
3953
+ Surface normals and texture coordinates are automatically generated. The
3954
+ returned normals are computed to produce smooth shading.
3955
+
3956
+ Parameters
3957
+ ----------
3958
+ radius : float, optional
3959
+ Radius of the sphere in scene units (usually meters). Default is 0.5.
3960
+ sectors, stacks : int, optional
3961
+ Number of longitudinal and latitudinal sub-divisions. Default is 16 for
3962
+ both.
3963
+ flipFaces : bool, optional
3964
+ If `True`, normals and face windings will be set to point inward towards
3965
+ the center of the sphere. Texture coordinates will remain the same.
3966
+ Default is `False`.
3967
+
3968
+ Returns
3969
+ -------
3970
+ tuple
3971
+ Vertex attribute arrays (position, texture coordinates, and normals) and
3972
+ triangle indices.
3973
+
3974
+ Examples
3975
+ --------
3976
+ Create a UV sphere and VAO to render it::
3977
+
3978
+ vertices, textureCoords, normals, faces = \
3979
+ gltools.createUVSphere(sectors=32, stacks=32)
3980
+
3981
+ vertexVBO = gltools.createVBO(vertices)
3982
+ texCoordVBO = gltools.createVBO(textureCoords)
3983
+ normalsVBO = gltools.createVBO(normals)
3984
+ indexBuffer = gltools.createVBO(
3985
+ faces.flatten(),
3986
+ target=GL.GL_ELEMENT_ARRAY_BUFFER,
3987
+ dataType=GL.GL_UNSIGNED_INT)
3988
+
3989
+ vao = gltools.createVAO({0: vertexVBO, 8: texCoordVBO, 2: normalsVBO},
3990
+ indexBuffer=indexBuffer)
3991
+
3992
+ # in the rendering loop
3993
+ gltools.drawVAO(vao, GL.GL_TRIANGLES)
3994
+
3995
+ The color of the sphere can be changed by calling `glColor*`::
3996
+
3997
+ glColor4f(1.0, 0.0, 0.0, 1.0) # red
3998
+ gltools.drawVAO(vao, GL.GL_TRIANGLES)
3999
+
4000
+ Raw coordinates can be transformed prior to uploading to VBOs. Here we can
4001
+ rotate vertex positions and normals so the equator rests on Z-axis::
4002
+
4003
+ r = mt.rotationMatrix(90.0, (1.0, 0, 0.0)) # 90 degrees about +X axis
4004
+ vertices = mt.applyMatrix(r, vertices)
4005
+ normals = mt.applyMatrix(r, normals)
4006
+
4007
+ """
4008
+ # based of the code found here https://www.songho.ca/opengl/gl_sphere.html
4009
+ sectorStep = 2.0 * np.pi / sectors
4010
+ stackStep = np.pi / stacks
4011
+ lengthInv = 1.0 / radius
4012
+
4013
+ vertices = []
4014
+ normals = []
4015
+ texCoords = []
4016
+
4017
+ for i in range(stacks + 1):
4018
+ stackAngle = np.pi / 2.0 - i * stackStep
4019
+ xy = radius * np.cos(stackAngle)
4020
+ z = radius * np.sin(stackAngle)
4021
+
4022
+ for j in range(sectors + 1):
4023
+ sectorAngle = j * sectorStep
4024
+ x = xy * np.cos(sectorAngle)
4025
+ y = xy * np.sin(sectorAngle)
4026
+
4027
+ vertices.append((x, y, z))
4028
+
4029
+ nx = x * lengthInv
4030
+ ny = y * lengthInv
4031
+ nz = z * lengthInv
4032
+
4033
+ normals.append((nx, ny, nz))
4034
+
4035
+ s = 1.0 - j / float(sectors)
4036
+ t = i / float(stacks)
4037
+
4038
+ texCoords.append((s, t))
4039
+
4040
+ # generate index
4041
+ indices = []
4042
+ for i in range(stacks):
4043
+ k1 = i * (sectors + 1)
4044
+ k2 = k1 + sectors + 1
4045
+
4046
+ for j in range(sectors):
4047
+ # case for caps
4048
+ if not flipFaces:
4049
+ if i != 0:
4050
+ indices.append((k1, k2, k1 + 1))
4051
+
4052
+ if i != stacks - 1:
4053
+ indices.append((k1 + 1, k2, k2 + 1))
4054
+ else:
4055
+ if i != 0:
4056
+ indices.append((k1, k1 + 1, k2))
4057
+
4058
+ if i != stacks - 1:
4059
+ indices.append((k1 + 1, k2 + 1, k2))
4060
+
4061
+ k1 += 1
4062
+ k2 += 1
4063
+
4064
+ # convert to numpy arrays
4065
+ vertices = np.ascontiguousarray(vertices, dtype=np.float32)
4066
+ normals = np.ascontiguousarray(normals, dtype=np.float32)
4067
+ texCoords = np.ascontiguousarray(texCoords, dtype=np.float32)
4068
+ faces = np.ascontiguousarray(indices, dtype=np.uint32)
4069
+
4070
+ if flipFaces: # flip normals so they point inwards
4071
+ normals *= -1.0
4072
+
4073
+ return vertices, texCoords, normals, faces
4074
+
4075
+
4076
+ def createPlane(size=(1., 1.)):
4077
+ """Create a plane.
4078
+
4079
+ Procedurally generate a plane (or quad) mesh by specifying its size. Texture
4080
+ coordinates are computed automatically, with origin at the bottom left of
4081
+ the plane. The generated plane is perpendicular to the +Z axis, origin of
4082
+ the plane is at its center.
4083
+
4084
+ Parameters
4085
+ ----------
4086
+ size : tuple or float
4087
+ Dimensions of the plane. If a single value is specified, the plane will
4088
+ be square. Provide a tuple of floats to specify the width and length of
4089
+ the plane (eg. `size=(0.2, 1.3)`).
4090
+
4091
+ Returns
4092
+ -------
4093
+ tuple
4094
+ Vertex attribute arrays (position, texture coordinates, and normals) and
4095
+ triangle indices.
4096
+
4097
+ Examples
4098
+ --------
4099
+ Create a plane mesh and draw it::
4100
+
4101
+ vertices, textureCoords, normals, faces = gltools.createPlane()
4102
+
4103
+ vertexVBO = gltools.createVBO(vertices)
4104
+ texCoordVBO = gltools.createVBO(textureCoords)
4105
+ normalsVBO = gltools.createVBO(normals)
4106
+ indexBuffer = gltools.createVBO(
4107
+ faces.flatten(),
4108
+ target=GL.GL_ELEMENT_ARRAY_BUFFER,
4109
+ dataType=GL.GL_UNSIGNED_INT)
4110
+
4111
+ vao = gltools.createVAO({0: vertexVBO, 8: texCoordVBO, 2: normalsVBO},
4112
+ indexBuffer=indexBuffer)
4113
+
4114
+ # in the rendering loop
4115
+ gltools.drawVAO(vao, GL.GL_TRIANGLES)
4116
+
4117
+ """
4118
+ if isinstance(size, (int, float,)):
4119
+ sx = sy = float(size) / 2.
4120
+ else:
4121
+ sx = size[0] / 2.
4122
+ sy = size[1] / 2.
4123
+
4124
+ vertices = np.ascontiguousarray(
4125
+ [[-1., 1., 0.],
4126
+ [ 1., 1., 0.],
4127
+ [-1., -1., 0.],
4128
+ [ 1., -1., 0.]])
4129
+
4130
+ if sx != 1.:
4131
+ vertices[:, 0] *= sx
4132
+
4133
+ if sy != 1.:
4134
+ vertices[:, 1] *= sy
4135
+
4136
+ # texture coordinates
4137
+ texCoords = np.ascontiguousarray([[0., 1.], [1., 1.], [0., 0.], [1., 0.]])
4138
+
4139
+ # normals, facing +Z
4140
+ normals = np.zeros_like(vertices)
4141
+ normals[:, 0] = 0.
4142
+ normals[:, 1] = 0.
4143
+ normals[:, 2] = 1.
4144
+
4145
+ # generate face index
4146
+ faces = np.ascontiguousarray([[0, 2, 1], [1, 2, 3]], dtype=np.uint32)
4147
+
4148
+ return vertices, texCoords, normals, faces
4149
+
4150
+
4151
+ def createMeshGridFromArrays(xvals, yvals, zvals=None, tessMode='diag', computeNormals=True):
4152
+ """Create a mesh grid using coordinates from arrays.
4153
+
4154
+ Generates a mesh using data in provided in 2D arrays of vertex coordinates.
4155
+ Triangle faces are automatically computed by this function by joining
4156
+ adjacent vertices at neighbouring indices in the array. Texture coordinates
4157
+ are generated covering the whole mesh, with origin at the bottom left.
4158
+
4159
+ Parameters
4160
+ ----------
4161
+ xvals, yvals : array_like
4162
+ NxM arrays of X and Y coordinates. Both arrays must have the same
4163
+ shape. the resulting mesh will have a single vertex for each X and Y
4164
+ pair. Faces will be generated to connect adjacent coordinates in the
4165
+ array.
4166
+ zvals : array_like, optional
4167
+ NxM array of Z coordinates for each X and Y. Must have the same shape
4168
+ as X and Y. If not specified, the Z coordinates will be filled with
4169
+ zeros.
4170
+ tessMode : str, optional
4171
+ Tessellation mode. Specifies how faces are generated. Options are
4172
+ 'center', 'radial', and 'diag'. Default is 'diag'. Modes 'radial' and
4173
+ 'center' work best with odd numbered array dimensions.
4174
+ computeNormals : bool, optional
4175
+ Compute normals for the generated mesh. If `False`, all normals are set
4176
+ to face in the +Z direction. Presently, computing normals is a slow
4177
+ operation and may not be needed for some meshes.
4178
+
4179
+ Returns
4180
+ -------
4181
+ tuple
4182
+ Vertex attribute arrays (position, texture coordinates, and normals) and
4183
+ triangle indices.
4184
+
4185
+ Examples
4186
+ --------
4187
+ Create a 3D sine grating mesh using 2D arrays::
4188
+
4189
+ x = np.linspace(0, 1.0, 32)
4190
+ y = np.linspace(1.0, 0.0, 32)
4191
+ xx, yy = np.meshgrid(x, y)
4192
+ zz = np.tile(np.sin(np.linspace(0.0, 32., 32)) * 0.02, (32, 1))
4193
+
4194
+ vertices, textureCoords, normals, faces = \
4195
+ gltools.createMeshGridFromArrays(xx, yy, zz)
4196
+
4197
+ """
4198
+ vertices = np.vstack([xvals.ravel(), yvals.ravel()]).T
4199
+
4200
+ if zvals is not None:
4201
+ assert xvals.shape == yvals.shape == zvals.shape
4202
+ else:
4203
+ assert xvals.shape == yvals.shape
4204
+
4205
+ if zvals is None:
4206
+ # fill z with zeros if not provided
4207
+ vertices = np.hstack([vertices, np.zeros((vertices.shape[0], 1))])
4208
+ else:
4209
+ vertices = np.hstack([vertices, np.atleast_2d(zvals.ravel()).T])
4210
+
4211
+ ny, nx = xvals.shape
4212
+
4213
+ # texture coordinates
4214
+ u = np.linspace(0.0, 1.0, nx)
4215
+ v = np.linspace(1.0, 0.0, ny)
4216
+ uu, vv = np.meshgrid(u, v)
4217
+
4218
+ texCoords = np.vstack([uu.ravel(), vv.ravel()]).T
4219
+
4220
+ # generate face index
4221
+ faces = []
4222
+
4223
+ if tessMode == 'diag':
4224
+ for i in range(ny - 1):
4225
+ k1 = i * nx
4226
+ k2 = k1 + nx
4227
+
4228
+ for j in range(nx - 1):
4229
+ faces.append([k1, k2, k1 + 1])
4230
+ faces.append([k1 + 1, k2, k2 + 1])
4231
+
4232
+ k1 += 1
4233
+ k2 += 1
4234
+
4235
+ else:
4236
+ raise ValueError('Invalid value for `tessMode`.')
4237
+
4238
+ # convert to numpy arrays
4239
+ vertices = np.ascontiguousarray(vertices, dtype=np.float32)
4240
+ texCoords = np.ascontiguousarray(texCoords, dtype=np.float32)
4241
+ faces = np.ascontiguousarray(faces, dtype=np.uint32)
4242
+
4243
+ # calculate surface normals for the mesh
4244
+ if computeNormals:
4245
+ normals = calculateVertexNormals(vertices, faces, shading='smooth')
4246
+ else:
4247
+ normals = np.zeros_like(vertices, dtype=np.float32)
4248
+ normals[:, 2] = 1.
4249
+
4250
+ return vertices, texCoords, normals, faces
4251
+
4252
+
4253
+ def createMeshGrid(size=(1., 1.), subdiv=0, tessMode='diag'):
4254
+ """Create a grid mesh.
4255
+
4256
+ Procedurally generate a grid mesh by specifying its size and number of
4257
+ sub-divisions. Texture coordinates are computed automatically. The origin is
4258
+ at the center of the mesh. The generated grid is perpendicular to the +Z
4259
+ axis, origin of the grid is at its center.
4260
+
4261
+ Parameters
4262
+ ----------
4263
+ size : tuple or float
4264
+ Dimensions of the mesh. If a single value is specified, the plane will
4265
+ be square. Provide a tuple of floats to specify the width and length of
4266
+ the plane (eg. `size=(0.2, 1.3)`).
4267
+ subdiv : int, optional
4268
+ Number of subdivisions. Zero subdivisions are applied by default, and
4269
+ the resulting mesh will only have vertices at the corners.
4270
+ tessMode : str, optional
4271
+ Tessellation mode. Specifies how faces are subdivided. Options are
4272
+ 'center', 'radial', and 'diag'. Default is 'diag'. Modes 'radial' and
4273
+ 'center' work best with an odd number of subdivisions.
4274
+
4275
+ Returns
4276
+ -------
4277
+ tuple
4278
+ Vertex attribute arrays (position, texture coordinates, and normals) and
4279
+ triangle indices.
4280
+
4281
+ Examples
4282
+ --------
4283
+ Create a grid mesh and draw it::
4284
+
4285
+ vertices, textureCoords, normals, faces = gltools.createPlane()
4286
+
4287
+ vertexVBO = gltools.createVBO(vertices)
4288
+ texCoordVBO = gltools.createVBO(textureCoords)
4289
+ normalsVBO = gltools.createVBO(normals)
4290
+ indexBuffer = gltools.createVBO(
4291
+ faces.flatten(),
4292
+ target=GL.GL_ELEMENT_ARRAY_BUFFER,
4293
+ dataType=GL.GL_UNSIGNED_INT)
4294
+
4295
+ vao = gltools.createVAO({0: vertexVBO, 8: texCoordVBO, 2: normalsVBO},
4296
+ indexBuffer=indexBuffer)
4297
+
4298
+ # in the rendering loop
4299
+ gltools.drawVAO(vao, GL.GL_TRIANGLES)
4300
+
4301
+ Randomly displace vertices off the plane of the grid by setting the `Z`
4302
+ value per vertex::
4303
+
4304
+ vertices, textureCoords, normals, faces = \
4305
+ gltools.createMeshGrid(subdiv=11)
4306
+
4307
+ numVerts = vertices.shape[0]
4308
+ vertices[:, 2] = np.random.uniform(-0.02, 0.02, (numVerts,))) # Z
4309
+
4310
+ # you must recompute surface normals to get correct shading!
4311
+ normals = gltools.calculateVertexNormals(vertices, faces)
4312
+
4313
+ # create a VAO as shown in the previous example here to draw it ...
4314
+
4315
+ """
4316
+ if isinstance(size, (int, float,)):
4317
+ divx = divy = float(size) / 2.
4318
+ else:
4319
+ divx = size[0] / 2.
4320
+ divy = size[1] / 2.
4321
+
4322
+ # generate plane vertices
4323
+ x = np.linspace(-divx, divx, subdiv + 2)
4324
+ y = np.linspace(divy, -divy, subdiv + 2)
4325
+ xx, yy = np.meshgrid(x, y)
4326
+
4327
+ vertices = np.vstack([xx.ravel(), yy.ravel()]).T
4328
+ vertices = np.hstack([vertices, np.zeros((vertices.shape[0], 1))]) # add z
4329
+
4330
+ # texture coordinates
4331
+ u = np.linspace(0.0, 1.0, subdiv + 2)
4332
+ v = np.linspace(1.0, 0.0, subdiv + 2)
4333
+ uu, vv = np.meshgrid(u, v)
4334
+
4335
+ texCoords = np.vstack([uu.ravel(), vv.ravel()]).T
4336
+
4337
+ # normals, facing +Z
4338
+ normals = np.zeros_like(vertices)
4339
+ normals[:, 0] = 0.
4340
+ normals[:, 1] = 0.
4341
+ normals[:, 2] = 1.
4342
+
4343
+ # generate face index
4344
+ faces = []
4345
+
4346
+ if tessMode == 'diag':
4347
+ for i in range(subdiv + 1):
4348
+ k1 = i * (subdiv + 2)
4349
+ k2 = k1 + subdiv + 2
4350
+
4351
+ for j in range(subdiv + 1):
4352
+ faces.append([k1, k2, k1 + 1])
4353
+ faces.append([k1 + 1, k2, k2 + 1])
4354
+
4355
+ k1 += 1
4356
+ k2 += 1
4357
+
4358
+ elif tessMode == 'center':
4359
+ lx = len(x)
4360
+ ly = len(y)
4361
+
4362
+ for i in range(subdiv + 1):
4363
+ k1 = i * (subdiv + 2)
4364
+ k2 = k1 + subdiv + 2
4365
+
4366
+ for j in range(subdiv + 1):
4367
+ if k1 + j < k1 + int((lx / 2)):
4368
+ if int(k1 / ly) + 1 > int(ly / 2):
4369
+ faces.append([k1, k2, k1 + 1])
4370
+ faces.append([k1 + 1, k2, k2 + 1])
4371
+ else:
4372
+ faces.append([k1, k2, k2 + 1])
4373
+ faces.append([k1 + 1, k1, k2 + 1])
4374
+ else:
4375
+ if int(k1 / ly) + 1 > int(ly / 2):
4376
+ faces.append([k1, k2, k2 + 1])
4377
+ faces.append([k1 + 1, k1, k2 + 1])
4378
+ else:
4379
+ faces.append([k1, k2, k1 + 1])
4380
+ faces.append([k1 + 1, k2, k2 + 1])
4381
+
4382
+ k1 += 1
4383
+ k2 += 1
4384
+
4385
+ elif tessMode == 'radial':
4386
+ lx = len(x)
4387
+ ly = len(y)
4388
+
4389
+ for i in range(subdiv + 1):
4390
+ k1 = i * (subdiv + 2)
4391
+ k2 = k1 + subdiv + 2
4392
+
4393
+ for j in range(subdiv + 1):
4394
+ if k1 + j < k1 + int((lx / 2)):
4395
+ if int(k1 / ly) + 1 > int(ly / 2):
4396
+ faces.append([k1, k2, k2 + 1])
4397
+ faces.append([k1 + 1, k1, k2 + 1])
4398
+ else:
4399
+ faces.append([k1, k2, k1 + 1])
4400
+ faces.append([k1 + 1, k2, k2 + 1])
4401
+ else:
4402
+ if int(k1 / ly) + 1 > int(ly / 2):
4403
+ faces.append([k1, k2, k1 + 1])
4404
+ faces.append([k1 + 1, k2, k2 + 1])
4405
+ else:
4406
+ faces.append([k1, k2, k2 + 1])
4407
+ faces.append([k1 + 1, k1, k2 + 1])
4408
+
4409
+ k1 += 1
4410
+ k2 += 1
4411
+
4412
+ else:
4413
+ raise ValueError('Invalid value for `tessMode`.')
4414
+
4415
+ # convert to numpy arrays
4416
+ vertices = np.ascontiguousarray(vertices, dtype=np.float32)
4417
+ texCoords = np.ascontiguousarray(texCoords, dtype=np.float32)
4418
+ normals = np.ascontiguousarray(normals, dtype=np.float32)
4419
+ faces = np.ascontiguousarray(faces, dtype=np.uint32)
4420
+
4421
+ return vertices, texCoords, normals, faces
4422
+
4423
+
4424
+ def createBox(size=(1., 1., 1.), flipFaces=False):
4425
+ """Create a box mesh.
4426
+
4427
+ Create a box mesh by specifying its `size` in three dimensions (x, y, z),
4428
+ or a single value (`float`) to create a cube. The resulting box will be
4429
+ centered about the origin. Texture coordinates and normals are automatically
4430
+ generated for each face.
4431
+
4432
+ Setting `flipFaces=True` will make faces and normals point inwards, this
4433
+ allows boxes to be viewed and lit correctly from the inside.
4434
+
4435
+ Parameters
4436
+ ----------
4437
+ size : tuple or float
4438
+ Dimensions of the mesh. If a single value is specified, the box will
4439
+ be a cube. Provide a tuple of floats to specify the width, length, and
4440
+ height of the box (eg. `size=(0.2, 1.3, 2.1)`).
4441
+ flipFaces : bool, optional
4442
+ If `True`, normals and face windings will be set to point inward towards
4443
+ the center of the box. Texture coordinates will remain the same.
4444
+ Default is `False`.
4445
+
4446
+ Returns
4447
+ -------
4448
+ tuple
4449
+ Vertex attribute arrays (position, texture coordinates, and normals) and
4450
+ triangle indices.
4451
+
4452
+ Examples
4453
+ --------
4454
+ Create a box mesh and draw it::
4455
+
4456
+ vertices, textureCoords, normals, faces = gltools.createBox()
4457
+
4458
+ vertexVBO = gltools.createVBO(vertices)
4459
+ texCoordVBO = gltools.createVBO(textureCoords)
4460
+ normalsVBO = gltools.createVBO(normals)
4461
+ indexBuffer = gltools.createVBO(
4462
+ faces.flatten(),
4463
+ target=GL.GL_ELEMENT_ARRAY_BUFFER,
4464
+ dataType=GL.GL_UNSIGNED_INT)
4465
+
4466
+ vao = gltools.createVAO({0: vertexVBO, 8: texCoordVBO, 2: normalsVBO},
4467
+ indexBuffer=indexBuffer)
4468
+
4469
+ # in the rendering loop
4470
+ gltools.drawVAO(vao, GL.GL_TRIANGLES)
4471
+
4472
+ """
4473
+ if isinstance(size, (int, float,)):
4474
+ sx = sy = sz = float(size) / 2.
4475
+ else:
4476
+ sx, sy, sz = size
4477
+ sx /= 2.
4478
+ sy /= 2.
4479
+ sz /= 2.
4480
+
4481
+ # vertices
4482
+ vertices = np.ascontiguousarray([
4483
+ [ 1., 1., 1.], [ 1., 1., -1.], [ 1., -1., 1.],
4484
+ [ 1., -1., -1.], [-1., 1., -1.], [-1., 1., 1.],
4485
+ [-1., -1., -1.], [-1., -1., 1.], [-1., 1., -1.],
4486
+ [ 1., 1., -1.], [-1., 1., 1.], [ 1., 1., 1.],
4487
+ [ 1., -1., -1.], [-1., -1., -1.], [ 1., -1., 1.],
4488
+ [-1., -1., 1.], [-1., 1., 1.], [ 1., 1., 1.],
4489
+ [-1., -1., 1.], [ 1., -1., 1.], [ 1., 1., -1.],
4490
+ [-1., 1., -1.], [ 1., -1., -1.], [-1., -1., -1.]
4491
+ ], dtype=np.float32)
4492
+
4493
+ # multiply vertex coordinates by box dimensions
4494
+ if sx != 1.:
4495
+ vertices[:, 0] *= sx
4496
+
4497
+ if sy != 1.:
4498
+ vertices[:, 1] *= sy
4499
+
4500
+ if sz != 1.:
4501
+ vertices[:, 2] *= sz
4502
+
4503
+ # normals for each side
4504
+ normals = np.repeat(
4505
+ [[ 1., 0., 0.], # +X
4506
+ [-1., 0., 0.], # -X
4507
+ [ 0., 1., 0.], # +Y
4508
+ [ 0., -1., 0.], # -Y
4509
+ [ 0., 0., 1.], # +Z
4510
+ [ 0., 0., -1.]], # -Z
4511
+ 4, axis=0)
4512
+
4513
+ normals = np.ascontiguousarray(normals, dtype=np.float32)
4514
+
4515
+ # texture coordinates for each side
4516
+ texCoords = np.tile([[0., 1.], [1., 1.], [0., 0.], [1., 0.]], (6, 1))
4517
+ texCoords = np.ascontiguousarray(texCoords, dtype=np.float32)
4518
+
4519
+ # vertex indices for faces
4520
+ faces = np.ascontiguousarray([
4521
+ [ 0, 2, 1], [ 1, 2, 3], # +X
4522
+ [ 4, 6, 5], [ 5, 6, 7], # -X
4523
+ [ 8, 10, 9], [ 9, 10, 11], # +Y
4524
+ [12, 14, 13], [13, 14, 15], # -Y
4525
+ [16, 18, 17], [17, 18, 19], # +Z
4526
+ [20, 22, 21], [21, 22, 23] # -Z
4527
+ ], dtype=np.uint32)
4528
+
4529
+ if flipFaces:
4530
+ faces = np.fliplr(faces)
4531
+ normals *= -1.0
4532
+
4533
+ return vertices, texCoords, normals, faces
4534
+
4535
+
4536
+ def transformMeshPosOri(vertices, normals, pos=(0., 0., 0.), ori=(0., 0., 0., 1.)):
4537
+ """Transform a mesh.
4538
+
4539
+ Transform mesh vertices and normals to a new position and orientation using
4540
+ a position coordinate and rotation quaternion. Values `vertices` and
4541
+ `normals` must be the same shape. This is intended to be used when editing
4542
+ raw vertex data prior to rendering. Do not use this to change the
4543
+ configuration of an object while rendering.
4544
+
4545
+ Parameters
4546
+ ----------
4547
+ vertices : array_like
4548
+ Nx3 array of vertices.
4549
+ normals : array_like
4550
+ Nx3 array of normals.
4551
+ pos : array_like, optional
4552
+ Position vector to transform mesh vertices. If Nx3, `vertices` will be
4553
+ transformed by corresponding rows of `pos`.
4554
+ ori : array_like, optional
4555
+ Orientation quaternion in form [x, y, z, w]. If Nx4, `vertices` and
4556
+ `normals` will be transformed by corresponding rows of `ori`.
4557
+
4558
+ Returns
4559
+ -------
4560
+ tuple
4561
+ Transformed vertices and normals.
4562
+
4563
+ Examples
4564
+ --------
4565
+ Create and re-orient a plane to face upwards::
4566
+
4567
+ vertices, textureCoords, normals, faces = createPlane()
4568
+
4569
+ # rotation quaternion
4570
+ qr = quatFromAxisAngle((1., 0., 0.), -90.0) # -90 degrees about +X axis
4571
+
4572
+ # transform the normals and points
4573
+ vertices, normals = transformMeshPosOri(vertices, normals, ori=qr)
4574
+
4575
+ Any `create*` primitive generating function can be used inplace of
4576
+ `createPlane`.
4577
+
4578
+ """
4579
+ # ensure these are contiguous
4580
+ vertices = np.ascontiguousarray(vertices)
4581
+ normals = np.ascontiguousarray(normals)
4582
+
4583
+ if not np.allclose(pos, [0., 0., 0.]):
4584
+ vertices = mt.transform(pos, ori, vertices)
4585
+
4586
+ if not np.allclose(ori, [0., 0., 0., 1.]):
4587
+ normals = mt.applyQuat(ori, normals)
4588
+
4589
+ return vertices, normals
4590
+
4591
+
4592
+ def calculateVertexNormals(vertices, faces, shading='smooth'):
4593
+ """Calculate vertex normals given vertices and triangle faces.
4594
+
4595
+ Finds all faces sharing a vertex index and sets its normal to either
4596
+ the face normal if `shading='flat'` or the average normals of adjacent
4597
+ faces if `shading='smooth'`. Flat shading only works correctly if each
4598
+ vertex belongs to exactly one face.
4599
+
4600
+ The direction of the normals are determined by the winding order of
4601
+ triangles, assumed counter clock-wise (OpenGL default). Most model
4602
+ editing software exports using this convention. If not, winding orders
4603
+ can be reversed by calling::
4604
+
4605
+ faces = np.fliplr(faces)
4606
+
4607
+ In some case, creases may appear if vertices are at the same location,
4608
+ but do not share the same index.
4609
+
4610
+ Parameters
4611
+ ----------
4612
+ vertices : array_like
4613
+ Nx3 vertex positions.
4614
+ faces : array_like
4615
+ Nx3 vertex indices.
4616
+ shading : str, optional
4617
+ Shading mode. Options are 'smooth' and 'flat'. Flat only works with
4618
+ meshes where no vertex index is shared across faces.
4619
+
4620
+ Returns
4621
+ -------
4622
+ ndarray
4623
+ Vertex normals array with the shame shape as `vertices`. Computed
4624
+ normals are normalized.
4625
+
4626
+ Examples
4627
+ --------
4628
+ Recomputing vertex normals for a UV sphere::
4629
+
4630
+ # create a sphere and discard normals
4631
+ vertices, textureCoords, _, faces = gltools.createUVSphere()
4632
+ normals = gltools.calculateVertexNormals(vertices, faces)
4633
+
4634
+ """
4635
+ # compute surface normals for all faces
4636
+ faceNormals = mt.surfaceNormal(vertices[faces])
4637
+
4638
+ normals = []
4639
+ if shading == 'flat':
4640
+ for vertexIdx in np.unique(faces):
4641
+ match, _ = np.where(faces == vertexIdx)
4642
+ normals.append(faceNormals[match, :])
4643
+ elif shading == 'smooth':
4644
+ # get all faces the vertex belongs to
4645
+ for vertexIdx in np.unique(faces):
4646
+ match, _ = np.where(faces == vertexIdx)
4647
+ normals.append(mt.vertexNormal(faceNormals[match, :]))
4648
+
4649
+ return np.ascontiguousarray(normals) + 0.0
4650
+
4651
+
4652
+ # -----------------------------
4653
+ # Misc. OpenGL Helper Functions
4654
+ # -----------------------------
4655
+
4656
+ def getIntegerv(parName):
4657
+ """Get a single integer parameter value, return it as a Python integer.
4658
+
4659
+ Parameters
4660
+ ----------
4661
+ pName : int
4662
+ OpenGL property enum to query (e.g. GL_MAJOR_VERSION).
4663
+
4664
+ Returns
4665
+ -------
4666
+ int
4667
+
4668
+ """
4669
+ val = GL.GLint()
4670
+ GL.glGetIntegerv(parName, val)
4671
+
4672
+ return int(val.value)
4673
+
4674
+
4675
+ def getFloatv(parName):
4676
+ """Get a single float parameter value, return it as a Python float.
4677
+
4678
+ Parameters
4679
+ ----------
4680
+ pName : float
4681
+ OpenGL property enum to query.
4682
+
4683
+ Returns
4684
+ -------
4685
+ float
4686
+
4687
+ """
4688
+ val = GL.GLfloat()
4689
+ GL.glGetFloatv(parName, val)
4690
+
4691
+ return float(val.value)
4692
+
4693
+
4694
+ def getString(parName):
4695
+ """Get a single string parameter value, return it as a Python UTF-8 string.
4696
+
4697
+ Parameters
4698
+ ----------
4699
+ pName : int
4700
+ OpenGL property enum to query (e.g. GL_VENDOR).
4701
+
4702
+ Returns
4703
+ -------
4704
+ str
4705
+
4706
+ """
4707
+ val = ctypes.cast(GL.glGetString(parName), ctypes.c_char_p).value
4708
+ return val.decode('UTF-8')
4709
+
4710
+
4711
+ def getModelViewMatrix():
4712
+ """Get the present model matrix from the OpenGL matrix stack.
4713
+
4714
+ Returns
4715
+ -------
4716
+ ndarray
4717
+ 4x4 model/view matrix.
4718
+
4719
+ """
4720
+ modelview = np.zeros((4, 4), dtype=np.float32)
4721
+
4722
+ GL.glGetFloatv(GL.GL_MODELVIEW_MATRIX, modelview.ctypes.data_as(
4723
+ ctypes.POINTER(ctypes.c_float)))
4724
+
4725
+ modelview[:, :] = np.transpose(modelview)
4726
+
4727
+ return modelview
4728
+
4729
+
4730
+ def getProjectionMatrix():
4731
+ """Get the present projection matrix from the OpenGL matrix stack.
4732
+
4733
+ Returns
4734
+ -------
4735
+ ndarray
4736
+ 4x4 projection matrix.
4737
+
4738
+ """
4739
+ proj = np.zeros((4, 4), dtype=np.float32, order='C')
4740
+
4741
+ GL.glGetFloatv(GL.GL_PROJECTION_MATRIX, proj.ctypes.data_as(
4742
+ ctypes.POINTER(ctypes.c_float)))
4743
+
4744
+ proj[:, :] = np.transpose(proj)
4745
+
4746
+ return proj
4747
+
4748
+
4749
+ # OpenGL information type
4750
+ OpenGLInfo = namedtuple(
4751
+ 'OpenGLInfo',
4752
+ ['vendor',
4753
+ 'renderer',
4754
+ 'version',
4755
+ 'majorVersion',
4756
+ 'minorVersion',
4757
+ 'doubleBuffer',
4758
+ 'maxTextureSize',
4759
+ 'stereo',
4760
+ 'maxSamples',
4761
+ 'extensions',
4762
+ 'userData'])
4763
+
4764
+
4765
+ def getOpenGLInfo():
4766
+ """Get general information about the OpenGL implementation on this machine.
4767
+ This should provide a consistent means of doing so regardless of the OpenGL
4768
+ interface we are using.
4769
+
4770
+ Returns are dictionary with the following fields::
4771
+
4772
+ vendor, renderer, version, majorVersion, minorVersion, doubleBuffer,
4773
+ maxTextureSize, stereo, maxSamples, extensions
4774
+
4775
+ Supported extensions are returned as a list in the 'extensions' field. You
4776
+ can check if a platform supports an extension by checking the membership of
4777
+ the extension name in that list.
4778
+
4779
+ Returns
4780
+ -------
4781
+ OpenGLInfo
4782
+
4783
+ """
4784
+ return OpenGLInfo(getString(GL.GL_VENDOR),
4785
+ getString(GL.GL_RENDERER),
4786
+ getString(GL.GL_VERSION),
4787
+ getIntegerv(GL.GL_MAJOR_VERSION),
4788
+ getIntegerv(GL.GL_MINOR_VERSION),
4789
+ getIntegerv(GL.GL_DOUBLEBUFFER),
4790
+ getIntegerv(GL.GL_MAX_TEXTURE_SIZE),
4791
+ getIntegerv(GL.GL_STEREO),
4792
+ getIntegerv(GL.GL_MAX_SAMPLES),
4793
+ [i for i in getString(GL.GL_EXTENSIONS).split(' ')],
4794
+ dict())
4795
+
4796
+
4797
+ # ---------------------
4798
+ # OpenGL/VRML Materials
4799
+ # ---------------------
4800
+ #
4801
+ # A collection of pre-defined materials for stimuli. Keep in mind that these
4802
+ # materials only approximate real-world equivalents. Values were obtained from
4803
+ # http://devernay.free.fr/cours/opengl/materials.html (08/24/18). There are four
4804
+ # material libraries to use, where individual material descriptors are accessed
4805
+ # via property names.
4806
+ #
4807
+ # Usage:
4808
+ #
4809
+ # useMaterial(metalMaterials.gold)
4810
+ # drawVAO(myObject)
4811
+ # ...
4812
+ #
4813
+ mineralMaterials = namedtuple(
4814
+ 'mineralMaterials',
4815
+ ['emerald', 'jade', 'obsidian', 'pearl', 'ruby', 'turquoise'])(
4816
+ createMaterial(
4817
+ [(GL.GL_AMBIENT, (0.0215, 0.1745, 0.0215, 1.0)),
4818
+ (GL.GL_DIFFUSE, (0.07568, 0.61424, 0.07568, 1.0)),
4819
+ (GL.GL_SPECULAR, (0.633, 0.727811, 0.633, 1.0)),
4820
+ (GL.GL_SHININESS, 0.6 * 128.0)]),
4821
+ createMaterial(
4822
+ [(GL.GL_AMBIENT, (0.135, 0.2225, 0.1575, 1.0)),
4823
+ (GL.GL_DIFFUSE, (0.54, 0.89, 0.63, 1.0)),
4824
+ (GL.GL_SPECULAR, (0.316228, 0.316228, 0.316228, 1.0)),
4825
+ (GL.GL_SHININESS, 0.1 * 128.0)]),
4826
+ createMaterial(
4827
+ [(GL.GL_AMBIENT, (0.05375, 0.05, 0.06625, 1.0)),
4828
+ (GL.GL_DIFFUSE, (0.18275, 0.17, 0.22525, 1.0)),
4829
+ (GL.GL_SPECULAR, (0.332741, 0.328634, 0.346435, 1.0)),
4830
+ (GL.GL_SHININESS, 0.3 * 128.0)]),
4831
+ createMaterial(
4832
+ [(GL.GL_AMBIENT, (0.25, 0.20725, 0.20725, 1.0)),
4833
+ (GL.GL_DIFFUSE, (1, 0.829, 0.829, 1.0)),
4834
+ (GL.GL_SPECULAR, (0.296648, 0.296648, 0.296648, 1.0)),
4835
+ (GL.GL_SHININESS, 0.088 * 128.0)]),
4836
+ createMaterial(
4837
+ [(GL.GL_AMBIENT, (0.1745, 0.01175, 0.01175, 1.0)),
4838
+ (GL.GL_DIFFUSE, (0.61424, 0.04136, 0.04136, 1.0)),
4839
+ (GL.GL_SPECULAR, (0.727811, 0.626959, 0.626959, 1.0)),
4840
+ (GL.GL_SHININESS, 0.6 * 128.0)]),
4841
+ createMaterial(
4842
+ [(GL.GL_AMBIENT, (0.1, 0.18725, 0.1745, 1.0)),
4843
+ (GL.GL_DIFFUSE, (0.396, 0.74151, 0.69102, 1.0)),
4844
+ (GL.GL_SPECULAR, (0.297254, 0.30829, 0.306678, 1.0)),
4845
+ (GL.GL_SHININESS, 0.1 * 128.0)])
4846
+ )
4847
+
4848
+ metalMaterials = namedtuple(
4849
+ 'metalMaterials',
4850
+ ['brass', 'bronze', 'chrome', 'copper', 'gold', 'silver'])(
4851
+ createMaterial(
4852
+ [(GL.GL_AMBIENT, (0.329412, 0.223529, 0.027451, 1.0)),
4853
+ (GL.GL_DIFFUSE, (0.780392, 0.568627, 0.113725, 1.0)),
4854
+ (GL.GL_SPECULAR, (0.992157, 0.941176, 0.807843, 1.0)),
4855
+ (GL.GL_SHININESS, 0.21794872 * 128.0)]),
4856
+ createMaterial(
4857
+ [(GL.GL_AMBIENT, (0.2125, 0.1275, 0.054, 1.0)),
4858
+ (GL.GL_DIFFUSE, (0.714, 0.4284, 0.18144, 1.0)),
4859
+ (GL.GL_SPECULAR, (0.393548, 0.271906, 0.166721, 1.0)),
4860
+ (GL.GL_SHININESS, 0.2 * 128.0)]),
4861
+ createMaterial(
4862
+ [(GL.GL_AMBIENT, (0.25, 0.25, 0.25, 1.0)),
4863
+ (GL.GL_DIFFUSE, (0.4, 0.4, 0.4, 1.0)),
4864
+ (GL.GL_SPECULAR, (0.774597, 0.774597, 0.774597, 1.0)),
4865
+ (GL.GL_SHININESS, 0.6 * 128.0)]),
4866
+ createMaterial(
4867
+ [(GL.GL_AMBIENT, (0.19125, 0.0735, 0.0225, 1.0)),
4868
+ (GL.GL_DIFFUSE, (0.7038, 0.27048, 0.0828, 1.0)),
4869
+ (GL.GL_SPECULAR, (0.256777, 0.137622, 0.086014, 1.0)),
4870
+ (GL.GL_SHININESS, 0.1 * 128.0)]),
4871
+ createMaterial(
4872
+ [(GL.GL_AMBIENT, (0.24725, 0.1995, 0.0745, 1.0)),
4873
+ (GL.GL_DIFFUSE, (0.75164, 0.60648, 0.22648, 1.0)),
4874
+ (GL.GL_SPECULAR, (0.628281, 0.555802, 0.366065, 1.0)),
4875
+ (GL.GL_SHININESS, 0.4 * 128.0)]),
4876
+ createMaterial(
4877
+ [(GL.GL_AMBIENT, (0.19225, 0.19225, 0.19225, 1.0)),
4878
+ (GL.GL_DIFFUSE, (0.50754, 0.50754, 0.50754, 1.0)),
4879
+ (GL.GL_SPECULAR, (0.508273, 0.508273, 0.508273, 1.0)),
4880
+ (GL.GL_SHININESS, 0.4 * 128.0)])
4881
+ )
4882
+
4883
+ plasticMaterials = namedtuple(
4884
+ 'plasticMaterials',
4885
+ ['black', 'cyan', 'green', 'red', 'white', 'yellow'])(
4886
+ createMaterial(
4887
+ [(GL.GL_AMBIENT, (0, 0, 0, 1.0)),
4888
+ (GL.GL_DIFFUSE, (0.01, 0.01, 0.01, 1.0)),
4889
+ (GL.GL_SPECULAR, (0.5, 0.5, 0.5, 1.0)),
4890
+ (GL.GL_SHININESS, 0.25 * 128.0)]),
4891
+ createMaterial(
4892
+ [(GL.GL_AMBIENT, (0, 0.1, 0.06, 1.0)),
4893
+ (GL.GL_DIFFUSE, (0.06, 0, 0.50980392, 1.0)),
4894
+ (GL.GL_SPECULAR, (0.50196078, 0.50196078, 0.50196078, 1.0)),
4895
+ (GL.GL_SHININESS, 0.25 * 128.0)]),
4896
+ createMaterial(
4897
+ [(GL.GL_AMBIENT, (0, 0, 0, 1.0)),
4898
+ (GL.GL_DIFFUSE, (0.1, 0.35, 0.1, 1.0)),
4899
+ (GL.GL_SPECULAR, (0.45, 0.55, 0.45, 1.0)),
4900
+ (GL.GL_SHININESS, 0.25 * 128.0)]),
4901
+ createMaterial(
4902
+ [(GL.GL_AMBIENT, (0, 0, 0, 1.0)),
4903
+ (GL.GL_DIFFUSE, (0.5, 0, 0, 1.0)),
4904
+ (GL.GL_SPECULAR, (0.7, 0.6, 0.6, 1.0)),
4905
+ (GL.GL_SHININESS, 0.25 * 128.0)]),
4906
+ createMaterial(
4907
+ [(GL.GL_AMBIENT, (0, 0, 0, 1.0)),
4908
+ (GL.GL_DIFFUSE, (0.55, 0.55, 0.55, 1.0)),
4909
+ (GL.GL_SPECULAR, (0.7, 0.7, 0.7, 1.0)),
4910
+ (GL.GL_SHININESS, 0.25 * 128.0)]),
4911
+ createMaterial(
4912
+ [(GL.GL_AMBIENT, (0, 0, 0, 1.0)),
4913
+ (GL.GL_DIFFUSE, (0.5, 0.5, 0, 1.0)),
4914
+ (GL.GL_SPECULAR, (0.6, 0.6, 0.5, 1.0)),
4915
+ (GL.GL_SHININESS, 0.25 * 128.0)])
4916
+ )
4917
+
4918
+ rubberMaterials = namedtuple(
4919
+ 'rubberMaterials',
4920
+ ['black', 'cyan', 'green', 'red', 'white', 'yellow'])(
4921
+ createMaterial(
4922
+ [(GL.GL_AMBIENT, (0.02, 0.02, 0.02, 1.0)),
4923
+ (GL.GL_DIFFUSE, (0.01, 0.01, 0.01, 1.0)),
4924
+ (GL.GL_SPECULAR, (0.4, 0.4, 0.4, 1.0)),
4925
+ (GL.GL_SHININESS, 0.078125 * 128.0)]),
4926
+ createMaterial(
4927
+ [(GL.GL_AMBIENT, (0, 0.05, 0.05, 1.0)),
4928
+ (GL.GL_DIFFUSE, (0.4, 0.5, 0.5, 1.0)),
4929
+ (GL.GL_SPECULAR, (0.04, 0.7, 0.7, 1.0)),
4930
+ (GL.GL_SHININESS, 0.078125 * 128.0)]),
4931
+ createMaterial(
4932
+ [(GL.GL_AMBIENT, (0, 0.05, 0, 1.0)),
4933
+ (GL.GL_DIFFUSE, (0.4, 0.5, 0.4, 1.0)),
4934
+ (GL.GL_SPECULAR, (0.04, 0.7, 0.04, 1.0)),
4935
+ (GL.GL_SHININESS, 0.078125 * 128.0)]),
4936
+ createMaterial(
4937
+ [(GL.GL_AMBIENT, (0.05, 0, 0, 1.0)),
4938
+ (GL.GL_DIFFUSE, (0.5, 0.4, 0.4, 1.0)),
4939
+ (GL.GL_SPECULAR, (0.7, 0.04, 0.04, 1.0)),
4940
+ (GL.GL_SHININESS, 0.078125 * 128.0)]),
4941
+ createMaterial(
4942
+ [(GL.GL_AMBIENT, (0.05, 0.05, 0.05, 1.0)),
4943
+ (GL.GL_DIFFUSE, (0.5, 0.5, 0.5, 1.0)),
4944
+ (GL.GL_SPECULAR, (0.7, 0.7, 0.7, 1.0)),
4945
+ (GL.GL_SHININESS, 0.078125 * 128.0)]),
4946
+ createMaterial(
4947
+ [(GL.GL_AMBIENT, (0.05, 0.05, 0, 1.0)),
4948
+ (GL.GL_DIFFUSE, (0.5, 0.5, 0.4, 1.0)),
4949
+ (GL.GL_SPECULAR, (0.7, 0.7, 0.04, 1.0)),
4950
+ (GL.GL_SHININESS, 0.078125 * 128.0)])
4951
+ )
4952
+
4953
+ # default material according to the OpenGL spec.
4954
+ defaultMaterial = createMaterial(
4955
+ [(GL.GL_AMBIENT, (0.2, 0.2, 0.2, 1.0)),
4956
+ (GL.GL_DIFFUSE, (0.8, 0.8, 0.8, 1.0)),
4957
+ (GL.GL_SPECULAR, (0.0, 0.0, 0.0, 1.0)),
4958
+ (GL.GL_EMISSION, (0.0, 0.0, 0.0, 1.0)),
4959
+ (GL.GL_SHININESS, 0)])