├── .nvmrc ├── .npmrc ├── shared ├── libs │ ├── posenet.js │ ├── artoolkit_wasm.wasm │ ├── cannon.json │ ├── ml5.json │ ├── jszip.json │ ├── socket.io.min.json │ ├── d3.json │ ├── mp_pose.json │ ├── tone.json │ ├── colorrick.json │ ├── exrloader.json │ ├── hashids.json │ ├── whammy.json │ ├── resemble.json │ ├── bodymovin.json │ ├── hammer.json │ ├── lottie_svg.json │ ├── meyda.json │ ├── posenet-tfjs.json │ ├── ammo.json │ ├── fuse.json │ ├── lottie.json │ ├── marked.json │ ├── mp_face.json │ ├── mp_hands.json │ ├── qrcode.json │ ├── ammo.wasm.json │ ├── earcut.json │ ├── fflate.json │ ├── iwanthue.json │ ├── mp_camera_utils.json │ ├── pako.json │ ├── perlin.json │ ├── jeelizFaceFilter.json │ ├── lottie_canvas.min.json │ ├── p5.json │ ├── chroma.json │ ├── clmtrackr.json │ ├── moment.json │ ├── socketcluster-client.json │ ├── conway-hart.json │ ├── draco_decoder.json │ ├── jeelizPupillometry.json │ ├── posenet.json │ ├── rhill-voronoi-core.json │ ├── jeelizGlanceTracker.json │ ├── moment-with-locales.json │ ├── tracking.json │ ├── webaudio-peaks.json │ ├── draco_decoder_wasm.json │ ├── moment_with_timezones.json │ ├── mqttws31-min.json │ ├── navigo.json │ ├── opentype.json │ ├── glsltokenizer.json │ ├── draco_wasm_wrapper.json │ ├── twitterFetcher_min.json │ ├── start-audio-context.json │ ├── platform.json │ ├── echarts.json │ ├── webvr-polyfill.json │ ├── artoolkit.json │ ├── tess2.json │ ├── artoolkit_wasm.json │ ├── artoolkit_worker.json │ ├── teachablemachine_tf_speech_image_pose.json │ ├── webaudio-peaks.js │ ├── mp_camera_utils.js │ ├── start-audio-context.js │ └── twitterFetcher_min.js ├── api │ ├── api_constants.js │ ├── utils │ │ ├── shared_libs_util.js │ │ ├── util_provider.js │ │ ├── shared_util.js │ │ ├── shared_teams_util.js │ │ ├── shared_subpatchop_util.js │ │ ├── shared_logger.js │ │ └── shared_files_util.js │ ├── package.json │ └── index.js ├── client │ ├── client_contstants.js │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── eventlistener.js │ │ ├── modalbg.js │ │ ├── helper.js │ │ ├── logger.js │ │ ├── ele.js │ │ ├── eventtarget.js │ │ └── talkerapi.js │ └── index.js ├── package.json ├── shared_constants.json └── buildwatcher.js ├── jsdoc ├── .gitignore ├── dev_robots.txt ├── template │ ├── index.html │ ├── manual.html │ ├── image │ │ ├── search.png │ │ ├── esdoc-logo-mini.png │ │ ├── esdoc-logo-mini-black.png │ │ ├── badge.svg │ │ └── manual-badge.svg │ ├── single.html │ ├── nav.html │ ├── manualIndex.html │ ├── file.html │ ├── script │ │ ├── patch-for-local.js │ │ ├── manual.js │ │ ├── pretty-print.js │ │ ├── inherited-summary.js │ │ ├── inner-link.js │ │ ├── test-summary.js │ │ └── search.js │ ├── testInterface.html │ ├── test.html │ ├── identifiers.html │ ├── manualCardIndex.html │ ├── properties.html │ ├── css │ │ ├── identifiers.css │ │ ├── source.css │ │ ├── test.css │ │ ├── github.css │ │ ├── search.css │ │ ├── prettify-tomorrow.css │ │ └── manual.css │ ├── source.html │ ├── summary.html │ ├── layout.html │ ├── details.html │ └── class.html ├── cables.css ├── index.html ├── package.json ├── config │ ├── core.json │ ├── ui.json │ └── standalone.json └── dev_layout.html ├── docs ├── howto_helper_scripts.md ├── howto_changelog.md ├── howto_create_new_ops.md ├── howto_op_new_version.md ├── toolchain.md └── howto_libraries.md ├── .eslintignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── webook_dev.yml │ ├── webook_pull_dev.yml │ ├── nightly.yml │ ├── tests.yml │ ├── jsdocs_master.yml │ └── jsdocs.yml ├── index.d.ts ├── co.sh ├── .editorconfig ├── .ignore ├── .gitignore ├── tsconfig.json ├── pm2_ecosystem.config.cjs ├── update_ops.sh ├── LICENCE ├── dev_cables.code-workspace ├── package.json ├── hook_standalone.sh ├── start.js ├── tag_repos.sh ├── README.md ├── .eslintrc ├── install_local.sh └── update_repos.sh /.nvmrc: -------------------------------------------------------------------------------- 1 | 20.13.1 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /shared/libs/posenet.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /jsdoc/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | template/layout.html 3 | -------------------------------------------------------------------------------- /jsdoc/dev_robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /docs/howto_helper_scripts.md: -------------------------------------------------------------------------------- 1 | # Helper scripts in cables_dev 2 | -------------------------------------------------------------------------------- /jsdoc/template/index.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /jsdoc/template/manual.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | !cables/src/ops/patches/*/* 2 | !cables/src/ops/teams/*/* 3 | !cables/src/ops/users/*/* 4 | -------------------------------------------------------------------------------- /jsdoc/template/image/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cables-gl/cables_dev/HEAD/jsdoc/template/image/search.png -------------------------------------------------------------------------------- /shared/libs/artoolkit_wasm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cables-gl/cables_dev/HEAD/shared/libs/artoolkit_wasm.wasm -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: cables_gl 4 | ko_fi: cablesgl 5 | 6 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare const vec3:any 3 | declare const vec2:any 4 | declare const mat4:any 5 | declare const chroma:any 6 | -------------------------------------------------------------------------------- /jsdoc/cables.css: -------------------------------------------------------------------------------- 1 | :not(pre) > code { 2 | background: unset !important; 3 | background-color: rgba(0,0,0,0.04); 4 | } 5 | -------------------------------------------------------------------------------- /jsdoc/template/single.html: -------------------------------------------------------------------------------- 1 |

2 |
3 |
4 | -------------------------------------------------------------------------------- /jsdoc/template/image/esdoc-logo-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cables-gl/cables_dev/HEAD/jsdoc/template/image/esdoc-logo-mini.png -------------------------------------------------------------------------------- /jsdoc/template/image/esdoc-logo-mini-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cables-gl/cables_dev/HEAD/jsdoc/template/image/esdoc-logo-mini-black.png -------------------------------------------------------------------------------- /shared/api/api_constants.js: -------------------------------------------------------------------------------- 1 | import CablesConstants from "../shared_constants.json" with { type: "json" }; 2 | 3 | export default { 4 | ...CablesConstants 5 | }; 6 | -------------------------------------------------------------------------------- /shared/libs/cannon.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"cannonjs", 3 | "description":"physics library", 4 | "url":"http://www.cannonjs.org/", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/ml5.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "ml5js", 3 | "description": "machine learning library", 4 | "url": "https://ml5js.org", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/client/client_contstants.js: -------------------------------------------------------------------------------- 1 | import CablesConstants from "../shared_constants.json" with { type: "json" }; 2 | 3 | export default { 4 | ...CablesConstants 5 | }; 6 | -------------------------------------------------------------------------------- /shared/libs/jszip.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"jszip", 3 | "description":"js zip archive library", 4 | "url":"https://stuk.github.io/jszip/", 5 | "licence": "MIT" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /shared/libs/socket.io.min.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"socket.io library", 3 | "description":"socket.io library", 4 | "url":"https://socket.io", 5 | "licence": "MIT" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /co.sh: -------------------------------------------------------------------------------- 1 | echo "----- share dev" 2 | git checkout $1 3 | cd cables 4 | echo "----- core" 5 | git checkout $1 6 | cd .. 7 | cd cables_ui 8 | echo "----- ui" 9 | git checkout $1 10 | cd .. 11 | -------------------------------------------------------------------------------- /shared/libs/d3.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"d3", 3 | "description":"library for visualizing data using web standards", 4 | "url":"https://github.com/d3/d3", 5 | "licence": "ISC" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/mp_pose.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "mediapipe pose", 3 | "description": "", 4 | "url": "https://cdn.jsdelivr.net/npm/@mediapipe/pose/pose.js", 5 | "licence": "Apache" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/tone.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"Tone.js", 3 | "description":"Webaudio Library", 4 | "url":"https://tonejs.github.io/", 5 | "version": "R12", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug, new, devenv 6 | assignees: '' 7 | 8 | 9 | --- 10 | -------------------------------------------------------------------------------- /shared/libs/colorrick.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"colorRick", 3 | "description":"colorpicker without bullshit", 4 | "url":"https://github.com/pandrr/colorRick", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/exrloader.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"exrloader", 3 | "description":"exrloader from three.js", 4 | "url":"https://threejs.org/", 5 | "version": "0", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/hashids.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"hashid", 3 | "description":"generate short unique ids from integers", 4 | "url":"http://hashids.org/", 5 | "licence": "Public Domain" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/whammy.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"Whammy", 3 | "description":"A real time javascript webm encoder", 4 | "url":"https://github.com/antimatter15/whammy", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: new, devenv 6 | assignees: '' 7 | 8 | 9 | --- 10 | -------------------------------------------------------------------------------- /jsdoc/template/nav.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | -------------------------------------------------------------------------------- /shared/libs/resemble.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"Resemble.js", 3 | "description":"Image analysis and comparison", 4 | "url":"https://github.com/Huddle/Resemble.js/", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/bodymovin.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"bodymovin", 3 | "description":"after effect animation exporer/player", 4 | "url":"https://github.com/airbnb/lottie-web", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/hammer.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"hammer.js", 3 | "description":"touch gesture detection", 4 | "url":"https://hammerjs.github.io/", 5 | "version": "2.0.8", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/lottie_svg.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"lottie svg", 3 | "description":"lottie svg", 4 | "url":"https://github.com/airbnb/lottie-web", 5 | "version": "5.10.2", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/meyda.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "meyda", 3 | "description": "Audio feature extraction", 4 | "url": "https://github.com/meyda/meyda", 5 | "version":"5.3.0", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/posenet-tfjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"posenet tensorflow", 3 | "description":"posenet tensorflow", 4 | "url":"https://github.com/tensorflow/tfjs-models", 5 | "licence": "MIT" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /shared/libs/ammo.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"ammo.js", 3 | "description":"Physics Library", 4 | "url":"https://github.com/kripken/ammo.js/", 5 | "version": "28 Jan", 6 | "licence": "Public Domain" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/fuse.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"fuse.js", 3 | "description":"lightweight fuzzy-search", 4 | "url":"https://fusejs.io/", 5 | "version": "v6.6.2", 6 | "licence": "Apache-2.0 License" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/lottie.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"lottie for web", 3 | "description":"lottie for web", 4 | "url":"https://github.com/airbnb/lottie-web", 5 | "version": "5.7.11", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/marked.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "marked", 3 | "description": "markdown to html parser", 4 | "url": "https://github.com/markedjs/marked", 5 | "version":"4.2.3", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/mp_face.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "mediapipe face mesh", 3 | "description": "", 4 | "url": "https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/face_mesh.js", 5 | "licence": "Apache" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/mp_hands.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "mediapipe hands", 3 | "description": "", 4 | "url": "https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js", 5 | "licence": "Apache" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/qrcode.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"qrcode.js", 3 | "description":"Cross-browser QRCode generator for javascript", 4 | "url":"https://davidshimjs.github.io/qrcodejs/", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/ammo.wasm.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"ammo.js", 3 | "description":"Physics Library", 4 | "url":"https://github.com/kripken/ammo.js/", 5 | "version": "25 Mar", 6 | "licence": "Public Domain" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/earcut.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"earcut.js", 3 | "description":"polygon triangulation library", 4 | "url":"https://github.com/mapbox/earcut", 5 | "licence": "ISC", 6 | "version": "2.2.3" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/fflate.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"fflate", 3 | "description":"High performance (de)compression", 4 | "url":"https://github.com/101arrowz/fflate", 5 | "version": "0", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/iwanthue.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"iwanthue.js", 3 | "description":"palette generator", 4 | "url":"http://medialab.github.io/iwanthue/", 5 | "version": "18 nov 2024", 6 | "licence": "" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/mp_camera_utils.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "mediapipe camera", 3 | "description": "", 4 | "url": "https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js", 5 | "licence": "Apache" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/pako.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"pako.js", 3 | "description":"zlib port to javascript, very fast!", 4 | "url":"https://github.com/nodeca/pako", 5 | "version": "2.0.3", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/perlin.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"perlin.js", 3 | "description":"perlin noise library", 4 | "url":"https://github.com/josephg/noisejs/blob/master/perlin.js", 5 | "licence": "Public Domain" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/jeelizFaceFilter.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"jeeliz", 3 | "description":"facetracking lib", 4 | "url":"https://github.com/jeeliz", 5 | "version": "24 oct 2019", 6 | "licence": "Apache License" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/lottie_canvas.min.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"lottie for web", 3 | "description":"lottie for web", 4 | "url":"https://github.com/airbnb/lottie-web", 5 | "version": "5.10.2", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/p5.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"p5.js", 3 | "description":"p5.js is an interpretation of Processing for today’s web", 4 | "url":"https://p5js.org/", 5 | "version": "1.2.0", 6 | "licence": "LGPL" 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | charset = utf-8 4 | end_of_line = lf 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | indent_brace_style=Allman 10 | -------------------------------------------------------------------------------- /shared/libs/chroma.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"chroma.js", 3 | "description":"library for color conversions", 4 | "url":"https://github.com/gka/chroma.js", 5 | "version": "2.4.2", 6 | "licence": "Apache-2.0" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/clmtrackr.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"clmtrackr", 3 | "description":"Javascript library for precise tracking of facial features", 4 | "url":"https://github.com/auduno/clmtrackr", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /jsdoc/template/manualIndex.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 |
7 |
8 | -------------------------------------------------------------------------------- /shared/libs/moment.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"moment.js", 3 | "description":"Parse, validate, manipulate, and display dates and times in JavaScript", 4 | "url":"https://momentjs.com/", 5 | "licence": "Public Domain" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/socketcluster-client.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"socketcluster client", 3 | "description":"socketcluster client", 4 | "url":"https://github.com/SocketCluster/socketcluster-client", 5 | "licence": "MIT" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /shared/libs/conway-hart.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"conway-heart", 3 | "description":"polyhedral notation interpreter", 4 | "url":"https://github.com/mikolalysenko/conway-hart", 5 | "licence": "GPL", 6 | "hidden": true 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/draco_decoder.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"draco", 3 | "description":"draco 3d mesh compression", 4 | "url":"https://github.com/google/draco/tree/gltf_2.0_draco_extension", 5 | "licence": " Apache-2.0 License " 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/jeelizPupillometry.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"jeeliz pupillometry", 3 | "description":"pupil tracking lib", 4 | "url":"https://github.com/jeeliz", 5 | "version": "24 nov 2019", 6 | "licence": "Apache License" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/posenet.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"posenet javascript library", 3 | "description":"posenet javascript library", 4 | "url":"https://github.com/tensorflow/tfjs-models/tree/master/posenet", 5 | "licence": "MIT" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /shared/libs/rhill-voronoi-core.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"Javascript-Voronoi", 3 | "description":"voronoi algorithm library", 4 | "url":"https://github.com/gorhill/Javascript-Voronoi", 5 | "licence": "Public Domain" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /shared/libs/jeelizGlanceTracker.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"jeeliz glance tracking", 3 | "description":"glance tracking lib", 4 | "url":"https://github.com/jeeliz", 5 | "version": "24 nov 2019", 6 | "licence": "Apache License" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/moment-with-locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"moment.js", 3 | "description":"Parse, validate, manipulate, and display dates and times in JavaScript", 4 | "url":"https://momentjs.com/", 5 | "licence": "Public Domain" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/tracking.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"tracking.js", 3 | "description":"Computer Vision on the web", 4 | "url":"https://github.com/eduardolundgren/tracking.js/", 5 | "version": "20. jan 2021", 6 | "licence": "BSD" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/webaudio-peaks.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"Webaudio Peaks", 3 | "description":"extract peaks from audio samples or a webaudio AudioBuffer", 4 | "url":"https://github.com/naomiaro/webaudio-peaks", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/draco_decoder_wasm.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"draco - wasm", 3 | "description":"draco 3d mesh compression", 4 | "url":"https://github.com/google/draco/tree/gltf_2.0_draco_extension", 5 | "licence": " Apache-2.0 License " 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/moment_with_timezones.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"moment.js", 3 | "description":"Parse, validate, manipulate, and display dates and times in JavaScript", 4 | "url":"https://momentjs.com/", 5 | "licence": "Public Domain" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/mqttws31-min.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"websocket to mqtt", 3 | "description":"Use WebSockets to connect to an MQTT Broker", 4 | "url":"https://www.eclipse.org/paho/clients/js/", 5 | "licence": "Eclipse Public License" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/navigo.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "navigo", 3 | "description": "A simple dependency-free minimalistic JavaScript router", 4 | "url": "https://github.com/krasimir/navigo", 5 | "version": "8.1.0", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/opentype.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "opentype", 3 | "description": "A JavaScript parser and writer for TrueType and OpenType fonts", 4 | "url": "https://github.com/opentypejs/opentype.js", 5 | "version": "1.3.4", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/glsltokenizer.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"glsltokenizer.js", 3 | "description":"Maps GLSL string data into GLSL tokens", 4 | "url":"https://www.npmjs.com/package/glsl-tokenizer", 5 | "version": "2.1.5", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/draco_wasm_wrapper.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"draco - wasm wrapper", 3 | "description":"draco 3d mesh compression", 4 | "url":"https://github.com/google/draco/tree/gltf_2.0_draco_extension", 5 | "licence": " Apache-2.0 License " 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/twitterFetcher_min.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"Twitter-Post-Fetcher", 3 | "description":"Allows you to get your tweets displaying on your website", 4 | "url":"https://github.com/jasonmayes/Twitter-Post-Fetcher", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/start-audio-context.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"StartAudioContext", 3 | "description":"Starts the Web Audio API's AudioContext on an explicit user action.", 4 | "url":"https://github.com/tambien/StartAudioContext", 5 | "licence": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /jsdoc/template/file.html: -------------------------------------------------------------------------------- 1 |

2 |
3 |

Sorry, this documentation does not provide source code.

4 | -------------------------------------------------------------------------------- /jsdoc/template/script/patch-for-local.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | if (location.protocol === 'file:') { 3 | var elms = document.querySelectorAll('a[href="./"]'); 4 | for (var i = 0; i < elms.length; i++) { 5 | elms[i].href = './index.html'; 6 | } 7 | } 8 | })(); 9 | -------------------------------------------------------------------------------- /shared/libs/platform.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Platform.js", 3 | "description": "A platform detection library that works on nearly all JavaScript platforms.", 4 | "url": "https://github.com/bestiejs/platform.js/", 5 | "version": "1.3.6", 6 | "licence": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /jsdoc/template/testInterface.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /shared/libs/echarts.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"echarts.js", 3 | "description":"Apache ECharts is a powerful, interactive charting and data visualization library for browser", 4 | "url":"https://echarts.apache.org/en/index.html", 5 | "licence": "Apache-2.0", 6 | "version": "5.1.2" 7 | } 8 | -------------------------------------------------------------------------------- /jsdoc/template/test.html: -------------------------------------------------------------------------------- 1 |

Test

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
DescriptionIdentifier
12 | -------------------------------------------------------------------------------- /shared/libs/webvr-polyfill.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"WebVr Polyfill", 3 | "description":"A JavaScript implementation of the WebVR spec, e.g. use webvr on phones which browsers don't support it", 4 | "url":"https://github.com/immersive-web/webvr-polyfill", 5 | "licence": "Apache License" 6 | } 7 | -------------------------------------------------------------------------------- /shared/libs/artoolkit.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"artoolkit.js", 3 | "description":"Emscripten port of ARToolKit to JavaScript.", 4 | "url":"https://github.com/artoolkitx/jsartoolkit5", 5 | "version": "27. September 2021", 6 | "licence": "ARToolKit LGPLv3 license and additional permission" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/tess2.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"tess2", 3 | "description":"The tess2.js library performs polygon boolean operations and tesselation to triangles and convex polygons.", 4 | "url":"https://github.com/memononen/tess2.js", 5 | "version": "5 Apr 2016", 6 | "licence": "SGI-B-2.0" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/artoolkit_wasm.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"artoolkit.wasm.js", 3 | "description":"Emscripten port of ARToolKit to JavaScript.", 4 | "url":"https://github.com/artoolkitx/jsartoolkit5", 5 | "version": "27. September 2021", 6 | "licence": "ARToolKit LGPLv3 license and additional permission" 7 | } 8 | -------------------------------------------------------------------------------- /shared/libs/artoolkit_worker.json: -------------------------------------------------------------------------------- 1 | { 2 | "title":"artoolkit.wasm.js", 3 | "description":"Emscripten port of ARToolKit to JavaScript.", 4 | "url":"https://github.com/artoolkitx/jsartoolkit5", 5 | "version": "27. September 2021", 6 | "licence": "ARToolKit LGPLv3 license and additional permission" 7 | } 8 | -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | cables/build/* 2 | cables_ui/dist/ 3 | cables_electron/dist/ 4 | jsdoc/dist/ 5 | cables_api/public/landing/standalone/patch/** 6 | cables_api/public/landing/standalone/hero/js/* 7 | cables_api/public/libs_core/** 8 | **/node_modules/** 9 | **/public/js/ 10 | **/gen/** 11 | **/public/js/libs_core/* 12 | **/public/libs_core/* 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | electron/ 3 | data/ 4 | docker-compose.yml 5 | gen/ 6 | 7 | # misc 8 | .idea/ 9 | .DS_Store 10 | .vscode 11 | docker-compose.yml 12 | 13 | # OS generated files # 14 | ###################### 15 | .DS_Store? 16 | ._* 17 | .Spotlight-V100 18 | .Trashes 19 | ehthumbs.db 20 | Thumbs.db 21 | 22 | #Node modules folder 23 | node_modules 24 | .external-ecmascript.js 25 | -------------------------------------------------------------------------------- /shared/libs/teachablemachine_tf_speech_image_pose.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "teachablemachine_tf_speech_image_pose", 3 | "description": "Library for using models created with Teachable Machine. Includes tensorflow, tensorflow speech models, 'image' and 'pose'", 4 | "url": "https://github.com/googlecreativelab/teachablemachine-libraries", 5 | "version": "0.8.4", 6 | "licence": "Apache-2.0" 7 | } 8 | -------------------------------------------------------------------------------- /docs/howto_changelog.md: -------------------------------------------------------------------------------- 1 | # How to add Changelog entries to Ops 2 | 3 | The following terms are used 4 | - New op : Op name here - One line summary of op 5 | - Op enhancement : Op name here - summary of enhancement / can also be a bug fix 6 | - Editor : Summary of changes to editor 7 | - Web : summary of change 8 | - Core : Summary of change 9 | 10 | Check [here](https://cables.gl/changelog) for examples 11 | -------------------------------------------------------------------------------- /jsdoc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | cables.gl jsdocs 4 | 5 | 6 | 7 | documentation on developing cables 8 | 9 | 10 | -------------------------------------------------------------------------------- /shared/client/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cables-shared-client", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cables-shared-client", 9 | "version": "0.0.1", 10 | "license": "MIT", 11 | "engines": { 12 | "node": "20.13.1" 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /jsdoc/template/identifiers.html: -------------------------------------------------------------------------------- 1 |

References

2 | 3 |
4 |
5 |
6 |

7 |
8 |
9 |
10 | 11 |
12 |
Directories
13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /jsdoc/template/manualCardIndex.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |

5 | 6 |
7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /shared/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cables-shared-client", 3 | "version": "0.0.1", 4 | "author": "undefined development", 5 | "description": "shared client classes between the different subprojects of cables_dev", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/cables-gl/cables_dev.git" 9 | }, 10 | "main": "index.js", 11 | "engines": { 12 | "node": "20.13.1" 13 | }, 14 | "type": "module", 15 | "license": "MIT" 16 | } 17 | -------------------------------------------------------------------------------- /jsdoc/template/properties.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
NameTypeAttributeDescription
16 |
17 | -------------------------------------------------------------------------------- /shared/client/src/eventlistener.js: -------------------------------------------------------------------------------- 1 | export class EventListener 2 | { 3 | 4 | /** 5 | * @param {Object} emitter 6 | * @param {string} id 7 | * @param {string} eventName 8 | * @param {Function} cb 9 | */ 10 | constructor(emitter, id, eventName, cb) 11 | { 12 | this.targetObj = emitter; 13 | this.id = id; 14 | this.eventName = eventName; 15 | this.cb = cb; 16 | } 17 | 18 | remove() 19 | { 20 | this.targetObj.off(this.id); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "checkJs": true, 6 | "allowJs": true, 7 | "moduleResolution": "bundler", 8 | "typeRoots": [ 9 | "cables/node_modules/@webgpu/types" 10 | ] 11 | }, 12 | "include": [ 13 | "shared/api/**/*", 14 | "shared/client/src/**/*", 15 | "cables_ui/src/**/*", 16 | "cables/src/core/**/*", 17 | "cables/src/corelibs/**/*" 18 | ] 19 | } -------------------------------------------------------------------------------- /jsdoc/template/script/manual.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var matched = location.pathname.match(/\/(manual\/.*\.html)$/); 3 | if (!matched) return; 4 | 5 | var currentName = matched[1]; 6 | var cssClass = '.navigation .manual-toc li[data-link="' + currentName + '"]'; 7 | var styleText = cssClass + '{ display: block; }\n'; 8 | styleText += cssClass + '.indent-h1 a { color: #039BE5 }'; 9 | var style = document.createElement('style'); 10 | style.textContent = styleText; 11 | document.querySelector('head').appendChild(style); 12 | })(); 13 | -------------------------------------------------------------------------------- /docs/howto_create_new_ops.md: -------------------------------------------------------------------------------- 1 | # How to create new Ops 2 | 3 | - Correct namespace / e.g. `Ops.Gl.TextureEffects.Blur` 4 | - Changelog has been updated with correct op name and one line summary / new op : `Ops.Gl.TextureEffects.Blur - blurs a texture ` 5 | - Make sure the op has full documentation, it doesn't matter if it seems obvious what a parameter does its parameters should all be documented. 6 | - Make sure the op has an example patch. Go to the op page, edit the documentation and put in the short-id of the example patch. 7 | - Make sure the author name is correct. 8 | -------------------------------------------------------------------------------- /.github/workflows/webook_dev.yml: -------------------------------------------------------------------------------- 1 | name: 'webhook dev' 2 | 3 | on: 4 | workflow_dispatch: 5 | # push: 6 | # branches: 7 | # - develop 8 | # paths: 9 | # - "shared/**" 10 | 11 | jobs: 12 | webhook-dev: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: notify dev 16 | uses: distributhor/workflow-webhook@v3 17 | with: 18 | curl_opts: "--retry 5 --retry-all-errors" 19 | webhook_type: "json-extended" 20 | webhook_url: "https://dev.cables.gl/api/webhooks/updateshared?secret=${{ secrets.WEBHOOK_SECRET }}" 21 | webhook_secret: ${{ secrets.WEBHOOK_SECRET }} 22 | -------------------------------------------------------------------------------- /.github/workflows/webook_pull_dev.yml: -------------------------------------------------------------------------------- 1 | name: 'webhook pull dev' 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - develop 8 | paths-ignore: 9 | - "shared/**" 10 | 11 | jobs: 12 | webhook-dev: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: notify dev 16 | uses: distributhor/workflow-webhook@v3 17 | with: 18 | curl_opts: "--retry 5 --retry-all-errors" 19 | webhook_type: "json-extended" 20 | webhook_url: "https://dev.cables.gl/api/webhooks/pulldev?secret=${{ secrets.WEBHOOK_SECRET }}" 21 | webhook_secret: ${{ secrets.WEBHOOK_SECRET }} 22 | -------------------------------------------------------------------------------- /shared/client/index.js: -------------------------------------------------------------------------------- 1 | import ele from "./src/ele.js"; 2 | import helper from "./src/helper.js"; 3 | import Events from "./src/eventtarget.js"; 4 | import TalkerAPI from "./src/talkerapi.js"; 5 | import Logger from "./src/logger.js"; 6 | import ModalBackground from "./src/modalbg.js"; 7 | import HandlebarsHelper from "./src/handlebars.js"; 8 | import CablesConstants from "./client_contstants.js"; 9 | import BuildWatcher from "../buildwatcher.js"; 10 | 11 | export { 12 | helper, 13 | ele, 14 | Events, 15 | TalkerAPI, 16 | Logger, 17 | ModalBackground, 18 | HandlebarsHelper, 19 | CablesConstants, 20 | BuildWatcher 21 | }; 22 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: 'nightly merge' 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 3 * * *' 7 | 8 | jobs: 9 | nightly-merge: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: nightly merge 18 | uses: usertesting/gh-action-nightly-merge@ut-v1.3.1-fixed 19 | with: 20 | stable_branch: 'develop' 21 | development_branch: 'nightly' 22 | allow_ff: false 23 | allow_forks: true 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /jsdoc/template/css/identifiers.css: -------------------------------------------------------------------------------- 1 | .identifiers-wrap { 2 | display: flex; 3 | align-items: flex-start; 4 | } 5 | 6 | .identifier-dir-tree { 7 | background: #fff; 8 | border: solid 1px #ddd; 9 | border-radius: 0.25em; 10 | top: 52px; 11 | position: -webkit-sticky; 12 | position: sticky; 13 | max-height: calc(100vh - 155px); 14 | overflow-y: scroll; 15 | min-width: 200px; 16 | margin-left: 1em; 17 | } 18 | 19 | .identifier-dir-tree-header { 20 | padding: 0.5em; 21 | background-color: #fafafa; 22 | border-bottom: solid 1px #ddd; 23 | } 24 | 25 | .identifier-dir-tree-content { 26 | padding: 0 0.5em 0; 27 | } 28 | 29 | .identifier-dir-tree-content > div { 30 | padding-top: 0.25em; 31 | padding-bottom: 0.25em; 32 | } 33 | 34 | .identifier-dir-tree-content a { 35 | color: inherit; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cables-shared", 3 | "version": "0.0.1", 4 | "author": "undefined development", 5 | "description": "shared artifacts between the different subproject builds of cables_dev", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/cables-gl/cables_dev.git" 9 | }, 10 | "engines": { 11 | "node": "20.13.1" 12 | }, 13 | "devDependencies": { 14 | "npm-run-all": "4.1.5", 15 | "socketcluster-client": "19.2.3", 16 | "jwt-encode": "1.0.1" 17 | }, 18 | "type": "module", 19 | "license": "MIT", 20 | "scripts": { 21 | "build": "run-s api client", 22 | "api": "cd ./api && npm install --loglevel silent", 23 | "client": "cd ./client && npm install --loglevel silent" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /jsdoc/template/image/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | document 13 | document 14 | @ratio@ 15 | @ratio@ 16 | 17 | 18 | -------------------------------------------------------------------------------- /jsdoc/template/image/manual-badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | manual 13 | manual 14 | @value@ 15 | @value@ 16 | 17 | 18 | -------------------------------------------------------------------------------- /jsdoc/template/script/pretty-print.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | prettyPrint(); 3 | var lines = document.querySelectorAll('.prettyprint.linenums li[class^="L"]'); 4 | for (var i = 0; i < lines.length; i++) { 5 | lines[i].id = 'lineNumber' + (i + 1); 6 | } 7 | 8 | var matched = location.hash.match(/errorLines=([\d,]+)/); 9 | if (matched) { 10 | var lines = matched[1].split(','); 11 | for (var i = 0; i < lines.length; i++) { 12 | var id = '#lineNumber' + lines[i]; 13 | var el = document.querySelector(id); 14 | el.classList.add('error-line'); 15 | } 16 | return; 17 | } 18 | 19 | if (location.hash) { 20 | // ``[ ] . ' " @`` are not valid in DOM id. so must escape these. 21 | var id = location.hash.replace(/([\[\].'"@$])/g, '\\$1'); 22 | var line = document.querySelector(id); 23 | if (line) line.classList.add('active'); 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /docs/howto_op_new_version.md: -------------------------------------------------------------------------------- 1 | # How to create a new version of an Op 2 | 3 | - Make sure that the version characters are added correctly. e.g. `Ops.Array.Array` becomes `Ops.Array.Array_v2` the next version would be `Ops.Array.Array_v3`. This removes all previous versions from the op creation menu for users. Old versions can only be found again on the op documentation page. 4 | - Make sure to copy over all relevant documentation from the previous version as the new op will have none. 5 | - Make sure that the op has a new example patch, it won't reference the old one. 6 | - If a port type has to be changed e.g. `op.inValueString` to `op.inString` then a new version of an op must be created, or it will break all patches that use that op. 7 | - A port name cannot be changed without breaking all patches that use it. Make a new version of the op if the port name must be changed. 8 | - Make sure the author name is correct from the user that made the previous version. 9 | -------------------------------------------------------------------------------- /docs/toolchain.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | cables uses the following tools for developing, building, deploying: 4 | 5 | - `javascript/ecmascript` as a main language 6 | - [git](https://git-scm.com/) for version control 7 | - [npm](https://www.npmjs.com/) and [nvm](https://github.com/nvm-sh/nvm) for dependency management 8 | - `npm run build` and `npm run start` are the main commands used 9 | - [bash](https://www.gnu.org/software/bash/) for running [shell-scripts](./howto_helper_scripts.md) (mostly helper-script to update/install everything) 10 | - [gulp](https://gulpjs.com/) for running the build scripts 11 | - [webpack](https://webpack.js.org/) to package bundles to use in other parts of the project 12 | - [eslint](https://eslint.org/) for linting code in editors 13 | - [electron](https://www.electronjs.org/) and [electron-builder](https://www.electron.build/) to pack and distribute cables standalone 14 | - several other open-source [tools and libraries](https://cables.gl/support), to get things done 15 | -------------------------------------------------------------------------------- /jsdoc/template/source.html: -------------------------------------------------------------------------------- 1 |

Source

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
FileIdentifierDocumentSizeLinesUpdated
25 | -------------------------------------------------------------------------------- /shared/api/utils/shared_libs_util.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | import sanitizeFileName from "sanitize-filename"; 4 | import SharedUtil from "./shared_util.js"; 5 | import { UtilProvider } from "./util_provider.js"; 6 | 7 | /** 8 | * @abstract 9 | */ 10 | export default class SharedLibsUtil extends SharedUtil 11 | { 12 | constructor(utilProvider) 13 | { 14 | super(utilProvider); 15 | } 16 | 17 | get utilName() 18 | { 19 | return UtilProvider.LIBS_UTIL; 20 | } 21 | 22 | libExists(libName) 23 | { 24 | let existsLib = false; 25 | if (typeof libName === "string") 26 | { 27 | libName = sanitizeFileName(libName); 28 | const libFilename = this._cables.getLibsPath() + libName; 29 | existsLib = fs.existsSync(libFilename); 30 | } 31 | return existsLib; 32 | } 33 | 34 | isAssetLib(fileName) 35 | { 36 | return (fileName && fileName.startsWith("/assets/") && fileName.endsWith(".js")); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /shared/api/utils/util_provider.js: -------------------------------------------------------------------------------- 1 | class UtilProvider 2 | { 3 | constructor() 4 | { 5 | this._utils = {}; 6 | } 7 | 8 | getUtil(name) 9 | { 10 | return this._utils[name]; 11 | } 12 | 13 | register(name, that) 14 | { 15 | const logger = this.getUtil(UtilProvider.LOGGER); 16 | if (logger) logger.info("registering", that.constructor.name, "as", name); 17 | this._utils[name] = that; 18 | } 19 | } 20 | UtilProvider.CABLES = "cables"; 21 | UtilProvider.DOCS_UTIL = "docsUtil"; 22 | UtilProvider.HELPER_UTIL = "helperUtil"; 23 | UtilProvider.LOGGER = "logger"; 24 | UtilProvider.OPS_UTIL = "opsUtil"; 25 | UtilProvider.SUBPATCH_OP_UTIL = "subPatchOpUtil"; 26 | UtilProvider.TEAMS_UTIL = "teamsUtil"; 27 | UtilProvider.PROJECTS_UTIL = "projectsUtil"; 28 | UtilProvider.FILES_UTIL = "filesUtil"; 29 | UtilProvider.LIBS_UTIL = "libsUtil"; 30 | UtilProvider.EXPORT_SERVICE = "exportService"; 31 | UtilProvider.BUILD_WATCHER = "buildWatcher"; 32 | 33 | export { UtilProvider }; 34 | export default new UtilProvider(); 35 | -------------------------------------------------------------------------------- /jsdoc/template/script/inherited-summary.js: -------------------------------------------------------------------------------- 1 | (function () 2 | { 3 | function toggle(ev) 4 | { 5 | let button = ev.target; 6 | let parent = ev.target.parentElement; 7 | while (parent) 8 | { 9 | if (parent.tagName === "TABLE" && parent.classList.contains("summary")) break; 10 | parent = parent.parentElement; 11 | } 12 | 13 | if (!parent) return; 14 | 15 | let tbody = parent.querySelector("tbody"); 16 | if (button.classList.contains("opened")) 17 | { 18 | button.classList.remove("opened"); 19 | button.classList.add("closed"); 20 | tbody.style.display = "none"; 21 | } 22 | else 23 | { 24 | button.classList.remove("closed"); 25 | button.classList.add("opened"); 26 | tbody.style.display = "block"; 27 | } 28 | } 29 | 30 | let buttons = document.querySelectorAll(".inherited-summary thead .toggle"); 31 | for (let i = 0; i < buttons.length; i++) 32 | { 33 | buttons[i].addEventListener("click", toggle); 34 | } 35 | }()); 36 | -------------------------------------------------------------------------------- /pm2_ecosystem.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "treekill": false, 3 | "apps": [ 4 | { 5 | "name": "server_api", 6 | "script": "src/servers/server_api.js", 7 | "cwd": "./cables_api", 8 | "instances": 4, 9 | "increment_var": "PM2_INSTANCE_ID", 10 | "env": { 11 | "PM2_INSTANCE_ID": 0 12 | } 13 | }, 14 | { 15 | "name": "server_sandbox", 16 | "script": "src/servers/server_sandbox.js", 17 | "cwd": "./cables_api", 18 | "instances": 4, 19 | "increment_var": "PM2_INSTANCE_ID", 20 | "env": { 21 | "PM2_INSTANCE_ID": 0 22 | } 23 | }, 24 | { 25 | "name": "server_socketcluster", 26 | "script": "src/servers/server_socketcluster.js", 27 | "cwd": "./cables_api", 28 | "instances": 1, 29 | "args": "-w 2 -s 2", 30 | "increment_var": "PM2_INSTANCE_ID", 31 | "env": { 32 | "PM2_INSTANCE_ID": 0 33 | } 34 | }] 35 | }; 36 | -------------------------------------------------------------------------------- /jsdoc/template/script/inner-link.js: -------------------------------------------------------------------------------- 1 | // inner link(#foo) can not correctly scroll, because page has fixed header, 2 | // so, I manually scroll. 3 | (function(){ 4 | var matched = location.hash.match(/errorLines=([\d,]+)/); 5 | if (matched) return; 6 | 7 | function adjust() { 8 | window.scrollBy(0, -55); 9 | var el = document.querySelector('.inner-link-active'); 10 | if (el) el.classList.remove('inner-link-active'); 11 | 12 | // ``[ ] . ' " @`` are not valid in DOM id. so must escape these. 13 | var id = location.hash.replace(/([\[\].'"@$])/g, '\\$1'); 14 | var el = document.querySelector(id); 15 | if (el) el.classList.add('inner-link-active'); 16 | } 17 | 18 | window.addEventListener('hashchange', adjust); 19 | 20 | if (location.hash) { 21 | setTimeout(adjust, 0); 22 | } 23 | })(); 24 | 25 | (function(){ 26 | var els = document.querySelectorAll('[href^="#"]'); 27 | var href = location.href.replace(/#.*$/, ''); // remove existed hash 28 | for (var i = 0; i < els.length; i++) { 29 | var el = els[i]; 30 | el.href = href + el.getAttribute('href'); // because el.href is absolute path 31 | } 32 | })(); 33 | -------------------------------------------------------------------------------- /update_ops.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -l 2 | # update userops/teamops if the default-dirs exist 3 | 4 | git pull 5 | 6 | set -e 7 | set -o pipefail 8 | 9 | CWD=`pwd` 10 | 11 | cd cables 12 | cd src/ops/ 13 | BASEDIR=`pwd` 14 | 15 | OPSDIR=$BASEDIR/users/ 16 | branch="master" 17 | if [ -d "$OPSDIR" ]; then 18 | echo "UPDATING USEROPS..." 19 | cd $OPSDIR 20 | if [ -d ".git" ]; then 21 | git checkout $branch 22 | git pull 23 | else 24 | echo " NOT A GIT REPO AT $OPSDIR, SKIPPING"; 25 | fi 26 | else 27 | echo " DIR NOT FOUND AT $OPSDIR, SKIPPING"; 28 | fi 29 | 30 | OPSDIR=$BASEDIR/teams/ 31 | branch="main" 32 | if [ -d "$OPSDIR" ]; then 33 | echo "UPDATING TEAMOPS..." 34 | cd $OPSDIR 35 | if [ -d ".git" ]; then 36 | git checkout $branch 37 | git pull 38 | else 39 | echo " NOT A GIT REPO AT $OPSDIR, SKIPPING"; 40 | fi 41 | else 42 | echo " DIR NOT FOUND AT $OPSDIR, SKIPPING"; 43 | fi 44 | 45 | cd $CWD 46 | if [ -d cables_api ]; then 47 | if [ -f cables_api/package.json ]; then 48 | echo "UPDATING OPDOCS..." 49 | cd $CWD/cables_api 50 | npm run opdocs 51 | fi 52 | fi 53 | cd $CWD 54 | 55 | echo "DONE" 56 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019-present undefined development 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /shared/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cables-shared-api", 3 | "version": "0.0.1", 4 | "author": "undefined development", 5 | "description": "shared api classes between the different subprojects of cables_dev", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/cables-gl/cables_dev.git" 9 | }, 10 | "main": "index.js", 11 | "engines": { 12 | "node": "20.13.1" 13 | }, 14 | "type": "module", 15 | "license": "MIT", 16 | "dependencies": { 17 | "archiver": "5.3.1", 18 | "eslint": "7.32.0", 19 | "eslint-config-airbnb-base": "14.2.1", 20 | "eslint-plugin-import": "2.27.5", 21 | "fs-extra": "11.2.0", 22 | "glsl-tokenizer": "2.1.5", 23 | "image-size": "1.0.2", 24 | "jsonfile": "6.1.0", 25 | "marked": "12.0.2", 26 | "mkdirp": "2.1.3", 27 | "moment-mini": "2.29.4", 28 | "project-name-generator": "2.1.9", 29 | "sanitize-filename": "1.6.3", 30 | "uuid-v4": "0.1.0", 31 | "xml-writer": "1.7.0", 32 | "md5-file": "5.0.0" 33 | }, 34 | "devDependencies": { 35 | "@types/node": "20.13.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /jsdoc/template/css/source.css: -------------------------------------------------------------------------------- 1 | table.files-summary { 2 | width: 100%; 3 | margin: 10px 0; 4 | border-spacing: 0; 5 | border: 0; 6 | border-collapse: collapse; 7 | text-align: right; 8 | } 9 | 10 | table.files-summary tbody tr:hover { 11 | background: #eee; 12 | } 13 | 14 | table.files-summary td:first-child, 15 | table.files-summary td:nth-of-type(2) { 16 | text-align: left; 17 | } 18 | 19 | table.files-summary[data-use-coverage="false"] td.coverage { 20 | display: none; 21 | } 22 | 23 | table.files-summary thead { 24 | background: #fafafa; 25 | } 26 | 27 | table.files-summary td { 28 | border: solid 1px #ddd; 29 | padding: 4px 10px; 30 | vertical-align: top; 31 | } 32 | 33 | table.files-summary td.identifiers > span { 34 | display: block; 35 | margin-top: 4px; 36 | } 37 | table.files-summary td.identifiers > span:first-child { 38 | margin-top: 0; 39 | } 40 | 41 | table.files-summary .coverage-count { 42 | font-size: 12px; 43 | color: #aaa; 44 | display: inline-block; 45 | min-width: 40px; 46 | } 47 | 48 | .total-coverage-count { 49 | position: relative; 50 | bottom: 2px; 51 | font-size: 12px; 52 | color: #666; 53 | font-weight: 500; 54 | padding-left: 5px; 55 | } 56 | -------------------------------------------------------------------------------- /dev_cables.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | 9 | "editor.codeActionsOnSave": { 10 | "source.fixAll.eslint": "explicit" 11 | }, 12 | "editor.formatOnSaveTimeout": 1000, 13 | "eslint.alwaysShowStatus": true, 14 | "files.autoSave": "off", 15 | "editor.autoIndent": "full", 16 | "eslint.enable": true, 17 | "prettier.eslintIntegration": true, 18 | "typescript.validate.enable": false, 19 | "javascript.format.enable": false, 20 | "prettier.tabWidth": 4, 21 | "search.useIgnoreFiles": false, 22 | "search.exclude": { 23 | "**/node_modules": true, 24 | "**/bower_components": true, 25 | "**/*min.js": true, 26 | "**/*max.js": true, 27 | "**/*.map.*": true, 28 | "*/ace/*": true, 29 | "*dist/*": true, 30 | "*jsdoc*": true, 31 | "*build*": true, 32 | "*/public/*": true, 33 | "*/logs*": true 34 | }, 35 | "files.exclude": { 36 | "**/.node_modules": true 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /jsdoc/template/summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 27 | 31 | 32 | 33 |
6 | 7 | 8 | 9 | 10 | 11 | 13 |
14 |

15 | 16 | 17 | 18 | 19 |

20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 | version 29 | since 30 |
34 | -------------------------------------------------------------------------------- /jsdoc/template/css/test.css: -------------------------------------------------------------------------------- 1 | table.test-summary thead { 2 | background: #fafafa; 3 | } 4 | 5 | table.test-summary thead .test-description { 6 | width: 50%; 7 | } 8 | 9 | table.test-summary { 10 | width: 100%; 11 | margin: 10px 0; 12 | border-spacing: 0; 13 | border: 0; 14 | border-collapse: collapse; 15 | } 16 | 17 | table.test-summary thead .test-count { 18 | width: 3em; 19 | } 20 | 21 | table.test-summary tbody tr:hover { 22 | background-color: #eee; 23 | } 24 | 25 | table.test-summary td { 26 | border: solid 1px #ddd; 27 | padding: 4px 10px; 28 | vertical-align: top; 29 | } 30 | 31 | table.test-summary td p { 32 | margin: 0; 33 | } 34 | 35 | table.test-summary tr.test-interface .toggle { 36 | display: inline-block; 37 | float: left; 38 | margin-right: 4px; 39 | cursor: pointer; 40 | font-size: 0.8em; 41 | padding-top: 0.25em; 42 | } 43 | 44 | table.test-summary tr.test-interface .toggle.opened:before { 45 | content: '▼'; 46 | } 47 | 48 | table.test-summary tr.test-interface .toggle.closed:before { 49 | content: '▶'; 50 | } 51 | 52 | table.test-summary .test-target > span { 53 | display: block; 54 | margin-top: 4px; 55 | } 56 | table.test-summary .test-target > span:first-child { 57 | margin-top: 0; 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: nightly tests 2 | 3 | on: 4 | workflow_dispatch: 5 | # schedule: 6 | # - cron: '0 3 * * *' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: install nodejs 14 | uses: actions/setup-node@v4 15 | with: 16 | node-version-file: ".nvmrc" 17 | check-latest: false 18 | - name: install nvm 19 | run: | 20 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash 21 | echo -n 'nvm "$@" && echo $NVM_BIN >> $GITHUB_PATH' >> ~/.nvm/nvm.sh 22 | sudo cp ~/.nvm/nvm.sh /usr/local/bin/nvm 23 | sudo chmod +x /usr/local/bin/nvm 24 | - name: setup repos 25 | run: | 26 | ./install_local.sh https 27 | - name: checkout api 28 | uses: actions/checkout@v4 29 | with: 30 | repository: "undev-studio/cables_api" 31 | ref: develop 32 | token: ${{ secrets.undev_token }} 33 | path: "cables_api/" 34 | fetch-depth: 0 35 | - name: export tests 36 | run: | 37 | cd cables_api/ 38 | npm install --no-save 39 | npm run tests:export 40 | -------------------------------------------------------------------------------- /shared/api/index.js: -------------------------------------------------------------------------------- 1 | import SharedUtil from "./utils/shared_util.js"; 2 | import Cables from "./cables.js"; 3 | import utilProvider from "./utils/util_provider.js"; 4 | import SharedDocUtil from "./utils/shared_doc_util.js"; 5 | import SharedHelperUtil from "./utils/shared_helper_util.js"; 6 | import SharedOpsUtil from "./utils/shared_ops_util.js"; 7 | import SharedTeamsUtil from "./utils/shared_teams_util.js"; 8 | import SharedSubPatchOpUtil from "./utils/shared_subpatchop_util.js"; 9 | import SharedLogger from "./utils/shared_logger.js"; 10 | import SharedProjectsUtil from "./utils/shared_projects_util.js"; 11 | import SharedFilesUtil from "./utils/shared_files_util.js"; 12 | import SharedLibsUtil from "./utils/shared_libs_util.js"; 13 | import SharedExportService from "./export/shared_export_service.js"; 14 | import CablesConstants from "./api_constants.js"; 15 | import BuildWatcher from "../buildwatcher.js"; 16 | 17 | export { 18 | utilProvider, 19 | Cables, 20 | SharedUtil, 21 | SharedDocUtil, 22 | SharedHelperUtil, 23 | SharedOpsUtil, 24 | SharedProjectsUtil, 25 | SharedTeamsUtil, 26 | SharedSubPatchOpUtil, 27 | SharedFilesUtil, 28 | SharedLibsUtil, 29 | SharedLogger, 30 | SharedExportService, 31 | CablesConstants, 32 | BuildWatcher 33 | }; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cables_dev", 3 | "version": "1.0.0", 4 | "description": "cables development environment", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "start": "cross-env node start.js", 9 | "watch:standalone": "cross-env node start.js standalone", 10 | "test": "echo \"Error: no test specified\" && exit 1", 11 | "pm2": "pm2 start pm2_ecosystem.config.cjs" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/cables-gl/cables_dev.git" 16 | }, 17 | "engines": { 18 | "node": "20.13.1" 19 | }, 20 | "author": "", 21 | "license": "ISC", 22 | "bugs": { 23 | "url": "https://github.com/cables-gl/cables/issues" 24 | }, 25 | "homepage": "https://github.com/cables-gl/cables_dev#readme", 26 | "devDependencies": { 27 | "concurrently": "8.2.2", 28 | "cross-env": "5.2.0", 29 | "eslint": "8.40.0", 30 | "eslint-config-airbnb-base": "15.0.0", 31 | "eslint-plugin-import": "2.27.5", 32 | "npm": "10.5.2", 33 | "pm2": "6.0.13", 34 | "prettier": "3.2.5", 35 | "prettier-eslint": "16.3.0", 36 | "tree-kill": "1.2.2", 37 | "uglify-js": "3.18.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /jsdoc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cables-jsdoc", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "build.js", 6 | "type": "module", 7 | "scripts": { 8 | "build": "run-s build:core build:ui build:standalone build:index", 9 | "build:dev": "run-s build:devlayout build build:robots", 10 | "build:core": "esdoc -c config/core.json", 11 | "build:ui": "esdoc -c config/ui.json", 12 | "build:standalone": "esdoc -c config/standalone.json", 13 | "build:devlayout": "cp dev_layout.html template/layout.html", 14 | "build:robots": "cp dev_robots.txt dist/robots.txt", 15 | "build:index": "cp index.html dist/index.html", 16 | "start": "http-server dist/" 17 | }, 18 | "engines": { 19 | "node": "20.13.1" 20 | }, 21 | "author": "", 22 | "license": "ISC", 23 | "devDependencies": { 24 | "@enterthenamehere/esdoc": "2.6.0-dev.1", 25 | "@enterthenamehere/esdoc-importpath-plugin":"2.6.0-dev.1", 26 | "@enterthenamehere/esdoc-standard-plugin": "2.6.0-dev.2", 27 | "@enterthenamehere/esdoc-publish-html-plugin": "2.6.0-dev.1", 28 | "@enterthenamehere/esdoc-inject-style-plugin": "2.6.0-dev.1", 29 | "@itsjamie/esdoc-importpath-plugin": "0.5.0", 30 | "npm-run-all": "4.1.5", 31 | "http-server": "14.1.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /jsdoc/config/core.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "../cables/README.md", 3 | "source": "../", 4 | "destination": "dist/cables", 5 | "includes": [ 6 | "^cables/src/core/.*\\.js$", 7 | "^cables/src/libs/.*\\.js$" 8 | ], 9 | "excludes": [ 10 | "node_modules" 11 | ], 12 | "plugins": [ 13 | { 14 | "name": "@enterthenamehere/esdoc-standard-plugin" 15 | }, 16 | { 17 | "name": "@enterthenamehere/esdoc-brand-plugin", 18 | "option": { 19 | "title": "cables.gl", 20 | "repository": "https://github.com/cables-gl/cables", 21 | "site": "https://cables.gl", 22 | "author": "https://undev.studio" 23 | } 24 | }, 25 | { 26 | "name": "@enterthenamehere/esdoc-inject-style-plugin", 27 | "option": { 28 | "enable": true, 29 | "styles": [ 30 | "./cables.css" 31 | ] 32 | } 33 | }, 34 | { 35 | "name": "@enterthenamehere/esdoc-importpath-plugin", 36 | "option": { 37 | "stripPackageName": true, 38 | "replaces": [ 39 | { 40 | "from": "^cables_dev/cables/src/", 41 | "to": "./" 42 | } 43 | ] 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /shared/client/src/modalbg.js: -------------------------------------------------------------------------------- 1 | import ele from "./ele.js"; 2 | import Events from "./eventtarget.js"; 3 | 4 | export default class ModalBackground extends Events 5 | { 6 | constructor(options = {}) 7 | { 8 | super(); 9 | this._eleBg = ele.byId("modalbg"); 10 | this.showing = false; 11 | 12 | this._eleBg.addEventListener("pointerdown", () => 13 | { 14 | this.hide(); 15 | }); 16 | this._eleBg.addEventListener("click", () => 17 | { 18 | this.hide(); 19 | }); 20 | 21 | if (options.listenToEsc) 22 | document.body.addEventListener("keydown", 23 | (event) => 24 | { 25 | if (this.showing && event.key === "Escape") this.hide(); 26 | }); 27 | } 28 | 29 | /** 30 | * @param {boolean} [transparent] 31 | */ 32 | show(transparent = false) 33 | { 34 | if (!this.showing) 35 | { 36 | this.showing = true; 37 | this.emitEvent("show"); 38 | } 39 | this._eleBg.style.display = "block"; 40 | 41 | if (transparent) this._eleBg.classList.add("modalbgtransparent"); 42 | else this._eleBg.classList.remove("modalbgtransparent"); 43 | } 44 | 45 | hide() 46 | { 47 | if (this.showing) 48 | { 49 | this.showing = false; 50 | this.emitEvent("hide"); 51 | } 52 | this._eleBg.style.display = "none"; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.github/workflows/jsdocs_master.yml: -------------------------------------------------------------------------------- 1 | name: jsdocs master 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 3 * * *' 7 | 8 | env: 9 | JDOC_APP_ID: "131e893c-eac4-4713-917b-a49fdd10c1c8" 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: checkout cables 17 | uses: actions/checkout@v4 18 | with: 19 | repository: "cables-gl/cables" 20 | ref: master 21 | token: ${{ secrets.undev_token }} 22 | path: "cables/" 23 | - name: checkout cables ui 24 | uses: actions/checkout@v4 25 | with: 26 | repository: "cables-gl/cables_ui" 27 | ref: master 28 | token: ${{ secrets.undev_token }} 29 | path: "cables_ui/" 30 | - name: checkout cables electron 31 | uses: actions/checkout@v4 32 | with: 33 | repository: "cables-gl/cables_electron" 34 | path: "cables_electron/" 35 | ref: master 36 | - name: build jsdoc 37 | run: | 38 | cd jsdoc/ 39 | npm install --no-save 40 | npm run build 41 | - name: Deploy jsdocs to netlify 42 | uses: netlify/actions/cli@master 43 | env: 44 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 45 | NETLIFY_SITE_ID: ${{ env.JDOC_APP_ID }} 46 | with: 47 | args: deploy --dir=jsdoc/dist --prod 48 | secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]' 49 | -------------------------------------------------------------------------------- /shared/client/src/helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Shared helper methods for cables uis 3 | */ 4 | class Helper 5 | { 6 | constructor() 7 | { 8 | this._simpleIdCounter = 0; 9 | } 10 | 11 | /** 12 | * generate a random v4 uuid 13 | * 14 | * @return {string} 15 | */ 16 | uuid() 17 | { 18 | let d = new Date().getTime(); 19 | return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => 20 | { 21 | const r = (d + Math.random() * 16) % 16 | 0; 22 | d = Math.floor(d / 16); 23 | return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); 24 | }); 25 | } 26 | 27 | /** 28 | * checks value for !isNan and isFinite 29 | * 30 | * @param {string} n 31 | * @return {boolean} 32 | */ 33 | isNumeric(n) 34 | { 35 | const nn = parseFloat(n); 36 | return !isNaN(nn) && isFinite(nn); 37 | } 38 | 39 | /** 40 | * generate a simple ID using an internal counter 41 | * 42 | * @return {Number} new id 43 | * @static 44 | */ 45 | simpleId() 46 | { 47 | this._simpleIdCounter++; 48 | return this._simpleIdCounter; 49 | } 50 | 51 | pathLookup(obj, path) 52 | { 53 | const parts = path.split("."); 54 | if (parts.length == 1) 55 | { 56 | return obj[parts[0]]; 57 | } 58 | return this.pathLookup(obj[parts[0]], parts.slice(1).join(".")); 59 | } 60 | 61 | } 62 | export default new Helper(); 63 | -------------------------------------------------------------------------------- /.github/workflows/jsdocs.yml: -------------------------------------------------------------------------------- 1 | name: jsdocs develop 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - develop 8 | paths: 9 | - "shared/**" 10 | - "jsdoc/**" 11 | schedule: 12 | - cron: '0 3 * * *' 13 | 14 | env: 15 | JDOC_APP_ID: "fdb282ef-1a12-4ed8-8859-ac16c5ea3390" 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: checkout cables 23 | uses: actions/checkout@v4 24 | with: 25 | repository: "cables-gl/cables" 26 | ref: develop 27 | token: ${{ secrets.undev_token }} 28 | path: "cables/" 29 | - name: checkout cables ui 30 | uses: actions/checkout@v4 31 | with: 32 | repository: "cables-gl/cables_ui" 33 | ref: develop 34 | token: ${{ secrets.undev_token }} 35 | path: "cables_ui/" 36 | - name: checkout cables electron 37 | uses: actions/checkout@v4 38 | with: 39 | repository: "cables-gl/cables_electron" 40 | path: "cables_electron/" 41 | ref: develop 42 | - name: build jsdoc 43 | run: | 44 | cd jsdoc/ 45 | npm install --no-save 46 | npm run build:dev 47 | - name: Deploy jsdocs to netlify 48 | uses: netlify/actions/cli@master 49 | env: 50 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 51 | NETLIFY_SITE_ID: ${{ env.JDOC_APP_ID }} 52 | with: 53 | args: deploy --dir=jsdoc/dist --prod 54 | secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]' 55 | -------------------------------------------------------------------------------- /jsdoc/template/css/github.css: -------------------------------------------------------------------------------- 1 | /* github markdown */ 2 | .github-markdown { 3 | font-size: 16px; 4 | } 5 | 6 | .github-markdown h1, 7 | .github-markdown h2, 8 | .github-markdown h3, 9 | .github-markdown h4, 10 | .github-markdown h5 { 11 | margin-top: 1em; 12 | margin-bottom: 16px; 13 | font-weight: bold; 14 | padding: 0; 15 | } 16 | 17 | .github-markdown h1:nth-of-type(1) { 18 | margin-top: 0; 19 | } 20 | 21 | .github-markdown h1 { 22 | font-size: 2em; 23 | padding-bottom: 0.3em; 24 | } 25 | 26 | .github-markdown h2 { 27 | font-size: 1.75em; 28 | padding-bottom: 0.3em; 29 | } 30 | 31 | .github-markdown h3 { 32 | font-size: 1.5em; 33 | } 34 | 35 | .github-markdown h4 { 36 | font-size: 1.25em; 37 | } 38 | 39 | .github-markdown h5 { 40 | font-size: 1em; 41 | } 42 | 43 | .github-markdown ul, .github-markdown ol { 44 | padding-left: 2em; 45 | } 46 | 47 | .github-markdown pre > code { 48 | font-size: 0.85em; 49 | } 50 | 51 | .github-markdown table { 52 | margin-bottom: 1em; 53 | border-collapse: collapse; 54 | border-spacing: 0; 55 | } 56 | 57 | .github-markdown table tr { 58 | background-color: #fff; 59 | border-top: 1px solid #ccc; 60 | } 61 | 62 | .github-markdown table th, 63 | .github-markdown table td { 64 | padding: 6px 13px; 65 | border: 1px solid #ddd; 66 | } 67 | 68 | .github-markdown table tr:nth-child(2n) { 69 | background-color: #f8f8f8; 70 | } 71 | 72 | .github-markdown hr { 73 | border-right: 0; 74 | border-bottom: 1px solid #e5e5e5; 75 | border-left: 0; 76 | border-top: 0; 77 | } 78 | 79 | /** badge(.svg) does not have border */ 80 | .github-markdown img:not([src*=".svg"]) { 81 | max-width: 100%; 82 | box-shadow: 1px 1px 1px rgba(0,0,0,0.5); 83 | } 84 | -------------------------------------------------------------------------------- /jsdoc/template/css/search.css: -------------------------------------------------------------------------------- 1 | /* search box */ 2 | .search-box { 3 | position: absolute; 4 | top: 10px; 5 | right: 50px; 6 | padding-right: 8px; 7 | padding-bottom: 10px; 8 | line-height: normal; 9 | font-size: 12px; 10 | } 11 | 12 | .search-box img { 13 | width: 20px; 14 | vertical-align: top; 15 | } 16 | 17 | .search-input { 18 | display: inline; 19 | visibility: hidden; 20 | width: 0; 21 | padding: 2px; 22 | height: 1.5em; 23 | outline: none; 24 | background: transparent; 25 | border: 1px #0af; 26 | border-style: none none solid none; 27 | vertical-align: bottom; 28 | } 29 | 30 | .search-input-edge { 31 | display: none; 32 | width: 1px; 33 | height: 5px; 34 | background-color: #0af; 35 | vertical-align: bottom; 36 | } 37 | 38 | .search-result { 39 | position: absolute; 40 | display: none; 41 | height: 600px; 42 | width: 100%; 43 | padding: 0; 44 | margin-top: 5px; 45 | margin-left: 24px; 46 | background: white; 47 | box-shadow: 1px 1px 4px rgb(0,0,0); 48 | white-space: nowrap; 49 | overflow-y: scroll; 50 | } 51 | 52 | .search-result-import-path { 53 | color: #aaa; 54 | font-size: 12px; 55 | } 56 | 57 | .search-result li { 58 | list-style: none; 59 | padding: 2px 4px; 60 | } 61 | 62 | .search-result li a { 63 | display: block; 64 | } 65 | 66 | .search-result li.selected { 67 | background: #ddd; 68 | } 69 | 70 | .search-result li.search-separator { 71 | background: rgb(37, 138, 175); 72 | color: white; 73 | } 74 | 75 | .search-box.active .search-input { 76 | visibility: visible; 77 | transition: width 0.2s ease-out; 78 | width: 300px; 79 | } 80 | 81 | .search-box.active .search-input-edge { 82 | display: inline-block; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /shared/libs/webaudio-peaks.js: -------------------------------------------------------------------------------- 1 | var webaudioPeaks=function(e){function n(t){if(a[t])return a[t].exports;var r=a[t]={exports:{},id:t,loaded:!1};return e[t].call(r.exports,r,r.exports,n),r.loaded=!0,r.exports}var a={};return n.m=e,n.c=a,n.p="",n(0)}([function(module,exports){"use strict";function findMinMax(e){for(var n,a=1/0,t=-(1/0),r=0,i=e.length;i>r;r++)n=e[r],a>n&&(a=n),n>t&&(t=n);return{min:a,max:t}}function convert(e,n){var a=Math.pow(2,n-1),t=0>e?e*a:e*a-1;return Math.max(-a,Math.min(a-1,t))}function extractPeaks(channel,samplesPerPixel,bits){var i,chanLength=channel.length,numPeaks=Math.ceil(chanLength/samplesPerPixel),start,end,segment,max,min,extrema,peaks=new(eval("Int"+bits+"Array"))(2*numPeaks);for(i=0;numPeaks>i;i++)start=i*samplesPerPixel,end=(i+1)*samplesPerPixel>chanLength?chanLength:(i+1)*samplesPerPixel,segment=channel.subarray(start,end),extrema=findMinMax(segment),min=convert(extrema.min,bits),max=convert(extrema.max,bits),peaks[2*i]=min,peaks[2*i+1]=max;return peaks}function makeMono(channelPeaks,bits){var numChan=channelPeaks.length,weight=1/numChan,numPeaks=channelPeaks[0].length/2,c=0,i=0,min,max,peaks=new(eval("Int"+bits+"Array"))(2*numPeaks);for(i=0;numPeaks>i;i++){for(min=0,max=0,c=0;numChan>c;c++)min+=weight*channelPeaks[c][2*i],max+=weight*channelPeaks[c][2*i+1];peaks[2*i]=min,peaks[2*i+1]=max}return[peaks]}module.exports=function(e,n,a,t,r,i){if(n=n||1e4,i=i||8,a=a||!0,[8,16,32].indexOf(i)<0)throw new Error("Invalid number of bits specified for peaks.");var s,m,h,l,o=e.numberOfChannels,u=[];if("undefined"==typeof e.subarray)for(s=0;o>s;s++)h=e.getChannelData(s),t=t||0,r=r||h.length,l=h.subarray(t,r),u.push(extractPeaks(l,n,i));else t=t||0,r=r||e.length,u.push(extractPeaks(e.subarray(t,r),n,i));return a&&u.length>1&&(u=makeMono(u,i)),m=u[0].length/2,{length:m,data:u,bits:i}}}]); -------------------------------------------------------------------------------- /jsdoc/dev_layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | Home 17 | Manual 18 | Reference 19 | Source 20 | Test 21 | 28 |
29 | 30 | 31 | 32 |
33 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /jsdoc/template/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | USING TEMPLATE!!! 15 |
16 | Home 17 | Manual 18 | Reference 19 | Source 20 | Test 21 | 28 |
29 | 30 | 31 | 32 |
33 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /jsdoc/config/ui.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "../cables_ui/README.md", 3 | "source": "../", 4 | "destination": "dist/ui", 5 | "includes": [ 6 | "^cables_ui/src/.*\\.js$", 7 | "^shared/client/index.js$" 8 | ], 9 | "excludes": [ 10 | "node_modules" 11 | ], 12 | "plugins": [ 13 | { 14 | "name": "@enterthenamehere/esdoc-standard-plugin" 15 | }, 16 | { 17 | "name": "@enterthenamehere/esdoc-type-inference-plugin", 18 | "option": { 19 | "enable": true 20 | } 21 | }, 22 | { 23 | "name": "@enterthenamehere/esdoc-brand-plugin", 24 | "option": { 25 | "title": "cables.gl - editor", 26 | "repository": "https://github.com/cables-gl/cables_ui", 27 | "site": "https://cables.gl", 28 | "author": "https://undev.studio" 29 | } 30 | }, 31 | { 32 | "name": "@enterthenamehere/esdoc-inject-style-plugin", 33 | "option": { 34 | "enable": true, 35 | "styles": [ 36 | "./cables.css" 37 | ] 38 | } 39 | }, 40 | { 41 | "name": "@enterthenamehere/esdoc-importpath-plugin", 42 | "option": { 43 | "stripPackageName": true, 44 | "replaces": [ 45 | { 46 | "from": "^cables_dev/cables_ui/src/", 47 | "to": "./" 48 | }, 49 | { 50 | "from": "^cables_dev/shared/client/index.js", 51 | "to": "cables-shared-client" 52 | } 53 | ] 54 | } 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /shared/libs/mp_camera_utils.js: -------------------------------------------------------------------------------- 1 | (function(){/* 2 | 3 | Copyright The Closure Library Authors. 4 | SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict';var e="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};function f(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b= targetDepth) 35 | { 36 | if (direction === "opened") 37 | { 38 | if (depth === targetDepth) nextElement.style.display = ""; 39 | } 40 | else if (direction === "closed") 41 | { 42 | nextElement.style.display = "none"; 43 | let innerButton = nextElement.querySelector(".toggle"); 44 | if (innerButton && innerButton.classList.contains("opened")) 45 | { 46 | innerButton.classList.remove("opened"); 47 | innerButton.classList.add("closed"); 48 | } 49 | } 50 | } 51 | else 52 | { 53 | break; 54 | } 55 | nextElement = nextElement.nextElementSibling; 56 | } 57 | } 58 | 59 | let buttons = document.querySelectorAll(".test-summary tr.test-interface .toggle"); 60 | for (var i = 0; i < buttons.length; i++) 61 | { 62 | buttons[i].addEventListener("click", toggle); 63 | } 64 | 65 | let topDescribes = document.querySelectorAll(".test-summary tr[data-test-depth=\"0\"]"); 66 | for (var i = 0; i < topDescribes.length; i++) 67 | { 68 | topDescribes[i].style.display = ""; 69 | } 70 | }()); 71 | -------------------------------------------------------------------------------- /start.js: -------------------------------------------------------------------------------- 1 | import concurrently from "concurrently"; 2 | import kill from "tree-kill"; 3 | import fs from "fs"; 4 | 5 | const args = process.argv ? process.argv.slice(2) : []; 6 | const electron = args && args[0] === "standalone"; 7 | 8 | let commands = [ 9 | { 10 | "command": "cd shared && npm run build", 11 | "name": "shared", 12 | "prefixColor": "blue", 13 | "env": { "cables_electron": electron, "NODE_OPTIONS": "--disable-warning=ExperimentalWarning" } 14 | }, 15 | { 16 | "command": "cd cables && npm run watch", 17 | "name": "core", 18 | "prefixColor": "yellow", 19 | "env": { "cables_electron": electron, "NODE_OPTIONS": "--disable-warning=ExperimentalWarning" } 20 | }, 21 | { 22 | "command": "cd cables_ui && npm run watch", 23 | "name": "gui", 24 | "prefixColor": "green", 25 | "env": { "cables_electron": electron, "NODE_OPTIONS": "--disable-warning=ExperimentalWarning" } 26 | }, 27 | ]; 28 | 29 | if (!electron) 30 | { 31 | let apiExists = true; 32 | try 33 | { 34 | if (!fs.statSync("cables_api").isDirectory() || !fs.existsSync("cables_api/src/cables.js")) 35 | { 36 | apiExists = false; 37 | } 38 | } 39 | catch (e) 40 | { 41 | apiExists = false; 42 | } 43 | if (apiExists) 44 | { 45 | commands.splice(2, 0, { 46 | "command": "cd cables_api && npm run start", 47 | "name": "api", 48 | "prefixColor": "cyan", 49 | "env": { "cables_electron": electron, "NODE_OPTIONS": "--disable-warning=ExperimentalWarning" } 50 | }); 51 | commands.splice(2, 0, { 52 | "command": "cd cables_api && npm run start:socketcluster", 53 | "name": "socketcluster", 54 | "prefixColor": "magenta", 55 | "env": { "cables_electron": electron, "NODE_OPTIONS": "--disable-warning=ExperimentalWarning" } 56 | }); 57 | } 58 | else 59 | { 60 | console.warn("FATAL: running `npm run start`, but cables_api/ dir does not exist!"); 61 | console.info("are you trying to run `npm run watch:standalone`?"); 62 | process.exit(1); 63 | } 64 | } 65 | 66 | const { result } = concurrently( 67 | commands, 68 | { 69 | "prefix": "name", 70 | "killOthers": ["failure"], 71 | "restartTries": 3, 72 | }, 73 | ); 74 | 75 | result.then(() => 76 | { 77 | console.log("stopped!"); 78 | kill(process.pid, "SIGHUP"); 79 | }, () => { console.log("WTF!!!!!!"); }).catch((err) => { return console.log("error", err); }); 80 | 81 | process.on("SIGINT", () => 82 | { 83 | kill(process.pid, "SIGHUP"); 84 | }); 85 | -------------------------------------------------------------------------------- /docs/howto_libraries.md: -------------------------------------------------------------------------------- 1 | # How to create/add libraries to cables-core 2 | 3 | ## Internal libraries 4 | If you want to create a library, there are some steps you need to consider: 5 | 6 | 1. Libraries can be found in `src/core/libs` 7 | 2. Files sould be in folders that (by convention) are named after the namespace they export to 8 | 3. Files in subfolders of these will not be built unless they are named `index.js` 9 | 4. Files control their own namespaces, no exports are used (see below) 10 | 5. The resulting filename will have the structure `folder_subfolder.min/max.js`. 11 | 6. If a file is in the `cables/` namespace, the resulting filename will be `filename.js` 12 | 7. Every library in a subfolder (see 3.) needs an `index.js` as the main entry point. 13 | 8. Webpack builds minified and non-minified versions to `build/corelibs/` 14 | 9. use `npm run build` to build the libraries 15 | 10. libraries are copied to `../cables_api/public/js/libs_core/` 16 | 17 | ### Example: 18 | 19 | Input structure: 20 | ```bash 21 | libs 22 | ├── cgl 23 | │ ├── cubemap 24 | │ │ └── index.js 25 | │ ├── light 26 | │ │ ├── createShaders.js 27 | │ │ └── index.js 28 | │ └── functions.js 29 | |── cables 30 | └── vargetset.js 31 | ``` 32 | 33 | Output structure: 34 | ```bash 35 | libs 36 | ├── cgl_cubemap.js 37 | ├── cgl_light.js 38 | ├── cgl_functions.js 39 | ├── vargetset.js 40 | ``` 41 | ## Working with internal libraries 42 | 43 | ### Root level libraries 44 | 1. All libraries have to "provide" and own or use an existing namespace, i.e.: 45 | 46 | `libs/cables/math.js`: 47 | ```javascript 48 | const add = (num1, num2) => num1 + num2; 49 | const sub = (num1, num2) => num1 - num2; 50 | 51 | CABLES.Math = { add: add, sub: sub }; 52 | 53 | // results in CABLES.Math.add(1, 2); 54 | 2. For the above example the exported file would be called `math.max/min.js`. 55 | 3. This also means that these libraries may be dependent on other libraries being loaded alongside or before them (as above with `CABLES`). 56 | 4. Handle with care! 57 | 5. You can use shared imports in subfolders like this: 58 | 59 | `libs/cables/math/index.js`: 60 | ```javascript 61 | import linearAlgebra from "./linearAlgebra" // make sure libs/cables/math/linearAlgebra.js exists! 62 | const add = (num1, num2) => num1 + num2; 63 | const sub = (num1, num2) => num1 - num2; 64 | 65 | CABLES.Math = CABLES.MATH || {}; 66 | CABLES.Math.linearAlgebra = linearAlgebra; 67 | 68 | // results in 69 | // - file: 70 | // - CABLES.Math.linearAlgebra; 71 | 72 | ### Adding libraries to ops 73 | 74 | 1. Click the op in the UI 75 | 2. Go to the `Core Libs` tab 76 | 3. Get your library file from the dropdown, click `Add` 77 | 4. Reload patch 78 | 5. profit 79 | 80 | 81 | -------------------------------------------------------------------------------- /jsdoc/template/css/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /tag_repos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -l 2 | # 3 | # checks out repos at branch, updates, then tags them with the same tag 4 | # 5 | 6 | RED='\033[0;31m' 7 | YELLOW='\033[1;33m' 8 | GREEN='\033[0;32m' 9 | NC='\033[0m' # No Color 10 | 11 | WAIT=10 12 | BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 13 | git fetch || true 14 | 15 | set -e 16 | set -o pipefail 17 | 18 | echo -e "" 19 | echo -e "${GREEN}TAGGING DEV...${NC}" 20 | if [[ `git status --porcelain --untracked-files=no` ]]; then 21 | echo -e "${RED}repository has local changes stash/commit before you tag...${NC}" 22 | exit 1 23 | fi 24 | branch=`git rev-parse --abbrev-ref HEAD` 25 | echo -e "${GREEN}tagging current state of '${branch}' with '${1}'...${NC}" 26 | git tag "${1}" 27 | git push origin tag "${1}" 28 | 29 | echo -e "" 30 | echo -e "${GREEN}TAGGING CORE...${NC}" 31 | cd cables 32 | if [[ `git status --porcelain --untracked-files=no` ]]; then 33 | echo -e "${RED}repository has local changes stash/commit before you tag...${NC}" 34 | exit 1 35 | fi 36 | branch=`git rev-parse --abbrev-ref HEAD` 37 | echo -e "${GREEN}tagging current state of '${branch}' with '${1}'...${NC}" 38 | git tag "${1}" 39 | git push origin tag "${1}" 40 | cd "$BASEDIR" 41 | 42 | if [ -d cables_api ]; then 43 | if [ -f cables_api/package.json ]; then 44 | echo -e "" 45 | echo -e "${GREEN}TAGGING API...${NC}" 46 | if [[ `git status --porcelain --untracked-files=no` ]]; then 47 | echo -e "${RED}repository has local changes stash/commit before you tag...${NC}" 48 | exit 1 49 | fi 50 | branch=`git rev-parse --abbrev-ref HEAD` 51 | echo -e "${GREEN}tagging current state of '${branch}' with '${1}'...${NC}" 52 | cd cables_api 53 | git tag "${1}" 54 | git push origin tag "${1}" 55 | fi 56 | fi 57 | cd "$BASEDIR" 58 | 59 | echo -e "" 60 | echo -e "${GREEN}TAGGING UI...${NC}" 61 | cd cables_ui 62 | if [[ `git status --porcelain --untracked-files=no` ]]; then 63 | echo -e "${RED}repository has local changes stash/commit before you tag...${NC}" 64 | exit 1 65 | fi 66 | branch=`git rev-parse --abbrev-ref HEAD` 67 | echo -e "${GREEN}tagging current state of '${branch}' with '${1}'...${NC}" 68 | git tag "${1}" 69 | git push origin tag "${1}" 70 | cd "$BASEDIR" 71 | 72 | if [ -d cables_electron ]; then 73 | echo -e "" 74 | echo -e "${GREEN}TAGGING ELECTRON...${NC}" 75 | cd cables_electron 76 | if [[ `git status --porcelain --untracked-files=no` ]]; then 77 | echo -e "${RED}repository has local changes stash/commit before you tag...${NC}" 78 | exit 1 79 | fi 80 | branch=`git rev-parse --abbrev-ref HEAD` 81 | echo -e "${GREEN}tagging current state of '${branch}' with '${1}'...${NC}" 82 | git tag "${1}" 83 | git push origin tag "${1}" 84 | fi 85 | cd "$BASEDIR" 86 | 87 | echo -e "" 88 | echo -e "${GREEN}DONE${NC}" 89 | -------------------------------------------------------------------------------- /shared/api/utils/shared_util.js: -------------------------------------------------------------------------------- 1 | import { UtilProvider } from "./util_provider.js"; 2 | 3 | /** 4 | * abstract class for cables utils 5 | * 6 | * @param {UtilProvider} utilProvider 7 | * @abstract 8 | */ 9 | export default class SharedUtil 10 | { 11 | 12 | /** 13 | * 14 | * 15 | */ 16 | constructor(utilProvider, register = true) 17 | { 18 | if (utilProvider) 19 | { 20 | this._utilProvider = utilProvider; 21 | if (register) this._utilProvider.register(this.utilName, this); 22 | } 23 | } 24 | 25 | /** 26 | * @abstract 27 | */ 28 | get utilName() 29 | { 30 | return "not implemented, abstract class"; 31 | } 32 | 33 | /** 34 | * 35 | * @return {*} 36 | * @protected 37 | */ 38 | get _log() 39 | { 40 | return this._utilProvider.getUtil(UtilProvider.LOGGER); 41 | } 42 | 43 | /** 44 | * 45 | * @return {*} 46 | * @protected 47 | */ 48 | get _cables() 49 | { 50 | return this._utilProvider.getUtil(UtilProvider.CABLES); 51 | } 52 | 53 | /** 54 | * 55 | * @return {*} 56 | * @protected 57 | */ 58 | get _opsUtil() 59 | { 60 | return this._utilProvider.getUtil(UtilProvider.OPS_UTIL); 61 | } 62 | 63 | /** 64 | * 65 | * @return {*} 66 | * @protected 67 | */ 68 | get _docsUtil() 69 | { 70 | return this._utilProvider.getUtil(UtilProvider.DOCS_UTIL); 71 | } 72 | 73 | /** 74 | * 75 | * @return {*} 76 | * @protected 77 | */ 78 | get _subPatchOpUtil() 79 | { 80 | return this._utilProvider.getUtil(UtilProvider.SUBPATCH_OP_UTIL); 81 | } 82 | 83 | /** 84 | * 85 | * @return {*} 86 | * @protected 87 | */ 88 | get _teamsUtil() 89 | { 90 | return this._utilProvider.getUtil(UtilProvider.TEAMS_UTIL); 91 | } 92 | 93 | /** 94 | * 95 | * @return {*} 96 | * @protected 97 | */ 98 | get _helperUtil() 99 | { 100 | return this._utilProvider.getUtil(UtilProvider.HELPER_UTIL); 101 | } 102 | 103 | /** 104 | * 105 | * @return {*} 106 | * @protected 107 | */ 108 | get _projectsUtil() 109 | { 110 | return this._utilProvider.getUtil(UtilProvider.PROJECTS_UTIL); 111 | } 112 | 113 | /** 114 | * 115 | * @return {*} 116 | * @protected 117 | */ 118 | get _libsUtil() 119 | { 120 | return this._utilProvider.getUtil(UtilProvider.LIBS_UTIL); 121 | } 122 | 123 | /** 124 | * 125 | * @return {*} 126 | * @protected 127 | */ 128 | get _filesUtil() 129 | { 130 | return this._utilProvider.getUtil(UtilProvider.FILES_UTIL); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /jsdoc/template/css/manual.css: -------------------------------------------------------------------------------- 1 | .github-markdown .manual-toc { 2 | padding-left: 0; 3 | } 4 | 5 | .manual-index .manual-cards { 6 | display: flex; 7 | flex-wrap: wrap; 8 | } 9 | 10 | .manual-index .manual-card-wrap { 11 | width: 280px; 12 | padding: 10px 20px 10px 0; 13 | box-sizing: border-box; 14 | } 15 | 16 | .manual-index .manual-card-wrap > h1 { 17 | margin: 0; 18 | font-size: 1em; 19 | font-weight: 600; 20 | padding: 0.2em 0 0.2em 0.5em; 21 | border-radius: 0.1em 0.1em 0 0; 22 | border: none; 23 | } 24 | 25 | .manual-index .manual-card-wrap > h1 span { 26 | color: #555; 27 | } 28 | 29 | .manual-index .manual-card { 30 | height: 200px; 31 | overflow: hidden; 32 | border: solid 1px rgba(230, 230, 230, 0.84); 33 | border-radius: 0 0 0.1em 0.1em; 34 | padding: 8px; 35 | position: relative; 36 | } 37 | 38 | .manual-index .manual-card > div { 39 | transform: scale(0.4); 40 | transform-origin: 0 0; 41 | width: 250%; 42 | } 43 | 44 | .manual-index .manual-card > a { 45 | position: absolute; 46 | top: 0; 47 | left: 0; 48 | width: 100%; 49 | height: 100%; 50 | background: rgba(210, 210, 210, 0.1); 51 | } 52 | 53 | .manual-index .manual-card > a:hover { 54 | background: none; 55 | } 56 | 57 | .manual-index .manual-badge { 58 | margin: 0; 59 | } 60 | 61 | .manual-index .manual-user-index { 62 | margin-bottom: 1em; 63 | border-bottom: solid 1px #ddd; 64 | } 65 | 66 | .manual-root .navigation { 67 | padding-left: 4px; 68 | margin-top: 4px; 69 | } 70 | 71 | .navigation .manual-toc-root > div { 72 | padding-left: 0.25em; 73 | padding-right: 0.75em; 74 | } 75 | 76 | .github-markdown .manual-toc-title a { 77 | color: inherit; 78 | } 79 | 80 | .manual-breadcrumb-list { 81 | font-size: 0.8em; 82 | margin-bottom: 1em; 83 | } 84 | 85 | .manual-toc-title a:hover { 86 | color: #039BE5; 87 | } 88 | 89 | .manual-toc li { 90 | margin: 0.75em 0; 91 | list-style-type: none; 92 | } 93 | 94 | .navigation .manual-toc [class^="indent-h"] a { 95 | color: #666; 96 | } 97 | 98 | .navigation .manual-toc .indent-h1 a { 99 | color: #555; 100 | font-weight: 600; 101 | display: block; 102 | } 103 | 104 | .manual-toc .indent-h1 { 105 | display: block; 106 | margin: 0.4em 0 0 0.25em; 107 | padding: 0.2em 0 0.2em 0.5em; 108 | border-radius: 0.1em; 109 | } 110 | 111 | .manual-root .navigation .manual-toc li:not(.indent-h1) { 112 | margin-top: 0.5em; 113 | } 114 | 115 | .manual-toc .indent-h2 { 116 | display: none; 117 | margin-left: 1.5em; 118 | } 119 | .manual-toc .indent-h3 { 120 | display: none; 121 | margin-left: 2.5em; 122 | } 123 | .manual-toc .indent-h4 { 124 | display: none; 125 | margin-left: 3.5em; 126 | } 127 | .manual-toc .indent-h5 { 128 | display: none; 129 | margin-left: 4.5em; 130 | } 131 | 132 | .manual-nav li { 133 | margin: 0.75em 0; 134 | } 135 | -------------------------------------------------------------------------------- /jsdoc/template/details.html: -------------------------------------------------------------------------------- 1 |

2 |
3 |

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | version 13 | since 14 | 15 | 16 |

17 | 18 |
19 |
20 |
21 |
22 | 23 |

Override:

24 | 25 |
26 | 27 |
28 |

Return:

29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 |
39 | 40 |
41 |

Emit:

42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |

50 |
51 | 52 |
53 |

Listen:

54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |

62 |
63 | 64 |
65 |

Throw:

66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |

74 |
75 | 76 |

Decorators:

77 | 78 |
79 |

Example:

80 |
81 |
82 |
83 |
84 |
85 | 86 |
87 |

Test:

88 |
    89 |
  • 90 |
91 |
92 | 93 |

See:

94 |

TODO:

95 |
96 | -------------------------------------------------------------------------------- /jsdoc/template/class.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | | variation 6 | | version 7 | | since 8 | | 9 |
10 | 11 |
12 |

13 | 14 |
15 | You can directly use an instance of this class. 16 | 17 |
18 | 19 |

Expression Extends:

20 |

Mixin Extends:

21 |

Extends:

22 |

Direct Subclass:

23 |

Indirect Subclass:

24 |

Implements:

25 |

Indirect Implements:

26 |

Direct Implemented:

27 |

Indirect Implemented:

28 | 29 |
30 |
31 |
32 |

Decorators:

33 | 34 |

See:

35 | 36 |
37 |

Example:

38 |
39 |
40 |
41 |
42 |
43 | 44 |
45 |

Test:

46 |
    47 |
  • 48 |
49 |
50 | 51 |

TODO:

52 |
53 | 54 |

Static Member Summary

55 |

Static Method Summary

56 |

Constructor Summary

57 |

Member Summary

58 |

Method Summary

59 | 60 |

Inherited Summary

61 | 62 |
63 |
64 |
65 |
66 |
67 | -------------------------------------------------------------------------------- /shared/api/utils/shared_teams_util.js: -------------------------------------------------------------------------------- 1 | import SharedUtil from "./shared_util.js"; 2 | import { UtilProvider } from "./util_provider.js"; 3 | 4 | /** 5 | * @abstract 6 | */ 7 | export default class SharedTeamsUtil extends SharedUtil 8 | { 9 | get utilName() 10 | { 11 | return UtilProvider.TEAMS_UTIL; 12 | } 13 | 14 | isPublic(team) 15 | { 16 | if (!team) return false; 17 | return team.visibility === "public"; 18 | } 19 | 20 | 21 | isOwner(user, team) 22 | { 23 | if (!user) return false; 24 | if (!team) return false; 25 | return team.owner._id == user._id; 26 | } 27 | 28 | isMember(user, team) 29 | { 30 | if (!user) return false; 31 | if (!team) return false; 32 | if (!team.members) return false; 33 | if (this.isOwner(user, team)) 34 | { 35 | return true; 36 | } 37 | else 38 | { 39 | return team.members.some((m) => { return String(m._id) === String(user._id); }) || team.membersReadOnly.some((m) => { return String(m._id) === String(user._id); }); 40 | } 41 | } 42 | 43 | 44 | userHasWriteAccess(user, team) 45 | { 46 | if (!user) return false; 47 | if (!team) return false; 48 | if (user.isAdmin) return true; 49 | if (this.isOwner(user, team)) 50 | { 51 | return true; 52 | } 53 | else 54 | { 55 | return team.members.some((m) => { return String(m._id) === String(user._id); }); 56 | } 57 | } 58 | 59 | getFullExtensionName(shortName) 60 | { 61 | let name = shortName; 62 | if (!name.endsWith(".")) name += "."; 63 | if (!name.startsWith("Ops.Extension.")) 64 | { 65 | return "Ops.Extension." + name; 66 | } 67 | return name; 68 | } 69 | 70 | makeReadable(teams) 71 | { 72 | if (!teams) return {}; 73 | if (!(teams instanceof Array)) return this._makeTeamReadable(teams); 74 | 75 | const readables = []; 76 | teams.forEach((p) => 77 | { 78 | const readable = this._makeTeamReadable(p); 79 | readables.push(readable); 80 | }); 81 | return readables; 82 | } 83 | 84 | _makeTeamReadable(team) 85 | { 86 | if (!team) return {}; 87 | const readable = { 88 | "_id": team._id, 89 | "link": team.link, 90 | "name": team.name, 91 | "description": team.description, 92 | "visibility": team.visibility, 93 | "created": team.created, 94 | "updated": team.updated, 95 | "published": team.published 96 | }; 97 | if (team.isMember) readable.isMember = team.isMember; 98 | return readable; 99 | } 100 | 101 | sanitizeShortNameForNamespace(teamName) 102 | { 103 | let name = teamName || ""; 104 | name = name.replace(/[^\x00-\x7F]/g, ""); 105 | name = name.split(" ").join(""); 106 | name = name.replaceAll(/\./g, ""); 107 | name = name.replaceAll("_", ""); 108 | name = name.replaceAll("-", ""); 109 | if (name.match(/^\d/))name = "T" + name; 110 | name = name.substring(0, 16); 111 | return this._helperUtil.capitalizeFirstLetter(name); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /shared/shared_constants.json: -------------------------------------------------------------------------------- 1 | { 2 | "DATE_FORMAT_LOGDATE": "YYYY-MM-DD HH:mm", 3 | "DATE_FORMAT_DISPLAYDATE_DATE": "YYYY-MM-DD HH:mm", 4 | "DATE_FORMAT_DISPLAYDATE_DISPLAY": "MMM D, YYYY [at] HH:mm", 5 | "DATE_FORMAT_TOOLTIPDATE": "MMM D, YYYY [at] HH:mm", 6 | "DATE_FORMAT_DISPLAYDATE_NO_TIME_DATE": "YYYY-MM-DD", 7 | "DATE_FORMAT_DISPLAYDATE_NO_TIME_DISPLAY": "MMM D, YYYY ", 8 | "DATE_FORMAT_RELATIVEDATE_CUTOFF_DAYS": 7, 9 | "DATE_FORMAT_RELATIVEDATE_FULL": "MMM D, YYYY [at] HH:mm", 10 | "IFRAME_OPTIONS_ALLOW": "clipboard-read;clipboard-write;gyroscope;accelerometer;geolocation;camera;microphone;midi;usb;serial;xr-spatial-tracking;web-share;ambient-light-sensor;window-management;bluetooth", 11 | "IFRAME_OPTIONS_SANDBOX": "allow-scripts allow-same-origin allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-presentation allow-downloads allow-popups allow-popups-to-escape-sandbox", 12 | "FILETYPES": { 13 | "image": [ 14 | ".jpg", 15 | ".jpeg", 16 | ".png", 17 | ".gif", 18 | ".webp", 19 | ".avif", 20 | ".jxl" 21 | ], 22 | "binary": [ 23 | ".bin" 24 | ], 25 | "audio": [ 26 | ".mp3", 27 | ".wav", 28 | ".ogg", 29 | ".aac", 30 | ".mid", 31 | ".flac" 32 | ], 33 | "video": [ 34 | ".m4a", 35 | ".mp4", 36 | ".mpg", 37 | ".webm", 38 | ".mkv" 39 | ], 40 | "gltf": [ 41 | ".glb" 42 | ], 43 | "3d raw": [ 44 | ".obj", 45 | ".fbx", 46 | ".3ds", 47 | ".ply", 48 | ".dae", 49 | ".blend", 50 | ".md2", 51 | ".md3", 52 | ".ase" 53 | ], 54 | "JSON": [ 55 | ".json" 56 | ], 57 | "CSS": [ 58 | ".css", 59 | ".scss" 60 | ], 61 | "textfile": [ 62 | ".txt", 63 | ".md" 64 | ], 65 | "pointcloud": [ 66 | ".pc.txt" 67 | ], 68 | "shader": [ 69 | ".frag", 70 | ".vert" 71 | ], 72 | "SVG": [ 73 | ".svg" 74 | ], 75 | "CSV": [ 76 | ".csv" 77 | ], 78 | "XML": [ 79 | ".xml" 80 | ], 81 | "font": [ 82 | ".otf", 83 | ".ttf", 84 | ".woff", 85 | ".woff2" 86 | ], 87 | "mesh sequence": [ 88 | ".seq.zip" 89 | ], 90 | "pointcloud json": [ 91 | ".pc.txt" 92 | ], 93 | "3d json": [ 94 | ".3d.json" 95 | ], 96 | "javascript": [ 97 | ".js", 98 | ".cjs", 99 | ".mjs" 100 | ], 101 | "ar markers": [ 102 | ".iset", 103 | ".fset", 104 | ".fset3" 105 | ] 106 | }, 107 | "EDITABLE_FILETYPES": [ 108 | "textfile", 109 | "CSS", 110 | "javascript", 111 | "XML", 112 | "JSON", 113 | "shader" 114 | ], 115 | "text": { 116 | "en": { 117 | "leave_patch": "Leave Patch" 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /shared/client/src/logger.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | export default class Logger 3 | { 4 | 5 | /** 6 | * @param {any} initiator 7 | * @param {Object} options 8 | */ 9 | constructor(initiator, options) 10 | { 11 | this.initiator = initiator; 12 | this._options = options; 13 | if (!this.initiator) 14 | { 15 | console.error("no log initator given"); 16 | CABLES.logStack(); 17 | } 18 | } 19 | 20 | /** 21 | * @param {string} t 22 | */ 23 | stack(t) 24 | { 25 | console.info("[" + this.initiator + "] ", t); 26 | console.log((new Error()).stack); 27 | } 28 | 29 | /** 30 | * @param {string} t 31 | */ 32 | groupCollapsed(t) 33 | { 34 | if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent) console.log("[" + this.initiator + "]", ...arguments); 35 | 36 | console.groupCollapsed("[" + this.initiator + "] " + t); 37 | } 38 | 39 | /** 40 | * @param {any[][]} t 41 | */ 42 | table(t) 43 | { 44 | console.table(t); 45 | } 46 | 47 | groupEnd() 48 | { 49 | console.groupEnd(); 50 | } 51 | 52 | error() 53 | { 54 | if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 2 }, ...arguments)) || !CABLES.UI) 55 | { 56 | console.error("[" + this.initiator + "]", ...arguments); 57 | } 58 | 59 | if (this._options && this._options.onError) 60 | { 61 | this._options.onError(this.initiator, ...arguments); 62 | // console.log("emitevent onerror..."); 63 | // CABLES.patch.emitEvent("onError", this.initiator, ...arguments); 64 | // CABLES.logErrorConsole("[" + this.initiator + "]", ...arguments); 65 | } 66 | } 67 | 68 | errorGui() 69 | { 70 | if (CABLES.UI) CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 2 }, ...arguments); 71 | } 72 | 73 | warn() 74 | { 75 | if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 1 }, ...arguments)) || !CABLES.logSilent) 76 | console.warn("[" + this.initiator + "]", ...arguments); 77 | } 78 | 79 | verbose() 80 | { 81 | if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent) 82 | console.log("[" + this.initiator + "]", ...arguments); 83 | } 84 | 85 | info() 86 | { 87 | if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent) 88 | console.info("[" + this.initiator + "]", ...arguments); 89 | } 90 | 91 | log() 92 | { 93 | if ((CABLES.UI && CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments)) || !CABLES.logSilent) 94 | console.log("[" + this.initiator + "]", ...arguments); 95 | } 96 | 97 | logGui() 98 | { 99 | if (CABLES.UI) CABLES.UI.logFilter.filterLog({ "initiator": this.initiator, "level": 0 }, ...arguments); 100 | } 101 | 102 | userInteraction(text) 103 | { 104 | // this.log({ "initiator": "userinteraction", "text": text }); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /shared/api/utils/shared_subpatchop_util.js: -------------------------------------------------------------------------------- 1 | import SharedUtil from "./shared_util.js"; 2 | import { UtilProvider } from "./util_provider.js"; 3 | 4 | /** 5 | * @abstract 6 | */ 7 | export default class SharedSubPatchOpUtil extends SharedUtil 8 | { 9 | get utilName() 10 | { 11 | return UtilProvider.SUBPATCH_OP_UTIL; 12 | } 13 | 14 | getSaveSubPatchOpProblems(opName, subPatch) 15 | { 16 | if (!opName) return null; 17 | if (!subPatch || !subPatch.ops) return null; 18 | let problem = null; 19 | for (let i = 0; i < subPatch.ops.length; i++) 20 | { 21 | const subPatchOp = subPatch.ops[i]; 22 | const subPatchOpName = this._opsUtil.getOpNameById(subPatchOp.opId); 23 | const outerNamespace = this._opsUtil.getNamespace(opName); 24 | const opId = this._opsUtil.getOpIdByObjName(opName); 25 | 26 | const opProblem = { 27 | "outerNamespace": outerNamespace, 28 | "outerOpName": opName, 29 | "outerOpId": opId, 30 | "innerOpName": subPatchOpName, 31 | "innerOpId": subPatchOp.opId, 32 | "innerOpInstanceId": subPatchOp.id, 33 | "subPatch": subPatch 34 | }; 35 | const hierarchyProblem = this._opsUtil.getNamespaceHierarchyProblem(opName, subPatchOpName); 36 | if (hierarchyProblem) 37 | { 38 | opProblem.msg = hierarchyProblem; 39 | } 40 | if (opProblem.msg) 41 | { 42 | problem = opProblem; 43 | break; 44 | } 45 | } 46 | return problem; 47 | } 48 | 49 | getOpsUsedInSubPatches(subPatch) 50 | { 51 | let opsInSubPatches = []; 52 | if (!subPatch || !subPatch.ops) return opsInSubPatches; 53 | const v2Bps = subPatch.ops.filter((op) => { return this._opsUtil.isSubPatchOp(op); }); 54 | opsInSubPatches = opsInSubPatches.concat(this._getOpsUsedInSubPatch({ "ops": v2Bps })); 55 | opsInSubPatches = opsInSubPatches.filter((obj, index) => { return opsInSubPatches.findIndex((item) => { return item.opId === obj.opId; }) === index; }); 56 | return opsInSubPatches; 57 | } 58 | 59 | _getOpsUsedInSubPatch(subPatch, currentOp = null) 60 | { 61 | let opsInSubPatch = []; 62 | if (!subPatch) return []; 63 | if (subPatch && subPatch.ops) opsInSubPatch = opsInSubPatch.concat(subPatch.ops); 64 | 65 | const subPatchOps = subPatch.ops.filter((op) => { return this._opsUtil.isSubPatchOp(op); }); 66 | 67 | if (subPatchOps.length > 0) 68 | { 69 | try 70 | { 71 | subPatchOps.forEach((subPatchOp) => 72 | { 73 | if (!currentOp || (currentOp.opId !== subPatchOp.opId)) 74 | { 75 | const attachmentOps = this._opsUtil.getSubPatchOpAttachment(this._opsUtil.getOpNameById(subPatchOp.opId)); 76 | opsInSubPatch = opsInSubPatch.concat(this._getOpsUsedInSubPatch(attachmentOps, subPatchOp)); 77 | } 78 | else 79 | { 80 | this._log.warn("skipping recursive subpatches", subPatchOp.opId, currentOp.opId); 81 | } 82 | }); 83 | } 84 | catch (e) 85 | { 86 | this._log.error(e); 87 | } 88 | 89 | opsInSubPatch = opsInSubPatch.filter((obj, index) => { return opsInSubPatch.findIndex((item) => { return item.opId === obj.opId; }) === index; }); 90 | } 91 | return opsInSubPatch; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cables development environment 2 | 3 | [cables.gl](https://cables.gl) and [cables standalone](https://cables.gl/standalone) are mainly developed by [undev](https://undev.studio/), 4 | with contributions by the [cables community](https://discord.gg/cablesgl) and support by [various other parties and projects](https://cables.gl/support). 5 | 6 | This is the repository that holds the parent directory for cables development. Read up about 7 | setting up everything for you to start contributing to cables in the section on ["Developing Cables"](https://cables.gl/docs/6_1_developing_cables/developing_cables) 8 | of the official cables documentation. 9 | 10 | If you want to learn more about the tools and processes involved, check our ["toolchain"](docs/toolchain.md) guide. 11 | 12 | ## Structure 13 | 14 | cables development is spread across five git-repositories 15 | 16 | ### [cables_dev](https://github.com/cables-gl/cables_dev) 17 | 18 | the current repository is the "root folder" for all cables development, it holds 19 | documentation, helper scripts to set up your environment and keep it up to date. 20 | 21 | it also contains shared code between the different projects and holds npm commands to run watchers 22 | for file changes during development (see below). 23 | 24 | ### [cables](https://github.com/cables-gl/cables) 25 | 26 | the cables repository holds all the core ops of cables, and everything that is needed 27 | to run cables patches (in the editor, but also in exported patches). 28 | 29 | ### [cables_ui](https://github.com/cables-gl/cables_ui) 30 | 31 | cables_ui contains all code that makes up the cables editor, the ui. everything that is needed 32 | to work on patches on cables.gl and in cables standalone lives in this repository. 33 | 34 | ### [cables_electron](https://github.com/cables-gl/cables_electron) 35 | 36 | the repository to bring all of the above together to have a running version of the cables ui 37 | with the cables code and ops. runs (and builds/packs) an electron executable that can be 38 | used to create patches locally, or develop on core and ui features on your local machine. 39 | 40 | ### [cables_extensionops](https://github.com/undev-studio/cables_extensionops) 41 | 42 | a repository containing all the extensions on cables.gl that are not in the core. it is not 43 | needed for local development but will give you a few more ops to work with. 44 | 45 | ## Giving Feedback 46 | 47 | ### Issue Workflow 48 | 49 | - create an issue, pick "Bug report" or "Feature Request" from the templates 50 | - the issue will be assigned a "new" label 51 | - we will check on these issues regularly, add them to a milestone and remove the "new" label 52 | - once we added the feature or fixed the bug in any release (also dev/nightly) we will close the issue 53 | - stable releases will have a changelog with all the closed issues 54 | 55 | ## Appreciation 56 | 57 | Thanks to the [cables community](https://discord.gg/cablesgl) and our [supporters](https://cables.gl/support) for making this possible. If you like this project, think about [supporting it](https://cables.gl/support). 58 | 59 | This project was partly funded through the [NGI0 Entrust Fund](https://nlnet.nl/entrust/), a fund established by [NLnet](https://nlnet.nl/) with financial support 60 | from the European Commission's [Next Generation Internet](https://www.ngi.eu/) programme, under the aegis of [DG Communications Networks](https://commission.europa.eu/about-european-commission/departments-and-executive-agencies/communications-networks-content-and-technology_en), 61 | Content and Technology under grant agreement No 101069594. 62 | 63 | ## More... 64 | - [tools involved](docs/toolchain.md) 65 | - [howto create_new_ops](docs/howto_create_new_ops.md) 66 | - [howto op_new_version](docs/howto_op_new_version.md) 67 | - [howto libraries](docs/howto_libraries.md) 68 | -------------------------------------------------------------------------------- /jsdoc/template/script/search.js: -------------------------------------------------------------------------------- 1 | (function () 2 | { 3 | let searchIndex = window.esdocSearchIndex; 4 | let searchBox = document.querySelector(".search-box"); 5 | let input = document.querySelector(".search-input"); 6 | let result = document.querySelector(".search-result"); 7 | let selectedIndex = -1; 8 | let prevText; 9 | 10 | // active search box and focus when mouse enter on search box. 11 | searchBox.addEventListener("mouseenter", function () 12 | { 13 | searchBox.classList.add("active"); 14 | input.focus(); 15 | }); 16 | 17 | // search with text when key is upped. 18 | input.addEventListener("keyup", function (ev) 19 | { 20 | let text = ev.target.value.toLowerCase(); 21 | if (!text) 22 | { 23 | result.style.display = "none"; 24 | result.innerHTML = ""; 25 | return; 26 | } 27 | 28 | if (text === prevText) return; 29 | prevText = text; 30 | 31 | let html = { "class": [], "method": [], "member": [], "function": [], "variable": [], "typedef": [], "external": [], "file": [], "test": [], "testFile": [] }; 32 | let len = searchIndex.length; 33 | let kind; 34 | for (let i = 0; i < len; i++) 35 | { 36 | let pair = searchIndex[i]; 37 | if (pair[0].indexOf(text) !== -1) 38 | { 39 | kind = pair[3]; 40 | html[kind].push("
  • " + pair[2] + "
  • "); 41 | } 42 | } 43 | 44 | let innerHTML = ""; 45 | for (kind in html) 46 | { 47 | let list = html[kind]; 48 | if (!list.length) continue; 49 | innerHTML += "
  • " + kind + "
  • \n" + list.join("\n"); 50 | } 51 | result.innerHTML = innerHTML; 52 | if (innerHTML) result.style.display = "block"; 53 | selectedIndex = -1; 54 | }); 55 | 56 | // down, up and enter key are pressed, select search result. 57 | input.addEventListener("keydown", function (ev) 58 | { 59 | if (ev.keyCode === 40) 60 | { 61 | // arrow down 62 | var current = result.children[selectedIndex]; 63 | var selected = result.children[selectedIndex + 1]; 64 | if (selected && selected.classList.contains("search-separator")) 65 | { 66 | var selected = result.children[selectedIndex + 2]; 67 | selectedIndex++; 68 | } 69 | 70 | if (selected) 71 | { 72 | if (current) current.classList.remove("selected"); 73 | selectedIndex++; 74 | selected.classList.add("selected"); 75 | } 76 | } 77 | else if (ev.keyCode === 38) 78 | { 79 | // arrow up 80 | var current = result.children[selectedIndex]; 81 | var selected = result.children[selectedIndex - 1]; 82 | if (selected && selected.classList.contains("search-separator")) 83 | { 84 | var selected = result.children[selectedIndex - 2]; 85 | selectedIndex--; 86 | } 87 | 88 | if (selected) 89 | { 90 | if (current) current.classList.remove("selected"); 91 | selectedIndex--; 92 | selected.classList.add("selected"); 93 | } 94 | } 95 | else if (ev.keyCode === 13) 96 | { 97 | // enter 98 | var current = result.children[selectedIndex]; 99 | if (current) 100 | { 101 | let link = current.querySelector("a"); 102 | if (link) location.href = link.href; 103 | } 104 | } 105 | else 106 | { 107 | return; 108 | } 109 | 110 | ev.preventDefault(); 111 | }); 112 | 113 | // select search result when search result is mouse over. 114 | result.addEventListener("mousemove", function (ev) 115 | { 116 | let current = result.children[selectedIndex]; 117 | if (current) current.classList.remove("selected"); 118 | 119 | let li = ev.target; 120 | while (li) 121 | { 122 | if (li.nodeName === "LI") break; 123 | li = li.parentElement; 124 | } 125 | 126 | if (li) 127 | { 128 | selectedIndex = Array.prototype.indexOf.call(result.children, li); 129 | li.classList.add("selected"); 130 | } 131 | }); 132 | 133 | // clear search result when body is clicked. 134 | document.body.addEventListener("click", function (ev) 135 | { 136 | selectedIndex = -1; 137 | result.style.display = "none"; 138 | result.innerHTML = ""; 139 | }); 140 | 141 | }()); 142 | -------------------------------------------------------------------------------- /shared/buildwatcher.js: -------------------------------------------------------------------------------- 1 | import socketClusterClient from "socketcluster-client"; 2 | import sign from "jwt-encode"; 3 | 4 | export default class BuildWatcher 5 | { 6 | 7 | constructor(gulp, cablesConfig, module) 8 | { 9 | this._gulp = gulp; 10 | this._module = module; 11 | this._config = cablesConfig.socketclusterClient || {}; 12 | const serverConfig = cablesConfig.socketclusterServer || {}; 13 | this._socketCluster = { 14 | "active": this._config.enabled && cablesConfig.watchBuildWhenLocal, 15 | "config": serverConfig, 16 | "connected": false, 17 | "socket": null, 18 | "secret": serverConfig.secret 19 | }; 20 | 21 | this._log = { 22 | "info": (...args) => 23 | { 24 | const date = new Date(); 25 | let hours = ("0" + date.getHours()).slice(-2); 26 | let minutes = ("0" + date.getMinutes()).slice(-2); 27 | let seconds = ("0" + date.getMinutes()).slice(-2); 28 | console.log("[" + hours + ":" + minutes + ":" + seconds + "]", "[buildwatcher]", ...args); 29 | } 30 | }; 31 | 32 | } 33 | 34 | watch(glob, watchOptions, task) 35 | { 36 | if (this._socketCluster.active) 37 | { 38 | if (!this._socketCluster.connected) this._connect(); 39 | const _build_watcher = (done) => 40 | { 41 | this._sendBroadcast({ "build": "started", "time": Date.now(), "module": this._module }); 42 | task(() => 43 | { 44 | this._sendBroadcast({ "build": "ended", "time": Date.now(), "module": this._module }); 45 | done(); 46 | }); 47 | }; 48 | this._gulp.watch(glob, watchOptions, _build_watcher); 49 | } 50 | else 51 | { 52 | this._gulp.watch(glob, watchOptions, task); 53 | } 54 | 55 | } 56 | 57 | notify(glob, watchOptions, eventName) 58 | { 59 | if (this._socketCluster.active) 60 | { 61 | if (!this._socketCluster.connected) this._connect(); 62 | const _build_notify = (fileName) => 63 | { 64 | const data = { "build": eventName, "time": Date.now(), "module": this._module }; 65 | let send = true; 66 | const dirSeperator = process && process.platform === "win32" ? "\\" : "/"; 67 | switch (eventName) 68 | { 69 | case "opchange": 70 | if (fileName) 71 | { 72 | data.opName = fileName.split(dirSeperator).reverse().find((pathPart) => { return pathPart && pathPart.startsWith("Ops.") && !pathPart.endsWith(".js"); }); 73 | } 74 | break; 75 | case "attachmentchange": 76 | if (fileName) 77 | { 78 | data.opName = fileName.split(dirSeperator).reverse().find((pathPart) => { return pathPart && pathPart.startsWith("Ops.") && !pathPart.endsWith(".js"); }); 79 | data.attachmentName = fileName.split(dirSeperator).reverse()[0]; 80 | } 81 | break; 82 | } 83 | if (send) this._sendBroadcast(data); 84 | }; 85 | const watcher = this._gulp.watch(glob, watchOptions); 86 | watcher.on("change", _build_notify); 87 | } 88 | } 89 | 90 | _connect() 91 | { 92 | if (this._socketCluster.active && !this._socketCluster.connected) 93 | { 94 | this._socketCluster.socket = socketClusterClient.create({ 95 | "hostname": this._socketCluster.config.interface, 96 | "port": this._socketCluster.config.port, 97 | "secure": false 98 | }); 99 | this._log.info(this._module, "- connected to socketcluster server at", this._socketCluster.config.interface + ":" + this._socketCluster.config.port); 100 | this._socketCluster.connected = true; 101 | } 102 | } 103 | 104 | _sendBroadcast(data) 105 | { 106 | if (!this._socketCluster.active) return; 107 | if (!this._socketCluster.connected) this._connect(); 108 | const channelName = "broadcast"; 109 | if (!this._socketCluster.connected) 110 | { 111 | this._log.info("not broadcasting serverside message - not connected"); 112 | return; 113 | } 114 | 115 | const socketclusterToken = sign({ 116 | "channels": [channelName], 117 | }, this._socketCluster.secret); 118 | 119 | const payload = { 120 | "token": socketclusterToken, 121 | "topic": "notify", 122 | "data": data 123 | }; 124 | this._socketCluster.socket.transmitPublish(channelName, payload); 125 | 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb-base", 3 | "globals": { 4 | "CABLES": true, 5 | "CABLESUILOADER": true, 6 | "CGL": true, 7 | "gui":true, 8 | "CGP":true, 9 | "Ops":true, 10 | "op": true, 11 | "logStartup": true, 12 | "attachments": true, 13 | "GPUShaderStage":true, 14 | "GPUTextureUsage":true, 15 | "GPUBufferUsage":true, 16 | "GPUMapMode":true, 17 | "BroadcastChannel": true, 18 | "document": true, 19 | "window": true, 20 | "navigator": true, 21 | "AudioContext": true, 22 | "XMLHttpRequest": true, 23 | "ace": true, 24 | "iziToast": true, 25 | "vec2": true, 26 | "vec3": true, 27 | "vec4": true, 28 | "mat3": true, 29 | "mat4": true, 30 | "quat": true, 31 | "chroma":true, 32 | "QRCode":true, 33 | "moment":true, 34 | "ColorRick":true, 35 | "introJs": true, 36 | "UndoManager": true, 37 | "Handlebars": true, 38 | "hljs": true, 39 | "loadjs": true, 40 | "pako": true, 41 | "MathParser": true, 42 | "socketClusterClient": true, 43 | "incrementStartup": true, 44 | "mmd": true, 45 | "platformLib": true, 46 | "Sortable": true, 47 | "tinysort":true, 48 | "marked":true 49 | }, 50 | "env": { 51 | "browser": true 52 | }, 53 | "parserOptions": { 54 | "ecmaVersion": "latest" 55 | }, 56 | "rules": { 57 | "no-useless-concat": 0, 58 | "object-property-newline": "error", 59 | "global-require": 1, 60 | "no-compare-neg-zero": 0, 61 | "camelcase": 0, 62 | "class-methods-use-this": 0, 63 | "no-var": 1, 64 | "vars-on-top": 0, 65 | "no-bitwise": 0, 66 | "no-underscore-dangle": 0, 67 | "brace-style": [ 68 | 1, 69 | "allman", 70 | { 71 | "allowSingleLine": true 72 | } 73 | ], 74 | "func-names": 0, 75 | "max-classes-per-file":0, 76 | "max-len": [ 77 | 0, 78 | { 79 | "code": 120, 80 | "tabWidth": 4, 81 | "comments": 300, 82 | "ignoreComments": true 83 | } 84 | ], 85 | "no-param-reassign": 0, 86 | "consistent-return": 0, 87 | "eqeqeq": 0, 88 | "one-var": 0, 89 | "no-unused-vars": 0, 90 | "no-lonely-if": 0, 91 | "no-plusplus": 0, 92 | "indent": [ 93 | 1, 94 | 4 95 | ], 96 | "quotes": [ 97 | 1, 98 | "double" 99 | ], 100 | "quote-props": [ 101 | 1, 102 | "always" 103 | ], 104 | "comma-dangle": 0, 105 | "nonblock-statement-body-position": 0, 106 | "curly": 0, 107 | "object-shorthand": 0, 108 | "prefer-spread": 0, 109 | "no-loop-func": 0, 110 | "no-trailing-spaces": 1, 111 | "space-before-function-paren": 1, 112 | "space-in-parens": 1, 113 | "space-infix-ops": 1, 114 | "keyword-spacing": 1, 115 | "padded-blocks": 0, 116 | "comma-spacing": 1, 117 | "space-before-blocks": 1, 118 | "spaced-comment": 1, 119 | "object-curly-spacing": 1, 120 | "object-curly-newline": 0, 121 | "implicit-arrow-linebreak": 0, 122 | "operator-linebreak": 0, 123 | "array-element-newline": 0, 124 | "function-paren-newline": 0, 125 | "no-self-compare": 0, 126 | "no-case-declarations": 0, 127 | "default-case": 0, 128 | "no-empty": 0, 129 | "no-use-before-define": 0, 130 | "no-multi-assign": 0, 131 | "no-extend-native": 0, 132 | "no-prototype-builtins": 0, 133 | "array-callback-return": 1, 134 | "prefer-destructuring": 0, 135 | "no-restricted-syntax": ["error", "TemplateLiteral"], 136 | "no-restricted-globals": 0, 137 | "no-continue": 0, 138 | "no-console": 1, 139 | "no-else-return": 0, 140 | "no-useless-return":0, 141 | "one-var-declaration-per-line": 0, 142 | "guard-for-in": 0, 143 | "no-new": 0, 144 | "radix": 0, 145 | "no-template-curly-in-string": 0, 146 | "no-useless-constructor": 0, 147 | "import/no-dynamic-require": 0, 148 | "import/no-cycle": [ 149 | 0, 150 | { 151 | "maxDepth": 3 152 | } 153 | ], 154 | "import/no-relative-packages": 0, 155 | "prefer-template": 0, 156 | "prefer-rest-params": 0, 157 | "no-restricted-properties": 0, 158 | "import/prefer-default-export": 0, 159 | "import/no-default-export": 0, 160 | "import/extensions": 0, 161 | "prefer-arrow-callback": 0, 162 | "arrow-body-style": [ "error", "always"], 163 | "new-cap": 0, 164 | "prefer-const": 0, 165 | "padding-line-between-statements": [ 166 | 1, 167 | { 168 | "blankLine": "always", 169 | "prev": "function", 170 | "next": "*" 171 | } 172 | ], 173 | "no-return-await": 0, 174 | "no-multiple-empty-lines": 1, 175 | "no-mixed-operators":0, 176 | "no-inner-declarations":0, 177 | "lines-around-comment": ["error", { "beforeBlockComment": true }], 178 | "lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }], 179 | "newline-per-chained-call": 0 180 | } 181 | 182 | } 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /shared/libs/start-audio-context.js: -------------------------------------------------------------------------------- 1 | /** 2 | * StartAudioContext.js 3 | * @author Yotam Mann 4 | * @license http://opensource.org/licenses/MIT MIT License 5 | * @copyright 2016 Yotam Mann 6 | */ 7 | (function (root, factory) { 8 | if (typeof define === "function" && define.amd) { 9 | define([], factory) 10 | } else if (typeof module === "object" && module.exports) { 11 | module.exports = factory() 12 | } else { 13 | root.StartAudioContext = factory() 14 | } 15 | }(this, function () { 16 | 17 | //TAP LISTENER///////////////////////////////////////////////////////////// 18 | 19 | /** 20 | * @class Listens for non-dragging tap ends on the given element 21 | * @param {Element} element 22 | * @internal 23 | */ 24 | var TapListener = function(element, context){ 25 | 26 | this._dragged = false 27 | 28 | this._element = element 29 | 30 | this._bindedMove = this._moved.bind(this) 31 | this._bindedEnd = this._ended.bind(this, context) 32 | 33 | element.addEventListener("touchstart", this._bindedEnd) 34 | element.addEventListener("touchmove", this._bindedMove) 35 | element.addEventListener("touchend", this._bindedEnd) 36 | element.addEventListener("mouseup", this._bindedEnd) 37 | } 38 | 39 | /** 40 | * drag move event 41 | */ 42 | TapListener.prototype._moved = function(e){ 43 | this._dragged = true 44 | }; 45 | 46 | /** 47 | * tap ended listener 48 | */ 49 | TapListener.prototype._ended = function(context){ 50 | if (!this._dragged){ 51 | startContext(context) 52 | } 53 | this._dragged = false 54 | }; 55 | 56 | /** 57 | * remove all the bound events 58 | */ 59 | TapListener.prototype.dispose = function(){ 60 | this._element.removeEventListener("touchstart", this._bindedEnd) 61 | this._element.removeEventListener("touchmove", this._bindedMove) 62 | this._element.removeEventListener("touchend", this._bindedEnd) 63 | this._element.removeEventListener("mouseup", this._bindedEnd) 64 | this._bindedMove = null 65 | this._bindedEnd = null 66 | this._element = null 67 | }; 68 | 69 | //END TAP LISTENER///////////////////////////////////////////////////////// 70 | 71 | /** 72 | * Plays a silent sound and also invoke the "resume" method 73 | * @param {AudioContext} context 74 | * @private 75 | */ 76 | function startContext(context){ 77 | // this accomplishes the iOS specific requirement 78 | var buffer = context.createBuffer(1, 1, context.sampleRate) 79 | var source = context.createBufferSource() 80 | source.buffer = buffer 81 | source.connect(context.destination) 82 | source.start(0) 83 | 84 | // resume the audio context 85 | if (context.resume){ 86 | context.resume() 87 | } 88 | } 89 | 90 | /** 91 | * Returns true if the audio context is started 92 | * @param {AudioContext} context 93 | * @return {Boolean} 94 | * @private 95 | */ 96 | function isStarted(context){ 97 | return context.state === "running" 98 | } 99 | 100 | /** 101 | * Invokes the callback as soon as the AudioContext 102 | * is started 103 | * @param {AudioContext} context 104 | * @param {Function} callback 105 | */ 106 | function onStarted(context, callback){ 107 | 108 | function checkLoop(){ 109 | if (isStarted(context)){ 110 | callback() 111 | } else { 112 | requestAnimationFrame(checkLoop) 113 | if (context.resume){ 114 | context.resume() 115 | } 116 | } 117 | } 118 | 119 | if (isStarted(context)){ 120 | callback() 121 | } else { 122 | checkLoop() 123 | } 124 | } 125 | 126 | /** 127 | * Add a tap listener to the audio context 128 | * @param {Array|Element|String|jQuery} element 129 | * @param {Array} tapListeners 130 | */ 131 | function bindTapListener(element, tapListeners, context){ 132 | if (Array.isArray(element) || (NodeList && element instanceof NodeList)){ 133 | for (var i = 0; i < element.length; i++){ 134 | bindTapListener(element[i], tapListeners, context) 135 | } 136 | } else if (typeof element === "string"){ 137 | bindTapListener(document.querySelectorAll(element), tapListeners, context) 138 | } else if (element.jquery && typeof element.toArray === "function"){ 139 | bindTapListener(element.toArray(), tapListeners, context) 140 | } else if (Element && element instanceof Element){ 141 | //if it's an element, create a TapListener 142 | var tap = new TapListener(element, context) 143 | tapListeners.push(tap) 144 | } 145 | } 146 | 147 | /** 148 | * @param {AudioContext} context The AudioContext to start. 149 | * @param {Array|String|Element|jQuery=} elements For iOS, the list of elements 150 | * to bind tap event listeners 151 | * which will start the AudioContext. If 152 | * no elements are given, it will bind 153 | * to the document.body. 154 | * @param {Function=} callback The callback to invoke when the AudioContext is started. 155 | * @return {Promise} The promise is invoked when the AudioContext 156 | * is started. 157 | */ 158 | function StartAudioContext(context, elements, callback){ 159 | 160 | //the promise is invoked when the AudioContext is started 161 | var promise = new Promise(function(success) { 162 | onStarted(context, success) 163 | }) 164 | 165 | // The TapListeners bound to the elements 166 | var tapListeners = [] 167 | 168 | // add all the tap listeners 169 | if (!elements){ 170 | elements = document.body 171 | } 172 | bindTapListener(elements, tapListeners, context) 173 | 174 | //dispose all these tap listeners when the context is started 175 | promise.then(function(){ 176 | for (var i = 0; i < tapListeners.length; i++){ 177 | tapListeners[i].dispose() 178 | } 179 | tapListeners = null 180 | 181 | if (callback){ 182 | callback() 183 | } 184 | }) 185 | 186 | return promise 187 | } 188 | 189 | return StartAudioContext 190 | })) -------------------------------------------------------------------------------- /shared/client/src/ele.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @callback whatever 3 | * @param {...any} param 4 | */ 5 | 6 | /** 7 | * @typedef myElement 8 | * @type {HTMLElement} 9 | * @extends {HTMLInputElement} 10 | */ 11 | 12 | /** 13 | * Ele - minimalistic html dom helper 14 | * 15 | * @class 16 | */ 17 | class Ele 18 | { 19 | 20 | /** 21 | * shortcut for document.getElementById(id) 22 | * 23 | * @param {String} id 24 | * @returns {HTMLElement&any} DOM element 25 | */ 26 | byId(id) 27 | { 28 | if (id && id[0] === "#") console.warn("ele.byId should not contain #"); 29 | return document.getElementById(id); 30 | } 31 | 32 | /** 33 | * shortcut for document.querySelector(id) 34 | * 35 | * @param {String} q 36 | * @returns {any} DOM element 37 | */ 38 | byQuery(q) 39 | { 40 | return document.querySelector(q); 41 | } 42 | 43 | /** 44 | * shortcut for document.querySelectorAll(id) 45 | * 46 | * @param {String} q 47 | * @returns {NodeListOf} DOM elements 48 | */ 49 | byQueryAll(q) 50 | { 51 | return document.querySelectorAll(q); 52 | } 53 | 54 | /** 55 | * returns the first element with class 56 | * 57 | * @param {String} name 58 | * @returns {HTMLElement|null|Element} DOM element 59 | */ 60 | byClass(name) 61 | { 62 | if (name && name[0] === ".") console.warn("ele.byClass should not contain ."); 63 | const els = document.getElementsByClassName(name); 64 | if (els.length > 0) return els[0]; 65 | return null; 66 | } 67 | 68 | /** 69 | * returns the all elements with class 70 | * 71 | * @param {String} name 72 | * @returns {HTMLCollectionOf|Array} DOM elements 73 | */ 74 | byClassAll(name) 75 | { 76 | if (name && name[0] === ".") console.warn("ele.byClassAll should not contain ."); 77 | const els = document.getElementsByClassName(name); 78 | if (!els) return []; 79 | return els; 80 | } 81 | 82 | /** 83 | * runs the callback with all elements that have the given class as first argument 84 | * 85 | * @param {String} name 86 | */ 87 | forEachClass(name, cb) 88 | { 89 | if (name && name[0] === ".") console.warn("ele.forEachClass should not contain ."); 90 | 91 | const eles = document.getElementsByClassName(name); 92 | for (let i = 0; i < eles.length; i++) cb(eles[i]); 93 | } 94 | 95 | /** 96 | * returns the currently selected value for a