cuju-render 0.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.
Files changed (382) hide show
  1. cuju/render/__init__.py +759 -0
  2. cuju/render/__main__.py +1065 -0
  3. cuju/render/_export/__init__.py +3 -0
  4. cuju/render/_export/feed.py +542 -0
  5. cuju/render/_export/sizes.py +157 -0
  6. cuju/render/_export/video.py +1618 -0
  7. cuju/render/_export/video_jobs.py +408 -0
  8. cuju/render/_format/__init__.py +3 -0
  9. cuju/render/_format/annotations.py +235 -0
  10. cuju/render/_format/codec.py +307 -0
  11. cuju/render/_format/keep.py +121 -0
  12. cuju/render/_format/recording.py +860 -0
  13. cuju/render/_format/writer.py +54 -0
  14. cuju/render/_guide/__init__.py +3 -0
  15. cuju/render/_guide/doctor.py +523 -0
  16. cuju/render/_guide/help.py +62 -0
  17. cuju/render/_guide/tutorial.py +254 -0
  18. cuju/render/_http/__init__.py +3 -0
  19. cuju/render/_http/commands.py +57 -0
  20. cuju/render/_http/headers.py +103 -0
  21. cuju/render/_http/launch.py +500 -0
  22. cuju/render/_http/launchers.py +408 -0
  23. cuju/render/_http/pwa.py +128 -0
  24. cuju/render/_http/server.py +2105 -0
  25. cuju/render/_http/window.py +360 -0
  26. cuju/render/_moments/__init__.py +3 -0
  27. cuju/render/_moments/captions.py +284 -0
  28. cuju/render/_moments/events.py +1123 -0
  29. cuju/render/_moments/search.py +694 -0
  30. cuju/render/_packages/__init__.py +3 -0
  31. cuju/render/_packages/glsl.py +746 -0
  32. cuju/render/_packages/loudness.py +334 -0
  33. cuju/render/_packages/pack.py +1959 -0
  34. cuju/render/_packages/presentation.py +1376 -0
  35. cuju/render/_packages/vocabulary.py +609 -0
  36. cuju/render/_playing/__init__.py +3 -0
  37. cuju/render/_playing/achievements.py +463 -0
  38. cuju/render/_playing/bench.py +609 -0
  39. cuju/render/_playing/challenges.py +1813 -0
  40. cuju/render/_playing/demo.py +323 -0
  41. cuju/render/_playing/draw.py +211 -0
  42. cuju/render/_playing/errors.py +20 -0
  43. cuju/render/_playing/game.py +645 -0
  44. cuju/render/_playing/limits.py +339 -0
  45. cuju/render/_playing/play.py +926 -0
  46. cuju/render/_playing/policy_worker.py +250 -0
  47. cuju/render/_playing/strict.py +810 -0
  48. cuju/render/_registry/__init__.py +3 -0
  49. cuju/render/_registry/clips.py +394 -0
  50. cuju/render/_registry/joints.py +108 -0
  51. cuju/render/_registry/teams.py +2058 -0
  52. cuju/render/_store/__init__.py +3 -0
  53. cuju/render/_store/home.py +70 -0
  54. cuju/render/_store/library.py +604 -0
  55. cuju/render/_store/samples.py +163 -0
  56. cuju/render/_text/__init__.py +3 -0
  57. cuju/render/_text/languages.py +637 -0
  58. cuju/render/_text/messages.py +1396 -0
  59. cuju/render/_tournaments/__init__.py +3 -0
  60. cuju/render/_tournaments/results.py +547 -0
  61. cuju/render/_tournaments/tournament.py +2742 -0
  62. cuju/render/_tournaments/tournament_cli.py +587 -0
  63. cuju/render/_tournaments/tournament_runner.py +1975 -0
  64. cuju/render/_version.py +6 -0
  65. cuju/render/_watch/__init__.py +3 -0
  66. cuju/render/_watch/grid.py +265 -0
  67. cuju/render/_watch/live.py +664 -0
  68. cuju/render/_watch/notebook.py +79 -0
  69. cuju/render/_watch/show.py +171 -0
  70. cuju/render/samples/sample-11v11.cjr +0 -0
  71. cuju/render/samples/sample-5v5.cjr +0 -0
  72. cuju/render/samples/teams/starter/main.py +33 -0
  73. cuju/render/scenarios/benchmark_full_game_11_vs_11_easy.py +46 -0
  74. cuju/render/scenarios/benchmark_full_game_11_vs_11_hard.py +46 -0
  75. cuju/render/scenarios/benchmark_full_game_11_vs_11_medium.py +46 -0
  76. cuju/render/scenarios/benchmark_full_game_5_vs_5_easy.py +34 -0
  77. cuju/render/scenarios/benchmark_full_game_5_vs_5_hard.py +34 -0
  78. cuju/render/scenarios/benchmark_full_game_5_vs_5_medium.py +34 -0
  79. cuju/render/web/assets/adboard_polygon.webp +0 -0
  80. cuju/render/web/assets/adboard_your_ad_here.webp +0 -0
  81. cuju/render/web/assets/animations/kaykit-rig-medium-combatmelee.glb +0 -0
  82. cuju/render/web/assets/animations/kaykit-rig-medium-general.glb +0 -0
  83. cuju/render/web/assets/animations/kaykit-rig-medium-movementadvanced.glb +0 -0
  84. cuju/render/web/assets/animations/kaykit-rig-medium-movementbasic.glb +0 -0
  85. cuju/render/web/assets/animations/kaykit-rig-medium-simulation.glb +0 -0
  86. cuju/render/web/assets/animations/kaykit-rig-medium-special.glb +0 -0
  87. cuju/render/web/assets/ball.glb +0 -0
  88. cuju/render/web/assets/challenges/3_vs_1_with_keeper.mp4 +0 -0
  89. cuju/render/web/assets/challenges/3_vs_1_with_keeper.webp +0 -0
  90. cuju/render/web/assets/challenges/corner.mp4 +0 -0
  91. cuju/render/web/assets/challenges/corner.webp +0 -0
  92. cuju/render/web/assets/challenges/counterattack_easy.mp4 +0 -0
  93. cuju/render/web/assets/challenges/counterattack_easy.webp +0 -0
  94. cuju/render/web/assets/challenges/counterattack_hard.mp4 +0 -0
  95. cuju/render/web/assets/challenges/counterattack_hard.webp +0 -0
  96. cuju/render/web/assets/challenges/empty_goal.mp4 +0 -0
  97. cuju/render/web/assets/challenges/empty_goal.webp +0 -0
  98. cuju/render/web/assets/challenges/empty_goal_close.mp4 +0 -0
  99. cuju/render/web/assets/challenges/empty_goal_close.webp +0 -0
  100. cuju/render/web/assets/challenges/manifest.json +375 -0
  101. cuju/render/web/assets/challenges/one_on_one.mp4 +0 -0
  102. cuju/render/web/assets/challenges/one_on_one.webp +0 -0
  103. cuju/render/web/assets/challenges/one_on_one_hard.mp4 +0 -0
  104. cuju/render/web/assets/challenges/one_on_one_hard.webp +0 -0
  105. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.mp4 +0 -0
  106. cuju/render/web/assets/challenges/pass_and_shoot_with_keeper.webp +0 -0
  107. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.mp4 +0 -0
  108. cuju/render/web/assets/challenges/run_pass_and_shoot_with_keeper.webp +0 -0
  109. cuju/render/web/assets/challenges/run_to_score.mp4 +0 -0
  110. cuju/render/web/assets/challenges/run_to_score.webp +0 -0
  111. cuju/render/web/assets/challenges/run_to_score_with_keeper.mp4 +0 -0
  112. cuju/render/web/assets/challenges/run_to_score_with_keeper.webp +0 -0
  113. cuju/render/web/assets/challenges/single_goal_versus_lazy.mp4 +0 -0
  114. cuju/render/web/assets/challenges/single_goal_versus_lazy.webp +0 -0
  115. cuju/render/web/assets/crowd.webp +0 -0
  116. cuju/render/web/assets/crowd_normal.webp +0 -0
  117. cuju/render/web/assets/cuju-logo-384.png +0 -0
  118. cuju/render/web/assets/cuju-logo.png +0 -0
  119. cuju/render/web/assets/cuju-logo.svg +46 -0
  120. cuju/render/web/assets/cuju-mark-light.svg +33 -0
  121. cuju/render/web/assets/cuju-mark.svg +33 -0
  122. cuju/render/web/assets/goal.glb +0 -0
  123. cuju/render/web/assets/grass.webp +0 -0
  124. cuju/render/web/assets/hair_black.png +0 -0
  125. cuju/render/web/assets/hair_blonde.png +0 -0
  126. cuju/render/web/assets/hair_brown.png +0 -0
  127. cuju/render/web/assets/hair_darkblonde.png +0 -0
  128. cuju/render/web/assets/hair_long01.glb +0 -0
  129. cuju/render/web/assets/hair_long02.glb +0 -0
  130. cuju/render/web/assets/hair_medium01.glb +0 -0
  131. cuju/render/web/assets/hair_red.png +0 -0
  132. cuju/render/web/assets/hair_short01.glb +0 -0
  133. cuju/render/web/assets/hair_short02.glb +0 -0
  134. cuju/render/web/assets/icons/cuju-192.png +0 -0
  135. cuju/render/web/assets/icons/cuju-512.png +0 -0
  136. cuju/render/web/assets/icons/cuju-maskable-512.png +0 -0
  137. cuju/render/web/assets/kit_goalkeeper.webp +0 -0
  138. cuju/render/web/assets/kit_mask.png +0 -0
  139. cuju/render/web/assets/kit_normal.webp +0 -0
  140. cuju/render/web/assets/manifest.json +601 -0
  141. cuju/render/web/assets/models/kaykit-barbarian.glb +0 -0
  142. cuju/render/web/assets/models/kaykit-barbarian.json +23 -0
  143. cuju/render/web/assets/models/kaykit-knight.glb +0 -0
  144. cuju/render/web/assets/models/kaykit-knight.json +23 -0
  145. cuju/render/web/assets/models/kaykit-mage.glb +0 -0
  146. cuju/render/web/assets/models/kaykit-mage.json +23 -0
  147. cuju/render/web/assets/models/kaykit-mannequin-medium.glb +0 -0
  148. cuju/render/web/assets/models/kaykit-mannequin-medium.json +23 -0
  149. cuju/render/web/assets/models/kaykit-ranger.glb +0 -0
  150. cuju/render/web/assets/models/kaykit-ranger.json +23 -0
  151. cuju/render/web/assets/models/kaykit-rogue-hooded.glb +0 -0
  152. cuju/render/web/assets/models/kaykit-rogue-hooded.json +23 -0
  153. cuju/render/web/assets/models/kaykit-rogue.glb +0 -0
  154. cuju/render/web/assets/models/kaykit-rogue.json +23 -0
  155. cuju/render/web/assets/models/kaykit-skeleton-mage.glb +0 -0
  156. cuju/render/web/assets/models/kaykit-skeleton-mage.json +23 -0
  157. cuju/render/web/assets/models/kaykit-skeleton-minion.glb +0 -0
  158. cuju/render/web/assets/models/kaykit-skeleton-minion.json +23 -0
  159. cuju/render/web/assets/models/kaykit-skeleton-rogue.glb +0 -0
  160. cuju/render/web/assets/models/kaykit-skeleton-rogue.json +23 -0
  161. cuju/render/web/assets/models/kaykit-skeleton-warrior.glb +0 -0
  162. cuju/render/web/assets/models/kaykit-skeleton-warrior.json +23 -0
  163. cuju/render/web/assets/pitch.webp +0 -0
  164. cuju/render/web/assets/pitch_normal.webp +0 -0
  165. cuju/render/web/assets/player.glb +0 -0
  166. cuju/render/web/assets/shoe.webp +0 -0
  167. cuju/render/web/assets/shoe_sole.png +0 -0
  168. cuju/render/web/assets/skin_01.png +0 -0
  169. cuju/render/web/assets/skin_02.png +0 -0
  170. cuju/render/web/assets/skin_03.png +0 -0
  171. cuju/render/web/assets/skin_04.png +0 -0
  172. cuju/render/web/assets/sounds/applause.ogg +0 -0
  173. cuju/render/web/assets/sounds/beach-wave-1.ogg +0 -0
  174. cuju/render/web/assets/sounds/beach-wave-2.ogg +0 -0
  175. cuju/render/web/assets/sounds/beach-wave-3.ogg +0 -0
  176. cuju/render/web/assets/sounds/beach-wave-4.ogg +0 -0
  177. cuju/render/web/assets/sounds/city-horn.ogg +0 -0
  178. cuju/render/web/assets/sounds/city-loop.ogg +0 -0
  179. cuju/render/web/assets/sounds/city-siren.ogg +0 -0
  180. cuju/render/web/assets/sounds/crowd-cheer.ogg +0 -0
  181. cuju/render/web/assets/sounds/crowd-loop.ogg +0 -0
  182. cuju/render/web/assets/sounds/crowd-ooh.ogg +0 -0
  183. cuju/render/web/assets/sounds/gulls.ogg +0 -0
  184. cuju/render/web/assets/sounds/neon-sting.ogg +0 -0
  185. cuju/render/web/assets/sounds/rain-loop.ogg +0 -0
  186. cuju/render/web/assets/sounds/sounds.json +46 -0
  187. cuju/render/web/assets/sounds/space-beep.ogg +0 -0
  188. cuju/render/web/assets/sounds/space-hum.ogg +0 -0
  189. cuju/render/web/assets/sounds/space-radio.ogg +0 -0
  190. cuju/render/web/assets/sounds/whistle-long.ogg +0 -0
  191. cuju/render/web/assets/sounds/whistle-short.ogg +0 -0
  192. cuju/render/web/assets/sounds/wind-loop.ogg +0 -0
  193. cuju/render/web/easy.css +357 -0
  194. cuju/render/web/export.html +23 -0
  195. cuju/render/web/feed.css +262 -0
  196. cuju/render/web/feed.html +28 -0
  197. cuju/render/web/flat.css +120 -0
  198. cuju/render/web/home.css +837 -0
  199. cuju/render/web/index.html +373 -0
  200. cuju/render/web/js/boot.js +50 -0
  201. cuju/render/web/js/broadcast/audio.js +2141 -0
  202. cuju/render/web/js/broadcast/celebrate.js +1238 -0
  203. cuju/render/web/js/broadcast/decisions.js +609 -0
  204. cuju/render/web/js/broadcast/hud.js +352 -0
  205. cuju/render/web/js/broadcast/show.js +3614 -0
  206. cuju/render/web/js/broadcast/transition.js +2231 -0
  207. cuju/render/web/js/broadcast/voices.js +153 -0
  208. cuju/render/web/js/capture.js +101 -0
  209. cuju/render/web/js/core/accessibility.js +90 -0
  210. cuju/render/web/js/core/api.js +429 -0
  211. cuju/render/web/js/core/comfort.js +135 -0
  212. cuju/render/web/js/core/i18n.js +705 -0
  213. cuju/render/web/js/core/icons.js +167 -0
  214. cuju/render/web/js/core/input-settings.js +156 -0
  215. cuju/render/web/js/core/keys.js +277 -0
  216. cuju/render/web/js/core/language-ui.js +125 -0
  217. cuju/render/web/js/core/menu.js +853 -0
  218. cuju/render/web/js/core/names.js +113 -0
  219. cuju/render/web/js/core/page-structure.js +110 -0
  220. cuju/render/web/js/core/scenarios.js +109 -0
  221. cuju/render/web/js/core/spoilers.js +236 -0
  222. cuju/render/web/js/core/typeahead.js +38 -0
  223. cuju/render/web/js/export/dom-picture.js +330 -0
  224. cuju/render/web/js/export/export-host.js +97 -0
  225. cuju/render/web/js/export/feed-dialog.js +191 -0
  226. cuju/render/web/js/export/feed-params.js +266 -0
  227. cuju/render/web/js/export/feed.js +363 -0
  228. cuju/render/web/js/export/mp4-mux.js +295 -0
  229. cuju/render/web/js/export/photo-core.js +313 -0
  230. cuju/render/web/js/export/photo.js +1314 -0
  231. cuju/render/web/js/export/safe-frame.js +59 -0
  232. cuju/render/web/js/export/size-fields.js +103 -0
  233. cuju/render/web/js/export/sizes.js +178 -0
  234. cuju/render/web/js/export/video-boot.js +55 -0
  235. cuju/render/web/js/export/video-browser.js +325 -0
  236. cuju/render/web/js/export/video-export.js +417 -0
  237. cuju/render/web/js/export/video-plan.js +207 -0
  238. cuju/render/web/js/export/video-range.js +185 -0
  239. cuju/render/web/js/export/webm-mux.js +198 -0
  240. cuju/render/web/js/feed-boot.js +151 -0
  241. cuju/render/web/js/feed-frame.js +101 -0
  242. cuju/render/web/js/help/doctor.js +488 -0
  243. cuju/render/web/js/help/firstrun.js +379 -0
  244. cuju/render/web/js/help/help-center.js +438 -0
  245. cuju/render/web/js/help/install-offer.js +164 -0
  246. cuju/render/web/js/help/install-state.js +104 -0
  247. cuju/render/web/js/help/lessons-core.js +207 -0
  248. cuju/render/web/js/help/lessons.js +463 -0
  249. cuju/render/web/js/help/palette.js +584 -0
  250. cuju/render/web/js/help/pwa.js +257 -0
  251. cuju/render/web/js/help/tour-core.js +241 -0
  252. cuju/render/web/js/help/tour.js +461 -0
  253. cuju/render/web/js/main.js +2513 -0
  254. cuju/render/web/js/pages/draw.js +188 -0
  255. cuju/render/web/js/pages/fieldpage.js +530 -0
  256. cuju/render/web/js/pages/home.js +521 -0
  257. cuju/render/web/js/pages/matches.js +779 -0
  258. cuju/render/web/js/pages/moments-ui.js +359 -0
  259. cuju/render/web/js/pages/queue-filters.js +63 -0
  260. cuju/render/web/js/pages/recording-groups.js +80 -0
  261. cuju/render/web/js/pages/recordings.js +1069 -0
  262. cuju/render/web/js/play/bench.js +347 -0
  263. cuju/render/web/js/play/challenges.js +1302 -0
  264. cuju/render/web/js/play/medals.js +127 -0
  265. cuju/render/web/js/play/play.js +1953 -0
  266. cuju/render/web/js/play/teasers.js +196 -0
  267. cuju/render/web/js/play/touch.js +350 -0
  268. cuju/render/web/js/play/tournament-layout.js +487 -0
  269. cuju/render/web/js/play/tournament-results.js +441 -0
  270. cuju/render/web/js/play/tournament-strict.js +560 -0
  271. cuju/render/web/js/play/tournament.js +2585 -0
  272. cuju/render/web/js/players/animate.js +972 -0
  273. cuju/render/web/js/players/clips.js +224 -0
  274. cuju/render/web/js/players/kaykit.js +162 -0
  275. cuju/render/web/js/players/kits.js +676 -0
  276. cuju/render/web/js/players/number-patch.js +82 -0
  277. cuju/render/web/js/players/players.js +2694 -0
  278. cuju/render/web/js/players/recolor.js +893 -0
  279. cuju/render/web/js/players/retarget.js +325 -0
  280. cuju/render/web/js/players/rig-numbers.js +174 -0
  281. cuju/render/web/js/presentation/animator.js +231 -0
  282. cuju/render/web/js/presentation/assign.js +85 -0
  283. cuju/render/web/js/presentation/behaviors.js +440 -0
  284. cuju/render/web/js/presentation/budget.js +209 -0
  285. cuju/render/web/js/presentation/catalog.js +1674 -0
  286. cuju/render/web/js/presentation/clocks.js +72 -0
  287. cuju/render/web/js/presentation/commands.js +301 -0
  288. cuju/render/web/js/presentation/contract.js +240 -0
  289. cuju/render/web/js/presentation/effects.js +904 -0
  290. cuju/render/web/js/presentation/flash.js +605 -0
  291. cuju/render/web/js/presentation/freeze-worklet.js +22 -0
  292. cuju/render/web/js/presentation/glsl.js +464 -0
  293. cuju/render/web/js/presentation/host.js +323 -0
  294. cuju/render/web/js/presentation/index.js +2066 -0
  295. cuju/render/web/js/presentation/loudness-worklet.js +235 -0
  296. cuju/render/web/js/presentation/loudness.js +740 -0
  297. cuju/render/web/js/presentation/moments.js +536 -0
  298. cuju/render/web/js/presentation/post.js +327 -0
  299. cuju/render/web/js/presentation/preview.js +180 -0
  300. cuju/render/web/js/presentation/protocol.js +174 -0
  301. cuju/render/web/js/presentation/reach.js +158 -0
  302. cuju/render/web/js/presentation/rigging.js +130 -0
  303. cuju/render/web/js/presentation/sandbox.js +157 -0
  304. cuju/render/web/js/presentation/shaders.js +235 -0
  305. cuju/render/web/js/presentation/stage.js +402 -0
  306. cuju/render/web/js/presentation/teamaudio.js +722 -0
  307. cuju/render/web/js/presentation/tracks.js +197 -0
  308. cuju/render/web/js/presentation/values.js +81 -0
  309. cuju/render/web/js/recording/annotation-data.js +203 -0
  310. cuju/render/web/js/recording/captions.js +491 -0
  311. cuju/render/web/js/recording/codec.js +185 -0
  312. cuju/render/web/js/recording/decode-worker.js +70 -0
  313. cuju/render/web/js/recording/decode.js +94 -0
  314. cuju/render/web/js/recording/episodes.js +46 -0
  315. cuju/render/web/js/recording/format.js +461 -0
  316. cuju/render/web/js/recording/live.js +348 -0
  317. cuju/render/web/js/recording/moments-query.js +59 -0
  318. cuju/render/web/js/recording/moments.js +149 -0
  319. cuju/render/web/js/recording/pose.js +86 -0
  320. cuju/render/web/js/recording/timeline.js +275 -0
  321. cuju/render/web/js/teams/art.js +50 -0
  322. cuju/render/web/js/teams/clip-editor.js +293 -0
  323. cuju/render/web/js/teams/editor.js +1979 -0
  324. cuju/render/web/js/teams/library.js +344 -0
  325. cuju/render/web/js/teams/painter.js +633 -0
  326. cuju/render/web/js/teams/surprise-ui.js +195 -0
  327. cuju/render/web/js/teams/surprise.js +497 -0
  328. cuju/render/web/js/teams/team-check.js +127 -0
  329. cuju/render/web/js/watch/annotations.js +270 -0
  330. cuju/render/web/js/watch/flat.js +366 -0
  331. cuju/render/web/js/watch/grid.js +436 -0
  332. cuju/render/web/js/watch/pitch2d.js +289 -0
  333. cuju/render/web/js/watch/player-tools.js +192 -0
  334. cuju/render/web/js/watch/presets.js +201 -0
  335. cuju/render/web/js/world/arenas.js +997 -0
  336. cuju/render/web/js/world/ball.js +204 -0
  337. cuju/render/web/js/world/cameras.js +982 -0
  338. cuju/render/web/js/world/crowd.js +376 -0
  339. cuju/render/web/js/world/field.js +227 -0
  340. cuju/render/web/js/world/framing.js +145 -0
  341. cuju/render/web/js/world/occlusion.js +48 -0
  342. cuju/render/web/js/world/pitch.js +703 -0
  343. cuju/render/web/js/world/scene.js +395 -0
  344. cuju/render/web/js/world/sky.js +325 -0
  345. cuju/render/web/js/world/stadium.js +1262 -0
  346. cuju/render/web/js/world/vendor-sky.js +367 -0
  347. cuju/render/web/js/world/weather.js +264 -0
  348. cuju/render/web/languages/en.json +4750 -0
  349. cuju/render/web/lessons.json +137 -0
  350. cuju/render/web/manifest.webmanifest +23 -0
  351. cuju/render/web/style.css +8399 -0
  352. cuju/render/web/sw.js +235 -0
  353. cuju/render/web/vendor/fabric/LICENSE +16 -0
  354. cuju/render/web/vendor/fabric/fabric.min.mjs +1 -0
  355. cuju/render/web/vendor/lucide/LICENSE +43 -0
  356. cuju/render/web/vendor/lucide/icons.js +141 -0
  357. cuju/render/web/vendor/three/LICENSE +21 -0
  358. cuju/render/web/vendor/three/build/three.core.js +60586 -0
  359. cuju/render/web/vendor/three/build/three.module.js +19719 -0
  360. cuju/render/web/vendor/three/examples/jsm/loaders/GLTFLoader.js +4925 -0
  361. cuju/render/web/vendor/three/examples/jsm/postprocessing/EffectComposer.js +365 -0
  362. cuju/render/web/vendor/three/examples/jsm/postprocessing/MaskPass.js +195 -0
  363. cuju/render/web/vendor/three/examples/jsm/postprocessing/OutputPass.js +148 -0
  364. cuju/render/web/vendor/three/examples/jsm/postprocessing/Pass.js +191 -0
  365. cuju/render/web/vendor/three/examples/jsm/postprocessing/RenderPass.js +193 -0
  366. cuju/render/web/vendor/three/examples/jsm/postprocessing/ShaderPass.js +135 -0
  367. cuju/render/web/vendor/three/examples/jsm/postprocessing/UnrealBloomPass.js +541 -0
  368. cuju/render/web/vendor/three/examples/jsm/shaders/CopyShader.js +52 -0
  369. cuju/render/web/vendor/three/examples/jsm/shaders/LuminosityHighPassShader.js +68 -0
  370. cuju/render/web/vendor/three/examples/jsm/shaders/OutputShader.js +103 -0
  371. cuju/render/web/vendor/three/examples/jsm/utils/BufferGeometryUtils.js +1501 -0
  372. cuju/render/web/vendor/three/examples/jsm/utils/SkeletonUtils.js +496 -0
  373. cuju_render-0.1.0.dist-info/METADATA +116 -0
  374. cuju_render-0.1.0.dist-info/RECORD +382 -0
  375. cuju_render-0.1.0.dist-info/WHEEL +4 -0
  376. cuju_render-0.1.0.dist-info/licenses/LICENSE +202 -0
  377. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC-BY-4.0.txt +396 -0
  378. cuju_render-0.1.0.dist-info/licenses/LICENSES/CC0-1.0.txt +127 -0
  379. cuju_render-0.1.0.dist-info/licenses/LICENSES/ISC.txt +16 -0
  380. cuju_render-0.1.0.dist-info/licenses/LICENSES/MIT.txt +24 -0
  381. cuju_render-0.1.0.dist-info/licenses/LICENSES/Unlicense.txt +13 -0
  382. cuju_render-0.1.0.dist-info/licenses/NOTICE +35 -0
@@ -0,0 +1,59 @@
1
+ // Copyright 2026 The cuju Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // The safe area of a picture of fixed size, for the clean feed and the video export. The page
5
+ // marks the app as framed, with the margins of sizes.js as CSS variables and the shape of the
6
+ // picture as a class, so feed.css keeps the score, the banners and the captions inside the safe
7
+ // area at every size and shape. The margins follow the size of the view as it changes.
8
+
9
+ import { parseSafe, safeArea, shapeOf } from './sizes.js';
10
+
11
+ export const SHAPES = ['wide', 'square', 'tall'];
12
+
13
+ // Applies the safe area of mode to the app element and returns the margins in CSS pixels.
14
+ export function applySafeArea(app, mode, width, height) {
15
+ const margins = safeArea(width, height, mode);
16
+ for (const side of ['top', 'right', 'bottom', 'left']) {
17
+ app.style.setProperty(`--safe-${side}`, `${margins[side]}px`);
18
+ }
19
+ const shape = shapeOf(width, height);
20
+ app.classList.add('framed');
21
+ for (const s of SHAPES) {
22
+ app.classList.toggle(`shape-${s}`, s === shape);
23
+ }
24
+ app.dataset.safe = String(mode);
25
+ return { ...margins, shape };
26
+ }
27
+
28
+ // Keeps the safe area of the app element in step with its size, and returns an object whose
29
+ // margins field holds the latest margins and whose stop ends the watch.
30
+ export function watchSafeArea(app, mode) {
31
+ const state = { margins: null, mode };
32
+ const update = () => {
33
+ const width = app.clientWidth || window.innerWidth;
34
+ const height = app.clientHeight || window.innerHeight;
35
+ state.margins = applySafeArea(app, state.mode, width, height);
36
+ state.width = width;
37
+ state.height = height;
38
+ };
39
+ update();
40
+ const observer = typeof ResizeObserver === 'function' ? new ResizeObserver(update) : null;
41
+ if (observer) {
42
+ observer.observe(app);
43
+ } else {
44
+ window.addEventListener('resize', update);
45
+ }
46
+ state.update = update;
47
+ state.stop = () => (observer ? observer.disconnect() : window.removeEventListener('resize', update));
48
+ return state;
49
+ }
50
+
51
+ // The safe area that the query of an address names, as the video export gives it, auto when it
52
+ // names none or one out of place.
53
+ export function safeMode(search) {
54
+ try {
55
+ return parseSafe(new URLSearchParams(search).get('safe'));
56
+ } catch {
57
+ return 'auto';
58
+ }
59
+ }
@@ -0,0 +1,103 @@
1
+ // Copyright 2026 The cuju Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // The fields of a picture size, shared by the Export video dialog and the Copy feed address
5
+ // dialog of the Watch page. A list holds the presets of sizes.js and Custom size, which shows a
6
+ // width and a height, and two lists set the scale and the safe area of the graphics.
7
+
8
+ import { t } from '../core/i18n.js';
9
+ import { h } from '../teams/library.js';
10
+ import { MAX_AREA, MAX_SIDE, MIN_SIDE, SIZE_PRESETS, checkSize, parseSafe } from './sizes.js';
11
+
12
+ // The scales of the graphics that the lists offer, the default first.
13
+ export const GRAPHICS_CHOICES = Object.freeze([
14
+ { id: '1', label: t('size-fields.graphics.1') },
15
+ { id: '0.75', label: t('size-fields.graphics.0_75') },
16
+ { id: '1.25', label: t('size-fields.graphics.1_25') },
17
+ { id: '1.5', label: t('size-fields.graphics.1_5') },
18
+ ]);
19
+ export const SAFE_CHOICES = Object.freeze([
20
+ { id: 'auto', label: t('size-fields.safe.auto') },
21
+ { id: 'social', label: t('size-fields.safe.social') },
22
+ { id: 'none', label: t('size-fields.safe.none') },
23
+ ]);
24
+
25
+ // The name of a preset in the language of the page. sizes.js keeps its English labels, the
26
+ // server and the tests read it alone.
27
+ export function presetLabel(preset) {
28
+ return t(`size-fields.preset.${preset.id}`);
29
+ }
30
+
31
+ // Checks a size as checkSize does, with its refusal in the language of the page.
32
+ function checkShown(width, height, limits) {
33
+ try {
34
+ return checkSize(width, height, limits);
35
+ } catch (err) {
36
+ const { min = MIN_SIDE, max = MAX_SIDE, area = MAX_AREA, even = false } = limits;
37
+ for (const [name, value] of [['width', width], ['height', height]]) {
38
+ if (!Number.isInteger(value) || value < min || value > max) {
39
+ throw new RangeError(t(`size-fields.error.${name}.range`, { min, max, value }));
40
+ }
41
+ if (even && value % 2) {
42
+ throw new RangeError(t(`size-fields.error.${name}.even`, { value }));
43
+ }
44
+ }
45
+ if (width * height > area) {
46
+ throw new RangeError(t('size-fields.error.area', { area, width, height }));
47
+ }
48
+ throw err;
49
+ }
50
+ }
51
+
52
+ // Builds the fields with the given prefix of their identifiers and returns them with read, which
53
+ // returns the chosen width, height, scale and safe area, or throws a RangeError for a custom size
54
+ // out of range. Options are the size chosen first, limits for checkSize and whether to offer the
55
+ // scale and the safe area.
56
+ export function sizeFields(prefix, { value = '720p', limits = {}, graphics = true, safe = true } = {}) {
57
+ const choice = h('select', { id: `${prefix}-size` },
58
+ SIZE_PRESETS.map((p) => h('option', { value: p.id, selected: p.id === value }, presetLabel(p))),
59
+ h('option', { value: 'custom' }, t('size-fields.custom')));
60
+ const side = (name, initial) => h('input', {
61
+ id: `${prefix}-${name}`, type: 'number', min: String(limits.min || 90), max: String(limits.max || 3840),
62
+ step: limits.even ? '2' : '1', value: String(initial), 'aria-label': t(`size-fields.${name === 'width' ? 'width' : 'height'}`),
63
+ });
64
+ const width = side('width', 1280);
65
+ const height = side('height', 720);
66
+ const custom = h('span', { class: 'size-custom', hidden: true }, width, h('span', { 'aria-hidden': 'true' }, t('size-fields.by')), height);
67
+ const list = (id, entries) => h('select', { id: `${prefix}-${id}` }, entries.map((e) => h('option', { value: e.id }, e.label)));
68
+ const scale = graphics ? list('scale', GRAPHICS_CHOICES) : null;
69
+ const area = safe ? list('safe', SAFE_CHOICES) : null;
70
+ choice.addEventListener('change', () => {
71
+ custom.hidden = choice.value !== 'custom';
72
+ const preset = SIZE_PRESETS.find((p) => p.id === choice.value);
73
+ if (preset) {
74
+ width.value = String(preset.width);
75
+ height.value = String(preset.height);
76
+ }
77
+ });
78
+ const field = (label, ...controls) => h('label', { class: 've-field' }, h('span', {}, label), ...controls);
79
+ const fields = [field(t('size-fields.size'), choice, custom)];
80
+ if (scale) {
81
+ fields.push(field(t('size-fields.graphics'), scale));
82
+ }
83
+ if (area) {
84
+ fields.push(field(t('size-fields.safe'), area));
85
+ }
86
+ const read = () => {
87
+ let size;
88
+ if (choice.value === 'custom') {
89
+ size = checkShown(Number(width.value), Number(height.value), limits);
90
+ } else {
91
+ const preset = SIZE_PRESETS.find((p) => p.id === choice.value);
92
+ size = checkShown(preset.width, preset.height, limits);
93
+ }
94
+ return {
95
+ id: choice.value,
96
+ width: size.width,
97
+ height: size.height,
98
+ scale: scale ? Number(scale.value) : 1,
99
+ safe: area ? parseSafe(area.value) : 'auto',
100
+ };
101
+ };
102
+ return { fields, read, choice, width, height, scale, area };
103
+ }
@@ -0,0 +1,178 @@
1
+ // Copyright 2026 The cuju Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // The picture sizes of the page, shared by the clean feed, the Export video dialog and photo
5
+ // mode, with the layout that keeps the graphics in proportion at every size and the safe areas
6
+ // that keep the score, the banners and the captions inside the picture at every shape. The module
7
+ // src/cuju/render/_export/sizes.py holds the same presets and rules for the server and the command
8
+ // line, and a test keeps the two equal.
9
+
10
+ // The named sizes, each with an identifier that the feed's address and the commands accept.
11
+ export const SIZE_PRESETS = Object.freeze([
12
+ Object.freeze({ id: '480p', width: 854, height: 480, label: '480p, 854 by 480' }),
13
+ Object.freeze({ id: '720p', width: 1280, height: 720, label: '720p, 1280 by 720' }),
14
+ Object.freeze({ id: '1080p', width: 1920, height: 1080, label: '1080p, 1920 by 1080' }),
15
+ Object.freeze({ id: '1440p', width: 2560, height: 1440, label: '1440p, 2560 by 1440' }),
16
+ Object.freeze({ id: '4k', width: 3840, height: 2160, label: '4K, 3840 by 2160' }),
17
+ Object.freeze({ id: 'square', width: 1080, height: 1080, label: 'Square, 1080 by 1080' }),
18
+ Object.freeze({ id: 'portrait', width: 1080, height: 1350, label: 'Portrait, 1080 by 1350' }),
19
+ Object.freeze({ id: 'vertical', width: 1080, height: 1920, label: 'Vertical, 1080 by 1920' }),
20
+ ]);
21
+
22
+ // Other names of sizes, each naming a preset or a size of its own.
23
+ export const SIZE_ALIASES = Object.freeze({
24
+ '360p': '640x360',
25
+ '2160p': '4k',
26
+ uhd: '4k',
27
+ hd: '720p',
28
+ fhd: '1080p',
29
+ tall: 'vertical',
30
+ });
31
+
32
+ // The size that a feed takes when its address names none.
33
+ export const DEFAULT_SIZE = '1080p';
34
+
35
+ // The smallest and largest side of a picture, and its largest area, that of 4K.
36
+ export const MIN_SIDE = 90;
37
+ export const MAX_SIDE = 3840;
38
+ export const MAX_AREA = 3840 * 2160;
39
+
40
+ // The page lays out with its shorter side at this many CSS pixels, so the graphics keep their
41
+ // proportion at every size, and a smaller picture lays out at its own size.
42
+ export const LAYOUT_SHORT = 720;
43
+
44
+ // The scale of the graphics, which makes them larger or smaller than the layout gives them.
45
+ export const MIN_GRAPHICS = 0.5;
46
+ export const MAX_GRAPHICS = 2;
47
+
48
+ // The safe areas. Auto keeps a margin of a twentieth of the picture on every side, and a tall
49
+ // picture keeps more at its top and bottom. Social keeps clear of the buttons and captions that
50
+ // apps of short videos lay over a tall picture. A number is a percentage of each side.
51
+ export const SAFE_MODES = Object.freeze(['auto', 'none', 'social']);
52
+ export const MAX_SAFE_PERCENT = 25;
53
+
54
+ const SIZE_TEXT = /^(\d{1,5})\s*[x×]\s*(\d{1,5})$/i;
55
+
56
+ // Returns the preset of a width and height, or null.
57
+ export function presetOf(width, height) {
58
+ return SIZE_PRESETS.find((p) => p.width === width && p.height === height) || null;
59
+ }
60
+
61
+ // Returns the name of a size, the preset's identifier or the width and height as 1280x720.
62
+ export function sizeName(width, height) {
63
+ const preset = presetOf(width, height);
64
+ return preset ? preset.id : `${width}x${height}`;
65
+ }
66
+
67
+ // Checks a width and height, whole numbers within the sides and the area, and even when asked.
68
+ // Throws a RangeError that says what fits.
69
+ export function checkSize(width, height, { min = MIN_SIDE, max = MAX_SIDE, area = MAX_AREA, even = false } = {}) {
70
+ for (const [name, value] of [['width', width], ['height', height]]) {
71
+ if (!Number.isInteger(value) || value < min || value > max) {
72
+ throw new RangeError(`The ${name} is a whole number from ${min} to ${max}, not ${value}.`);
73
+ }
74
+ if (even && value % 2) {
75
+ throw new RangeError(`The ${name} is an even number for the video encoder, not ${value}.`);
76
+ }
77
+ }
78
+ if (width * height > area) {
79
+ throw new RangeError(`A picture holds at most ${area} pixels, as 3840 by 2160 does, not ${width} by ${height}.`);
80
+ }
81
+ return { width, height };
82
+ }
83
+
84
+ // Returns the width and height that a size names, a preset such as 1080p, an alias such as
85
+ // 2160p, or a width and height such as 1280x720. Throws a RangeError for anything else.
86
+ export function parseSize(text, limits = {}) {
87
+ let value = String(text ?? '').trim().toLowerCase();
88
+ value = SIZE_ALIASES[value] || value;
89
+ const preset = SIZE_PRESETS.find((p) => p.id === value);
90
+ if (preset) {
91
+ return checkSize(preset.width, preset.height, limits);
92
+ }
93
+ const m = value.match(SIZE_TEXT);
94
+ if (!m) {
95
+ throw new RangeError(`A size is a width and height such as 1280x720, or one of ${SIZE_PRESETS.map((p) => p.id).join(', ')}, not ${JSON.stringify(String(text ?? ''))}.`);
96
+ }
97
+ return checkSize(Number(m[1]), Number(m[2]), limits);
98
+ }
99
+
100
+ // Returns the scale of the graphics that a text names, from MIN_GRAPHICS to MAX_GRAPHICS.
101
+ export function parseGraphicsScale(text) {
102
+ if (text == null || text === '') {
103
+ return 1;
104
+ }
105
+ const value = Number(text);
106
+ if (!Number.isFinite(value) || value < MIN_GRAPHICS || value > MAX_GRAPHICS) {
107
+ throw new RangeError(`The scale of the graphics is a number from ${MIN_GRAPHICS} to ${MAX_GRAPHICS}, not ${JSON.stringify(String(text))}.`);
108
+ }
109
+ return value;
110
+ }
111
+
112
+ // Returns the size in CSS pixels that the page lays out at for a picture, and the scale from
113
+ // those pixels to the picture's own. The shorter side lays out at LAYOUT_SHORT, or at its own
114
+ // size when it is smaller, and the scale of the graphics shrinks or grows the layout around them.
115
+ export function layoutFor(width, height, graphics = 1) {
116
+ const g = Math.min(MAX_GRAPHICS, Math.max(MIN_GRAPHICS, Number(graphics) || 1));
117
+ const scale = Math.max(1, Math.min(width, height) / LAYOUT_SHORT) * g;
118
+ return {
119
+ width: Math.max(1, Math.round(width / scale)),
120
+ height: Math.max(1, Math.round(height / scale)),
121
+ scale,
122
+ };
123
+ }
124
+
125
+ // Returns the safe area mode that a text names, auto, none, social or a percentage. Throws a
126
+ // RangeError for anything else.
127
+ export function parseSafe(text) {
128
+ const value = String(text ?? '').trim().toLowerCase();
129
+ if (!value) {
130
+ return 'auto';
131
+ }
132
+ if (SAFE_MODES.includes(value)) {
133
+ return value;
134
+ }
135
+ const percent = Number(value.replace(/%$/, ''));
136
+ if (value !== '' && Number.isFinite(percent) && percent >= 0 && percent <= MAX_SAFE_PERCENT) {
137
+ return percent;
138
+ }
139
+ throw new RangeError(`A safe area is auto, none, social or a percentage from 0 to ${MAX_SAFE_PERCENT}, not ${JSON.stringify(String(text))}.`);
140
+ }
141
+
142
+ // Returns the margins of the safe area of a picture of the given size, in the same unit, for a
143
+ // mode of parseSafe. A wide picture keeps a twentieth of each side, a tall one a little more at
144
+ // its top and bottom, where a phone holds its own bars. Social keeps clear of the buttons along
145
+ // the right and the captions along the bottom of the apps of short videos.
146
+ export function safeArea(width, height, mode = 'auto') {
147
+ const w = Math.max(0, width);
148
+ const h = Math.max(0, height);
149
+ const round = (v) => Math.round(v * 10) / 10;
150
+ if (mode === 'none') {
151
+ return { top: 0, right: 0, bottom: 0, left: 0 };
152
+ }
153
+ if (typeof mode === 'number') {
154
+ const f = Math.min(MAX_SAFE_PERCENT, Math.max(0, mode)) / 100;
155
+ return { top: round(h * f), right: round(w * f), bottom: round(h * f), left: round(w * f) };
156
+ }
157
+ const tall = shapeOf(w, h) === 'tall';
158
+ if (mode === 'social') {
159
+ return tall
160
+ ? { top: round(h * 0.12), right: round(w * 0.14), bottom: round(h * 0.22), left: round(w * 0.06) }
161
+ : { top: round(h * 0.08), right: round(w * 0.08), bottom: round(h * 0.14), left: round(w * 0.08) };
162
+ }
163
+ return tall
164
+ ? { top: round(h * 0.06), right: round(w * 0.05), bottom: round(h * 0.08), left: round(w * 0.05) }
165
+ : { top: round(h * 0.05), right: round(w * 0.05), bottom: round(h * 0.05), left: round(w * 0.05) };
166
+ }
167
+
168
+ // The shape of a picture, for rules that differ between them.
169
+ export function shapeOf(width, height) {
170
+ const aspect = width / Math.max(1, height);
171
+ if (aspect < 0.85) {
172
+ return 'tall';
173
+ }
174
+ if (aspect < 1.25) {
175
+ return 'square';
176
+ }
177
+ return 'wide';
178
+ }
@@ -0,0 +1,55 @@
1
+ // Copyright 2026 The cuju Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // The start of the page that draws a video export of the browser, active only when the address
5
+ // carries the query parameters capture and export, as video-browser.js opens it in a frame of its
6
+ // own. It runs before main.js, so the viewer starts with the settings of the export, which
7
+ // exportSettings of video-plan.js gives and the parameter export carries. The settings live in
8
+ // memory, so an export never changes the settings that the browser keeps for the page. The
9
+ // drawing takes the pixels of the picture through the parameter ratio, the pointer stays free and
10
+ // keys and controllers reach nothing.
11
+
12
+ import { MemoryStorage } from '../feed-boot.js';
13
+
14
+ const params = new URLSearchParams(location.search);
15
+
16
+ // The settings of the parameter export, a JSON object of the stored settings, or null.
17
+ export function readSettings(text) {
18
+ try {
19
+ const value = JSON.parse(text);
20
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+
26
+ function boot() {
27
+ const settings = readSettings(params.get('export')) || {};
28
+ const storage = new MemoryStorage(Object.entries(settings).map(([key, value]) => [`cuju.${key}`, JSON.stringify(value)]));
29
+ try {
30
+ Object.defineProperty(window, 'localStorage', { configurable: true, get: () => storage });
31
+ } catch {
32
+ // A browser that keeps its storage fixed draws on the stored settings.
33
+ }
34
+ const ratio = Math.min(8, Math.max(0.25, Number(params.get('ratio')) || 1));
35
+ try {
36
+ Object.defineProperty(window, 'devicePixelRatio', { configurable: true, get: () => ratio });
37
+ } catch {
38
+ // The drawing then takes the window's own ratio.
39
+ }
40
+ Element.prototype.requestPointerLock = function () {
41
+ return Promise.reject(new Error('The pointer stays free while exporting.'));
42
+ };
43
+ Object.defineProperty(navigator, 'getGamepads', { configurable: true, value: () => [] });
44
+ for (const type of ['keydown', 'keyup', 'keypress']) {
45
+ window.addEventListener(type, (e) => {
46
+ e.stopImmediatePropagation();
47
+ e.preventDefault();
48
+ }, true);
49
+ }
50
+ window.cujuExport = { ratio };
51
+ }
52
+
53
+ if (params.has('capture') && params.has('export')) {
54
+ boot();
55
+ }