diff --git a/.gitignore b/.gitignore index 64c8753..db35b6d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,9 @@ public/js/bundle.js images/project_thumbnails .cache dist/ -utilities/getProjectThumbnails/projectThumbnails \ No newline at end of file +utilities/getProjectThumbnails/projectThumbnails +utilities/100DaysScripts/package-lock.json +**/instagram-scraper* +src/assets/images/100Days +utilities/100DaysScripts/*.log +utilities/100DaysScripts/latestScrapes.txt diff --git a/.prettierrc.json b/.prettierrc.json index e1033d7..3cef820 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,7 +1,7 @@ { "trailingComma": "es5", "tabWidth": 4, - "semi": false, + "semi": true, "singleQuote": true, "printWidth": 200 } diff --git a/README.md b/README.md index 745a734..3475a07 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![image of 3D environment with one person in it](docs/images/yorb-2020.png "YORB 2020") +![image of 3D environment with many people moving around](docs/images/winter-show-2020.png "YORB 2020") ## About diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index acec35b..0a6571d 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -6,7 +6,7 @@ If you want to run the code locally, you can do so against either the ITP Yorb s 1. Clone or fork the repository and download a local copy: ```bash - git clone https://github.com/AidanNelson/YORB2020.git + git clone https://github.com/yorb-club/YORB2020.git ``` 2. Navigate into the repository and install dependencies: ```bash @@ -44,14 +44,20 @@ If you want to run the code locally, you can do so against either the ITP Yorb s cd server npm install ``` -4. Change directory again back to the root directory of the project and start the server: +4. Create a new file in the `/server` folder called `.env` and copy the contents of `example.env` into it. Adjust the `PRODUCTION_IP` to reflect your computer's IP address on the local network: + ``` + PROJECT_DATABASE_URL = 'https://itp.nyu.edu/projects/public/projectsJSON_ALL.php?venue_id=164&room_id=1' + PRODUCTION_IP="192.168.0.107" + PRODUCTION_PORT="3000" + ``` +5. Change directory again back to the root directory of the project and start the server: ```bash cd .. npm run start-server ``` -5. In a separate terminal window (in the root directory of the project), start the build system (same as step #4 from above): +6. In a separate terminal window (in the root directory of the project), start the build system (same as step #4 from above): ```bash npm run watch ``` -6. Navigate your browser window to http://localhost:1234. This page should now connect to your backend server at http://localhost:3000. -7. Note that you may need to restart this local development server / build system from time to time to ensure that your changes are being reflected in the browser! \ No newline at end of file +7. Navigate your browser window to http://localhost:1234. This page should now connect to your backend server at http://localhost:3000. +8. Note that you may need to restart this local development server / build system from time to time to ensure that your changes are being reflected in the browser! diff --git a/docs/images/winter-show-2020.png b/docs/images/winter-show-2020.png new file mode 100644 index 0000000..19b6bee Binary files /dev/null and b/docs/images/winter-show-2020.png differ diff --git a/package-lock.json b/package-lock.json index 206e5e9..a5c4b95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6686,9 +6686,9 @@ } }, "three": { - "version": "0.115.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.115.0.tgz", - "integrity": "sha512-mAV2Ky3RdcbdSbR9capI+tKLvRldWYxd4151PZTT/o7+U2jh9Is3a4KmnYwzyUAhB2ZA3pXSgCd2DOY4Tj5kow==" + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.127.0.tgz", + "integrity": "sha512-wtgrn+mhYUbobxT7QN3GPdu3SRpSBQvwY6uOzLChWS7QE//f7paDU/+wlzbg+ngeIvBBqjBHSRuywTh8A99Jng==" }, "through2": { "version": "2.0.5", diff --git a/package.json b/package.json index 3171037..a12ac02 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "mediasoup-client": "^3.6.5", "p5": "^1.0.0", "socket.io-client": "^3.0.3", - "three": "^0.115.0" + "three": "^0.127.0" }, "devDependencies": { "cssnano": "^4.1.10", diff --git a/server/package-lock.json b/server/package-lock.json index 8772e51..7a25b94 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -4,6 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@coolaj86/urequest": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.7.tgz", + "integrity": "sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA==" + }, "@types/body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", @@ -1411,6 +1416,14 @@ "tweetnacl": "~0.14.0" } }, + "ssl-root-cas": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ssl-root-cas/-/ssl-root-cas-1.3.1.tgz", + "integrity": "sha512-KR8J210Wfvjh+iNE9jcQEgbG0VG2713PHreItx6aNCPnkFO8XChz1cJ4iuCGeBj0+8wukLmgHgJqX+O5kRjPkQ==", + "requires": { + "@coolaj86/urequest": "^1.3.6" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", diff --git a/server/package.json b/server/package.json index d79b322..9b2b5ca 100644 --- a/server/package.json +++ b/server/package.json @@ -8,7 +8,8 @@ "dotenv": "^8.2.0", "express": "^4.17.1", "mediasoup": "^3.6.28", - "socket.io": "^3.0.3" + "socket.io": "^3.0.3", + "ssl-root-cas": "^1.3.1" }, "devDependencies": {}, "author": "", diff --git a/server/server.js b/server/server.js index 8a048c6..35654c0 100644 --- a/server/server.js +++ b/server/server.js @@ -31,6 +31,10 @@ const debugModule = require('debug') const mediasoup = require('mediasoup') const fs = require('fs') const https = require('https') +https.globalAgent.options.ca = require('ssl-root-cas').create(); + +process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0 + // HTTP Server setup: // https://stackoverflow.com/questions/27393705/how-to-resolve-a-socket-io-404-not-found-error @@ -208,6 +212,7 @@ main() async function updateProjects() { let url = process.env.PROJECT_DATABASE_URL + console.log('Updating Projects from Database...'); https .get(url, (res) => { diff --git a/src/assets/images/Grass004_1K_Color.jpg b/src/assets/images/Grass004_1K_Color.jpg new file mode 100755 index 0000000..6402978 Binary files /dev/null and b/src/assets/images/Grass004_1K_Color.jpg differ diff --git a/src/assets/images/TexturesCom_WaterPlain0012_1_seamless_S.jpg b/src/assets/images/TexturesCom_WaterPlain0012_1_seamless_S.jpg new file mode 100644 index 0000000..4709857 Binary files /dev/null and b/src/assets/images/TexturesCom_WaterPlain0012_1_seamless_S.jpg differ diff --git a/src/assets/images/screensaver8.mp4 b/src/assets/images/screensaver8.mp4 deleted file mode 100644 index 286edc6..0000000 Binary files a/src/assets/images/screensaver8.mp4 and /dev/null differ diff --git a/src/index.html b/src/index.html index b307780..0eee4eb 100644 --- a/src/index.html +++ b/src/index.html @@ -38,10 +38,9 @@
-
ITP Winter Show 2020
+
ITP Spring Show 2021 Gallery
- Wed Dec 16th, 8-10 p.m. ET
- Thu Dec 17th, 8-10 p.m. ET

+ Remarks – Thurs May 16th, 10 am - 12 pm ET

@@ -50,13 +49,13 @@
CONTROLS:
- ESCAPE.......exit
- WASD.........move
- SPACEBAR.....jump
- MOUSE........look
- C............webcam
- M............mic
- 1............paint + WASD..........move
+ SPACEBAR......jump
+ MOUSE.........look
+ SHIFT+CLICK...interact
+ C.............webcam
+ M.............mic
+ 1.............paint

diff --git a/src/js/yorbControls2.js b/src/js/controls.js similarity index 99% rename from src/js/yorbControls2.js rename to src/js/controls.js index d91a5ec..27c2ff7 100644 --- a/src/js/yorbControls2.js +++ b/src/js/controls.js @@ -1,6 +1,6 @@ import * as THREE from 'three' -export class YorbControls2 { +export class Controls { constructor(scene, camera, renderer) { this.scene = scene this.camera = camera diff --git a/src/js/daysGallery.js b/src/js/daysGallery.js new file mode 100644 index 0000000..3907285 --- /dev/null +++ b/src/js/daysGallery.js @@ -0,0 +1,623 @@ +// 100 days gallery module +// August Luhrs Jan/Feb 2020 + +import { Vector3 } from 'three' +import * as THREE from 'three' +import debugModule from 'debug'; +const log = debugModule('YORB:DaysGallery'); +const Place = require('../../utilities/tools/place.js'); //for generating the canvases along wall + +// why folders in dist is better than one big folder: +// https://medium.com/hceverything/parcel-js-moving-static-resources-to-a-separate-folder-aef63a038cbd +const postsDir = require('../assets/images/100Days/resized/**/*.*'); + +/* postsDir STRUCTURE: + + postsDir = { + classroom: { + account : { + date: { + 'file': { //this is annoying, but it's done by require, not resizeScrapes... + .png:"file.png" + } + } + } + } + } +*/ + +export class DaysGallery { + constructor(scene, camera, mouse) { + this.scene = scene; //where the magic happens + this.gallery = undefined; //holds the canvas objects + //for interaction, from Billy's projectionScreens.js + this.camera = camera; + this.mouse = mouse; + this.shift_down = false; + this.raycaster = new THREE.Raycaster(); + this.selectedPost = null; + let domElement = document.getElementById('scene-container') + domElement.addEventListener('click', (e) => this.onMouseClick(e), false) + window.addEventListener('keydown', (e) => this.onKeyDown(e), false) + window.addEventListener('keyup', (e) => this.onKeyUp(e), false) + //get it goinnn + this.setup(); + } + + /* + ~ * ~ * ~ * MAIN FUNCTION: SETUP + ~ * ~ * ~ * + ~ * ~ * ~ * get posts from resized + ~ * ~ * ~ * sort to get today's post + ~ * ~ * ~ * generate canvases along the walls of the back classrooms + */ + + setup () { + this.galleryTitle(); //place the gallery title on the wall outside the classrooms + let sortedDates = this.sortPosts(); + let todaysPosts = this.getTodaysPosts(sortedDates); + this.generateGallery(todaysPosts); //keeping classroom location info in relevant methods instead of whole class + } + + + /* + ~ * ~ * ~ * SCRAPING AND SORTING + ~ * ~ * ~ * + ~ * ~ * ~ * sort all the posts by date so we can grab today's post and later show by date + */ + + sortPosts () { + let sortedDates = {}; //want this to be same structure as postsDir, but account object holds an array of dates + + //using for/of instead of foreach because ¯\_(ツ)_/¯ https://thecodebarbarian.com/for-vs-for-each-vs-for-in-vs-for-of-in-javascript.html + for (let classroom of Object.keys(postsDir)){ + sortedDates[classroom] = {}; + for (let account of Object.keys(postsDir[classroom])) { + sortedDates[classroom][account] = []; + for (let date of Object.keys(postsDir[classroom][account])) { + sortedDates[classroom][account].push(date); + } + sortedDates[classroom][account] = sortedDates[classroom][account].sort((a, b) => { + return b-a + }); + } + } + return sortedDates; + } + + getTodaysPosts (sortedDates) { + //for now, just getting the first image from the most recent post folder + let todaysPosts = []; + for (let classroom of Object.keys(sortedDates)) { + let posts = []; //array for place function + for (let account of Object.keys(sortedDates[classroom])) { + let post = {}; + post[account] = Object.values(postsDir[classroom][account][sortedDates[classroom][account][0]]['0'])[0]; //get the file from posts dir that matches the first file in the most recent date in sorted, wow that triple 0 at the end is fucked uppp X_X + posts.push(post); + } + let room = {} + room[classroom] = posts; + todaysPosts.push(room); + } + return todaysPosts; + } + + /* + ~ * ~ * ~ * GENERATE GALLERY + ~ * ~ * ~ * + ~ * ~ * ~ * use the Place tool and the posts array + ~ * ~ * ~ * to generate canvases along the three back classrooms + */ + + generateGallery (posts) { + if(posts.length != 0) { //to prevent place tool error of adding non-objects to scene if no gallery files + let galleryGroup = new THREE.Group(); + let galleryGeometry = new THREE.BoxGeometry(1.5, 1.5, .2); + //might want to eventually make this more programatic, but fine for now... + //have to find by key since position in posts can change + let kdPosts = ["","","","","","","","","","","","","","","","",""]; + let kcPosts = ["","","","","","","","","","","","","","",""]; + let paulaPosts = ["","","","","","","","","","","","","","",""]; + for (let section of Object.keys(posts)) { + let sec = Object.keys(posts[section])[0]; + + if(sec == 'kc'){ + kcPosts = posts[section][sec]; + } + if(sec == 'kd'){ + kdPosts = posts[section][sec]; + } + if(sec == 'paula'){ + paulaPosts = posts[section][sec]; + } + } + + //left classroom -- kd 17 incl kd + let kdGroup = new THREE.Group(); + let southGroupKD = kdPosts.slice(0, 3); + let westGroupKD = kdPosts.slice(3, 9); + let northGroupKD = kdPosts.slice(9, 12); + let eastGroupKD = kdPosts.slice(12, kdPosts.length); + + let southWallKD = Place.onWall(new Vector3(41.5, 2, 7.4), new Vector3(47, 2, 7.4), southGroupKD, galleryGeometry, {labelLocation: 'alternating'}); + let westWallKD = Place.onWall(new Vector3(47, 2, 7.4), new Vector3(47, 2, 18.4), westGroupKD, galleryGeometry, {labelLocation: 'alternating'}); + let northWallKD = Place.onWall(new Vector3(47, 2, 18.4), new Vector3(41.5, 2, 18.4), northGroupKD, galleryGeometry, {labelLocation: 'alternating'}); + let eastWallKD = Place.onWall(new Vector3(41.5, 2, 18.4), new Vector3(41.5, 2, 10), eastGroupKD, galleryGeometry, {labelLocation: 'alternating'}); + + kdGroup.add(southWallKD, eastWallKD, northWallKD, westWallKD); + + //right classroom -- kc 15 incl. kc + let kcGroup = new THREE.Group(); + let southGroupKC = kcPosts.slice(0, 3); + let westGroupKC = kcPosts.slice(3, 8); + let northGroupKC = kcPosts.slice(8, 11); + let eastGroupKC = kcPosts.slice(11, kcPosts.length); + + let southWallKC = Place.onWall(new Vector3(41.5, 2, 19.5), new Vector3(47, 2, 19.5), southGroupKC, galleryGeometry, {labelLocation: 'alternating'}); + let westWallKC = Place.onWall(new Vector3(47, 2, 19.5), new Vector3(47, 2, 29.8), westGroupKC, galleryGeometry, {labelLocation: 'alternating'}); + let northWallKC = Place.onWall(new Vector3(47, 2, 29.8), new Vector3(41.5, 2, 29.8), northGroupKC, galleryGeometry, {labelLocation: 'alternating'}); + let eastWallKC = Place.onWall(new Vector3(41.5, 2, 29.8), new Vector3(41.5, 2, 20.9), eastGroupKC, galleryGeometry, {labelLocation: 'alternating'}); + + kcGroup.add(southWallKC, eastWallKC, northWallKC, westWallKC); + + //third classroom -- paula 15 incl. p-- starts from west so last wall(see through) has least num of canvases + let paulaGroup = new THREE.Group(); + let westGroupPaula = paulaPosts.slice(0, 5); //tight squeeze... + let northGroupPaula = paulaPosts.slice(5, 8); + let eastGroupPaula = paulaPosts.slice(8, 13); + let southGroupPaula = paulaPosts.slice(13, paulaPosts.length); + + let westWallPaula = Place.onWall(new Vector3(39.5, 2, 21.9), new Vector3(39.5, 2, 29.8), westGroupPaula, galleryGeometry, {labelLocation: 'alternating'}); + let northWallPaula = Place.onWall(new Vector3(39.5, 2, 29.8), new Vector3(33.7, 2, 29.8), northGroupPaula, galleryGeometry, {labelLocation: 'alternating'}); + let eastWallPaula = Place.onWall(new Vector3(33.7, 2, 29.8), new Vector3(33.7, 2, 21.9), eastGroupPaula, galleryGeometry, {labelLocation: 'alternating'}); + let southWallPaula = Place.onWall(new Vector3(34.8, 2, 21.9), new Vector3(39.5, 2, 21.9), southGroupPaula, galleryGeometry, {labelLocation: 'alternating'}); + + paulaGroup.add(southWallPaula, eastWallPaula, northWallPaula, westWallPaula); + + + //add all groups to scene + galleryGroup.add(kdGroup, kcGroup, paulaGroup) //prob not necessary but w/e + this.scene.add(galleryGroup); + //add to object to maybe reference later if need to update specific canvas? + this.gallery = galleryGroup; + } + } + + /* + ~ * ~ * ~ * INTERACTION + ~ * ~ * ~ * + ~ * ~ * ~ * use Billy's Raycaster Shift-Click interaction from projectionScreens.js + ~ * ~ * ~ * to generate pop up links from Aidan's index.js coordinate modals + */ + + makeInstagramLinkModal(account) { + if (!document.getElementsByClassName('insta-modal')[0]) { + // yorbScene.controls.pause(); + let modalEl = document.createElement('div'); + modalEl.className = 'project-modal'; + modalEl.id = 'insta_modal'; + + let contentEl = document.createElement('div'); + contentEl.className = 'project-modal-content'; + + let link = `https://instagram.com/${account}`; + + let linkEl = document.createElement('a'); + linkEl.href = link; + linkEl.innerHTML = `Check out all of ${account}'s posts on Instagram!`; + linkEl.target = '_blank'; + linkEl.rel = 'noopener noreferrer'; + + let closeButton = document.createElement('button'); + closeButton.addEventListener('click', () => { + modalEl.remove(); + // yorbScene.controls.resume(); + }); + closeButton.innerHTML = 'X'; + + + let spacerDiv = document.createElement('div'); + spacerDiv.innerHTML += "

" + + let spacerDiv2 = document.createElement('div'); + spacerDiv2.innerHTML += "

" + + contentEl.appendChild(closeButton); + contentEl.appendChild(spacerDiv) + contentEl.appendChild(linkEl); + contentEl.appendChild(spacerDiv2) + + modalEl.appendChild(contentEl); + document.body.appendChild(modalEl); + } + } + + checkGalleryCanvasCollisions() { + this.raycaster.setFromCamera(this.mouse, this.camera); + + var intersects = this.raycaster.intersectObject(this.gallery, true); + + // if we have intersections, highlight them + let thresholdDist = 7; + if (intersects.length > 0) { + if (intersects[0].distance < thresholdDist) { + let post = intersects[0].object; + this.selectedPost = post; + } else { + this.selectedPost = null; + } + } else { + this.selectedPost = null; + } + } + + + onMouseClick(e) { + // log('gallery'); + // log(JSON.stringify(this.gallery)); + if(this.gallery != undefined){ //to prevent raycasting to empty gallery error + this.checkGalleryCanvasCollisions(); + if (this.selectedPost && this.shift_down) { + log('selected: ' + JSON.stringify(this.selectedPost.name)); + this.makeInstagramLinkModal(this.selectedPost.name); + this.shift_down = false // reset this because the displayMedia dialog means we lose the onKeyUp event + } + } + } + + onKeyDown(e) { + if (e.keyCode == 16) { + this.shift_down = true + } + } + + onKeyUp(e) { + if (e.keyCode == 16) { + this.shift_down = false + } + } + + /* + ~ * ~ * ~ * TITLE // BANNER + ~ * ~ * ~ * + ~ * ~ * ~ * use YG's yorblet.js/portal.js labels to make a big banner + */ + + galleryTitle () { + const fontJson = require('../assets/fonts/helvetiker_regular_copy.typeface.json') + const font = new THREE.Font(fontJson) + const text = 'X Days of Making' + + const fontGeometry = new THREE.TextBufferGeometry(text, { + font: font, + size: .8, + height: 0.01, + curveSegments: 11, + bevelEnabled: true, + bevelThickness: 0.1, + bevelSize: 0.1, + bevelSegments: 6, + }); + + const fontMaterial1 = new THREE.MeshBasicMaterial({ color: 0x18DD6C, flatShading: true }) + const fontMaterial2 = new THREE.MeshBasicMaterial({ color: 0x1250CC, flatShading: true }) + const fontMesh = new THREE.Mesh(fontGeometry, [fontMaterial1, fontMaterial2]) + + fontMesh.position.set(39, 2.7, 8.5) + fontMesh.lookAt(0, 2.6, 8.5) + this.scene.add(fontMesh) + } + +} + +/* +OLD FUNCTIONS -- I know I could probably just delete these, but I'm a hoarder + +//goes along the classroom wall with a .5 gap between + generateGallery (posts, startPoint) { + let currentSpot = startPoint.left; + let room = 'left'; + let direction = 'west' + //go through all posts (TODO -- might want to not just start at corner) + + + //hacky because rushing -- TODO fix + for (let post of posts) { + if(post.classroom = "kd") { + //add next canvas + this.generateCanvas(post.post, currentSpot); + //update spot by moving clockwise along boundaries towards cardinal directions (doors to room are on east side) + [currentSpot, room, direction] = this.placeClockwise(currentSpot, room, direction); + } + } + + currentSpot = startPoint.right; + room = 'right'; + direction = 'north'; + + //this isn't working because of the wonky getTodaysPosts code -- should start over. + for (let post of posts) { + if(post.classroom == "kc") { + //add next canvas + this.generateCanvas(post.post, currentSpot); + //update spot by moving clockwise along boundaries towards cardinal directions (doors to room are on east side) + [currentSpot, room, direction] = this.placeClockwise(currentSpot, room, direction); + } + } + } + + //for making each individual gallery "canvas" + generateCanvas (post, spot) { + const postTexture = new THREE.TextureLoader().load(post); + const postGeometry = new THREE.BoxGeometry(1,1,1); + const postMaterial = new THREE.MeshBasicMaterial({map: postTexture}); + var postCanvas = new THREE.Mesh(postGeometry, postMaterial); + postCanvas.position.set(spot.x, spot.y, spot.z); + this.scene.add(postCanvas); + } + + placeClockwise (spot, room, direction) { //TODO -- make utility/tool? + let boundaries = { //per classroom + left: { x: [42, 47], + z: [7.4, 18] + }, + right: {x: [42, 47], + z: [19.4, 30] + } + } + + let spacing = .5; + let canvasSize = 1; + let gap = spacing + canvasSize; //putting here for now since will change eventually + + if (direction == 'west') { + if (spot.x + gap > boundaries[room]['x'][1]) { + spot.x += canvasSize; + return this.placeClockwise(spot, room, 'north'); + } else { + spot.x += gap; + return [spot, room, direction]; + } + } else if (direction == 'north') { + if (spot.z + gap > boundaries[room]['z'][1]) { + spot.z += gap; + return this.placeClockwise(spot, room, 'east'); + } else { + spot.z += gap; + return [spot, room, direction]; + } + } else if (direction == 'east') { + if (spot.x - gap < boundaries[room]['x'][0]) { + spot.x -= gap; + return this.placeClockwise(spot, room, 'south'); + } else { + spot.x -= gap; + return [spot, room, direction]; + } + } else if (direction == 'south') { + if (spot.z - gap < boundaries[room]['z'][0] + 2) { //have to account for door + console.log('out of room in : ' + room); + // spot = new Vector3(47, 2, 19); //starting in SW corner of right room + // return this.placeClockwise(spot, 'right', 'north'); // move to right room + } else { + spot.z -= gap; + return [spot, room, direction]; + } + } + } + + testPlace () { + log(postsDir); + // log(postsDir['kd']['100dayscoffee']['20101005']['0']); + let startPoint = new Vector3(42, 2, 7.4); + let endPoint = new Vector3(47, 2, 7.4); + let assets = [ + Object.values(postsDir['kd']['100dayscoffee']['20101005']['0'])[0], + Object.values(postsDir['kd']['100dayscoffee']['20210110']['0'])[0], + Object.values(postsDir['kd']['100dayscoffee']['20101005']['0'])[0] + ] + let geometry = new THREE.BoxGeometry(1.5, 1.5, .2); + let group = Place.onWall(startPoint, endPoint, assets, geometry); + this.scene.add(group); + + let startPoint2 = new Vector3(47, 2, 7.4); + let endPoint2 = new Vector3(47, 2, 18.4); + let assets2 = [ + Object.values(postsDir['kd']['100dayscoffee']['20101005']['0'])[0], + Object.values(postsDir['kd']['100dayscoffee']['20210110']['0'])[0], + Object.values(postsDir['kd']['moving.drawing']['20210118']['0needsResize'])[0], + Object.values(postsDir['kd']['100dayscoffee']['20101005']['0'])[0] + ] + let geometry2 = new THREE.BoxGeometry(1.5, 1.5, .2); + let group2 = Place.onWall(startPoint2, endPoint2, assets2, geometry2); + this.scene.add(group2); + } + + setupTest(){ //just for testing flow, test cube in elevators + + // create the video element from url + // let protoVideo = document.createElement( 'video' ) + // protoVideo.setAttribute('id', 'protoVideo') + // protoVideo.src = "https://scontent-lga3-1.cdninstagram.com/v/t50.2886-16/125367180_843826916364667_3564841615660490363_n.mp4?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=107&_nc_ohc=ImHrFkZ1GVkAX_-q_Ug&oe=5FB6A187&oh=51e86203ab5bf76414f27be6b0110138" + // protoVideo.load() // must call after setting/changing source + // protoVideo.loop = true + // protoVideo.play() + + //loading video into texture + // const protoVideoTexture = new THREE.VideoTexture( document.getElementById('protoVideo')) + + + //loading photo from url + // const protoTexture = new THREE.TextureLoader().load("https://scontent-lga3-1.cdninstagram.com/v/t51.2885-15/e35/125364127_1230307457348884_674277153923938623_n.jpg?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=104&_nc_ohc=twpkkEj5BDAAX_svcnq&tp=18&oh=883284a6619ab238bde83e5cb291814f&oe=5FDD0EEE") + // const protoTexture = new THREE.TextureLoader().load("https://scontent-lga3-1.cdninstagram.com/v/t51.2885-15/e35/55742633_587080988439344_46306404217687397_n.jpg?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=108&_nc_ohc=reT_0gAvwvkAX_6CfaB&tp=1&oh=c6851409abc5764c2824f1c5a71d6921&oe=602083E2") + const protoTexture = new THREE.TextureLoader().load(postsDir['kcconch']['20101005']['0']); + + //set up proto cube + const protoGeometry = new THREE.BoxGeometry(1,1,1) + // const protoMaterial = new THREE.MeshBasicMaterial({map: protoVideoTexture}) + const protoMaterial = new THREE.MeshBasicMaterial({map: protoTexture}) + + var dayProto = new THREE.Mesh(protoGeometry, protoMaterial) + + dayProto.position.set( + 4.5, + .5, + 0.5 + ) + // dayProto.position.set(this.location.center); + + this.scene.add(dayProto) + console.log("PROTOTYPE ADDED") + } + +//go to resized folder and grab the most recent post for each student + getTodaysPosts () { + let allPosts = []; + //sort the account dates so we know the most recent folder + Object.keys(postsDir).forEach(classroom => { + let unsorted = {}; + unsorted[classroom] = {}; + Object.keys(postsDir[classroom]).forEach(account => { + unsorted[classroom][account] = []; + Object.keys(postsDir[classroom][account]).forEach(date => { + unsorted[classroom][account].push(date); + }); + }); + allPosts.push(unsorted); + }); + // console.log(JSON.stringify(allPosts) + '\n\n\n\n\n'); + allPosts.forEach(classroom => { + //this is def weird + console.log(classroom) + Object.keys(classroom).forEach(classObj => { + // console.log(JSON.stringify(classObj) + 'asdfd'); + console.log(classObj); + Object.keys(classroom[classObj]).forEach(account => { + console.log(JSON.stringify(account) + account) + //prob a better way of doing this + // classroom[classObj][account].forEach(dateArray => { + // console.log(dateArray) + // console.log(JSON.stringify(account)) + console.log(classroom[classObj][account]) + // account[dateArray] = account[dateArray].sort((a, b) => { + classroom[classObj][account] = classroom[classObj][account].sort((a, b) => { + + return b-a + }); + // }); + }); + }); + }); + //for now, just getting the first image from the most recent post folder + let todaysPosts = []; + allPosts.forEach(classroom => { + Object.keys(classroom).forEach(classObj => { + console.log(classObj) + console.log(postsDir); + Object.keys(classroom[classObj]).forEach(account => { + console.log(account); + // let accountName = Object.keys(account)[0]; + todaysPosts.push({classroom: classObj, account: account, post: postsDir[classObj][account][classroom[classObj][account][0]]['0']}); + }); + }); + }); + + return todaysPosts; + } + + check () { + log('checking postsDir'); + log(postsDir); + return postsDir; + } + + // async setupGrid(){ + setupGrid(){ + // console.log('set up gallery grid') + // let bDocs = await this.db.asyncFind({type: 'B'}); + // console.log('after db load: ' + bDocs.length) + //laborious way for now + let index = 0; + let xIndex = 0; + let yIndex = 0; + let zIndex = 0; + // for (let b of bDocs){ //for each post b, find photos p + // for (let p of b.links.imgs) { //just photos for now + + for (let b of testLinks){ + // log('b: ' + JSON.stringify(b)); + for (let p of b){ + //loading photo from url + const photoTexture = new THREE.TextureLoader().load(p) + // const photoTexture = new THREE.TextureLoader().load("https://scontent-lga3-1.cdninstagram.com/v/t51.2885-15/e35/55742633_587080988439344_46306404217687397_n.jpg?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=108&_nc_ohc=reT_0gAvwvkAX_6CfaB&tp=1&oh=c6851409abc5764c2824f1c5a71d6921&oe=602083E2") + + //set up photo cube + const photoGeometry = new THREE.BoxGeometry(1,1,1) + const photoMaterial = new THREE.MeshBasicMaterial({map: photoTexture}) + var dayCanvas = new THREE.Mesh(photoGeometry, photoMaterial) + + //go along the grid set up in this.location + if (index % (this.location.width * this.location.depth) == 0) { + yIndex++ + xIndex = 0 + zIndex = 0 + } else if (index % this.location.width == 0) { + xIndex = 0 + zIndex++ + } else { + xIndex++ + } + // log('index: ' + index + " " + xIndex + " " + yIndex + " " + zIndex) + index++ + + + dayCanvas.position.set( + this.location.center.x + xIndex, + this.location.center.y + yIndex, + this.location.center.z + zIndex + ) + + //add to scene + this.scene.add(dayCanvas) + } + } + } + + setupTest(){ //add to the scene + + // create the video element from url + let protoVideo = document.createElement( 'video' ) + protoVideo.setAttribute('id', 'protoVideo') + protoVideo.src = "https://scontent-lga3-1.cdninstagram.com/v/t50.2886-16/125367180_843826916364667_3564841615660490363_n.mp4?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=107&_nc_ohc=ImHrFkZ1GVkAX_-q_Ug&oe=5FB6A187&oh=51e86203ab5bf76414f27be6b0110138" + protoVideo.load() // must call after setting/changing source + protoVideo.loop = true + protoVideo.play() + + //loading video into texture + const protoVideoTexture = new THREE.VideoTexture( document.getElementById('protoVideo')) + + + //loading photo from url + // const protoTexture = new THREE.TextureLoader().load("https://scontent-lga3-1.cdninstagram.com/v/t51.2885-15/e35/125364127_1230307457348884_674277153923938623_n.jpg?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=104&_nc_ohc=twpkkEj5BDAAX_svcnq&tp=18&oh=883284a6619ab238bde83e5cb291814f&oe=5FDD0EEE") + const protoTexture = new THREE.TextureLoader().load("https://scontent-lga3-1.cdninstagram.com/v/t51.2885-15/e35/55742633_587080988439344_46306404217687397_n.jpg?_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_cat=108&_nc_ohc=reT_0gAvwvkAX_6CfaB&tp=1&oh=c6851409abc5764c2824f1c5a71d6921&oe=602083E2") + + //set up proto cube + const protoGeometry = new THREE.BoxGeometry(1,1,1) + const protoMaterial = new THREE.MeshBasicMaterial({map: protoVideoTexture}) + // const protoMaterial = new THREE.MeshBasicMaterial({map: protoTexture}) + + + var dayProto = new THREE.Mesh(protoGeometry, protoMaterial) + + dayProto.position.set( + 4.5, + .5, + 0.5 + ) + // dayProto.position.set(this.location.center); + + this.scene.add(dayProto) + console.log("PROTOTYPE ADDED") + } +} +*/ diff --git a/src/js/index.js b/src/js/index.js index 2dc1a90..c4c9d17 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -8,26 +8,25 @@ //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// // IMPORTS //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// -import 'regenerator-runtime/runtime' +import 'regenerator-runtime/runtime'; -import { Yorb } from './yorb' +import { Yorb } from './yorb'; -const io = require('socket.io-client') -const socketPromise = require('./libs/socket.io-promise').promise +const io = require('socket.io-client'); +const socketPromise = require('./libs/socket.io-promise').promise; // const hostname = window.location.hostname; // import * as config from '../../server/config'; -import * as mediasoup from 'mediasoup-client' -import debugModule from 'debug' +import * as mediasoup from 'mediasoup-client'; +import debugModule from 'debug'; -const log = debugModule('YORB') -const warn = debugModule('YORB:WARN') -const err = debugModule('YORB:ERROR') -const info = debugModule('YORB:INFO') +const log = debugModule('YORB'); +const warn = debugModule('YORB:WARN'); +const err = debugModule('YORB:ERROR'); +const info = debugModule('YORB:INFO'); // load p5 for self view -const p5 = require('p5') - +const p5 = require('p5'); let WEB_SOCKET_SERVER = false; let INSTANCE_PATH = false; @@ -37,8 +36,8 @@ let INSTANCE_PATH = false; // INSTANCE_PATH = '/socket.io' // For running against ITP server -// WEB_SOCKET_SERVER = "https://yorb.itp.io"; -// INSTANCE_PATH = "/socket.io"; +WEB_SOCKET_SERVER = 'https://yorb.itp.io'; +INSTANCE_PATH = '/socket.io'; //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// // Setup Global Variables: @@ -75,10 +74,10 @@ export let mySocketID, projects = [], miniMapSketch, selfViewSketch, - initialized = false + initialized = false; -window.clients = {} // array of connected clients for three.js scene -window.lastPollSyncData = {} +window.clients = {}; // array of connected clients for three.js scene +window.lastPollSyncData = {}; // adding constraints, VIDEO_CONSTRAINTS is video quality levels // localMediaCOnstraints is passed to the getUserMedia object to request a lower video quality than the maximum @@ -88,7 +87,7 @@ const VIDEO_CONSTRAINTS = { qvga: { width: { ideal: 320 }, height: { ideal: 240 } }, vga: { width: { ideal: 640 }, height: { ideal: 480 } }, hd: { width: { ideal: 1280 }, height: { ideal: 720 } }, -} +}; let localMediaConstraints = { audio: true, video: { @@ -96,7 +95,7 @@ let localMediaConstraints = { height: VIDEO_CONSTRAINTS.qvga.height, frameRate: { max: 30 }, }, -} +}; //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// // Start-Up Sequence: @@ -105,54 +104,54 @@ let localMediaConstraints = { // start with user interaction with the DOM so we can auto-play audio/video from // now on... window.onload = async () => { - info('Window loaded.') + info('Window loaded.'); - createScene() - createMiniMap() + createScene(); + createMiniMap(); // create mediasoup Device try { - device = new mediasoup.Device() + device = new mediasoup.Device(); } catch (e) { if (e.name === 'UnsupportedError') { - console.error('browser not supported for video calls') - return + console.error('browser not supported for video calls'); + return; } else { - console.error(e) + console.error(e); } } - await initSocketConnection() + await initSocketConnection(); // use sendBeacon to tell the server we're disconnecting when // the page unloads window.addEventListener('unload', () => { - socket.request('leave', {}) - }) + socket.request('leave', {}); + }); - alert('Allow YORB to access your webcam for the full experience') - await startCamera() + alert('Allow YORB to access your webcam for the full experience'); + await startCamera(); - var startButton = document.getElementById('startButton') - startButton.addEventListener('click', init) -} + var startButton = document.getElementById('startButton'); + startButton.addEventListener('click', init); +}; async function init() { - document.getElementById('overlay').style.visibility = 'hidden' + document.getElementById('overlay').style.visibility = 'hidden'; // only join room after we user has interacted with DOM (to ensure that media elements play) if (!initialized) { - await joinRoom() - sendCameraStreams() - setupControls() - turnGravityOn() - initialized = true + await joinRoom(); + sendCameraStreams(); + setupControls(); + turnGravityOn(); + initialized = true; } } export function shareScreen(screenId) { - info('Starting screenshare to screen with ID ', screenId) - startScreenshare(screenId) + info('Starting screenshare to screen with ID ', screenId); + startScreenshare(screenId); } //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// @@ -163,81 +162,81 @@ export function shareScreen(screenId) { // uses promise to ensure that we receive our so function initSocketConnection() { return new Promise((resolve) => { - info('Initializing socket.io...') + info('Initializing socket.io...'); if (WEB_SOCKET_SERVER && INSTANCE_PATH) { socket = io(WEB_SOCKET_SERVER, { path: INSTANCE_PATH, - }) + }); } else { - socket = io() + socket = io(); } - window.socket = socket - socket.request = socketPromise(socket) + window.socket = socket; + socket.request = socketPromise(socket); - socket.on('connect', () => {}) + socket.on('connect', () => {}); //On connection server sends the client his ID and a list of all keys socket.on('introduction', (_id, _ids) => { // keep a local copy of my ID: - info('My socket ID is: ' + _id) - mySocketID = _id + info('My socket ID is: ' + _id); + mySocketID = _id; // for each existing user, add them as a client and add tracks to their peer connection for (let i = 0; i < _ids.length; i++) { if (_ids[i] != mySocketID) { - addClient(_ids[i]) + addClient(_ids[i]); } } - resolve() - }) + resolve(); + }); // when a new user has entered the server socket.on('newUserConnected', (clientCount, _id, _ids) => { - info(clientCount + ' clients connected') + info(clientCount + ' clients connected'); if (!(_id in clients)) { if (_id != mySocketID) { - info('A new user connected with the id: ' + _id) - addClient(_id) + info('A new user connected with the id: ' + _id); + addClient(_id); } } - }) + }); socket.on('projects', (_projects) => { - info('Received project list from server.') - updateProjects(_projects) - }) + info('Received project list from server.'); + updateProjects(_projects); + }); socket.on('userDisconnected', (_id, _ids) => { // Update the data from the server if (_id in clients) { if (_id == mySocketID) { - info('Uh oh! The server thinks we disconnected!') + info('Uh oh! The server thinks we disconnected!'); } else { - info('A user disconnected with the id: ' + _id) - yorbScene.removeClient(_id) - removeClientDOMElements(_id) - delete clients[_id] + info('A user disconnected with the id: ' + _id); + yorbScene.removeClient(_id); + removeClientDOMElements(_id); + delete clients[_id]; } } - }) + }); // Update when one of the users moves in space socket.on('userPositions', (_clientProps) => { - yorbScene.updateClientPositions(_clientProps) - }) + yorbScene.updateClientPositions(_clientProps); + }); socket.on('projectionScreenUpdate', (_clientProps) => { - yorbScene.updateProjectionScreenOwnership(_clientProps) - }) + yorbScene.updateProjectionScreenOwnership(_clientProps); + }); // listen for projection screen changes: socket.on('releaseProjectionScreen', (data) => { - info('Releasing screen with id', data.screenId) - yorbScene.releaseProjectionScreen(data.screenId) - }) - }) + info('Releasing screen with id', data.screenId); + yorbScene.releaseProjectionScreen(data.screenId); + }); + }); } //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// @@ -246,16 +245,16 @@ function initSocketConnection() { // Adds client object with THREE.js object, DOM video object and and an RTC peer connection for each : async function addClient(_id) { - info('Adding client with id ' + _id) - clients[_id] = {} - yorbScene.addClient(_id) + info('Adding client with id ' + _id); + clients[_id] = {}; + yorbScene.addClient(_id); } function updateProjects(_projects) { - projects = _projects + projects = _projects; if (yorbScene.updateProjects) { - yorbScene.updateProjects(projects) - yorbScene.createHtmlProjectList(projects) + yorbScene.updateProjects(projects); + yorbScene.createHtmlProjectList(projects); } } @@ -264,27 +263,27 @@ function updateProjects(_projects) { //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// function onPlayerMove() { - socket.emit('move', yorbScene.getPlayerPosition()) + socket.emit('move', yorbScene.getPlayerPosition()); } export function hackToRemovePlayerTemporarily() { - info('removing user temporarily') - let pos = [0, 10000, 0] - let rotation = [0, 0, 0] - socket.emit('move', [pos, rotation]) + info('removing user temporarily'); + let pos = [0, 10000, 0]; + let rotation = [0, 0, 0]; + socket.emit('move', [pos, rotation]); for (let _id in clients) { - pauseAllConsumersForPeer(_id) + pauseAllConsumersForPeer(_id); } } function createScene() { // initialize three.js scene - info('Creating three.js scene...') + info('Creating three.js scene...'); - yorbScene = new Yorb(onPlayerMove, clients, mySocketID) + yorbScene = new Yorb(onPlayerMove, clients, mySocketID); - yorbScene.updateProjects(projects) + yorbScene.updateProjects(projects); } //==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==//==// @@ -308,193 +307,242 @@ function setupControls() { (e) => { if (e.keyCode == 67) { // "C" - toggleWebcamVideoPauseState() + toggleWebcamVideoPauseState(); } if (e.keyCode == 77) { // "M" - toggleWebcamAudioPauseState() + toggleWebcamAudioPauseState(); } // if (e.keyCode == 13) { // "Enter" // yorbScene.activateHighlightedProject(); // } if (e.keyCode == 49) { // "1" - yorbScene.swapMaterials() + yorbScene.swapMaterials(); } if (e.keyCode == 80) { // 'p' - console.log(yorbScene.getPlayerPosition()[0]) + let position = yorbScene.getPlayerPosition()[0]; + console.log(position); + let url = `https://yorb.itp.io/?x=${position[0].toFixed(2)}&y=${position[1].toFixed(2)}&z=${position[2].toFixed(2)}`; + console.log('Have your friends meet you here: ', url); + makePositionLinkModal(position); } }, false - ) + ); +} + +function makePositionLinkModal(position) { + // parse project descriptions to render without & etc. + // https://stackoverflow.com/questions/3700326/decode-amp-back-to-in-javascript + + if (!document.getElementsByClassName('project-modal')[0]) { + yorbScene.controls.pause(); + let modalEl = document.createElement('div'); + modalEl.className = 'project-modal'; + modalEl.id = 'link_modal'; + + let contentEl = document.createElement('div'); + contentEl.className = 'project-modal-content'; + + let link = `https://yorb.itp.io/?x=${position[0].toFixed(2)}&y=${position[1].toFixed(2)}&z=${position[2].toFixed(2)}`; + + let linkEl = document.createElement('a'); + linkEl.href = link; + linkEl.innerHTML = 'Have your friends meet you with this link!'; + linkEl.target = '_blank'; + linkEl.rel = 'noopener noreferrer'; + + let closeButton = document.createElement('button'); + closeButton.addEventListener('click', () => { + modalEl.remove(); + yorbScene.controls.resume(); + }); + closeButton.innerHTML = 'X'; + + + let spacerDiv = document.createElement('div'); + spacerDiv.innerHTML += "

" + + let spacerDiv2 = document.createElement('div'); + spacerDiv2.innerHTML += "

" + + contentEl.appendChild(closeButton); + contentEl.appendChild(spacerDiv) + contentEl.appendChild(linkEl); + contentEl.appendChild(spacerDiv2) + + modalEl.appendChild(contentEl); + document.body.appendChild(modalEl); + } } function turnGravityOn() { - yorbScene.controls.turnGravityOn() + yorbScene.controls.turnGravityOn(); } function toggleWebcamImage() { - let webcamImage = document.getElementById('webcam-status-image') + let webcamImage = document.getElementById('webcam-status-image'); if (getCamPausedState()) { - webcamImage.src = require('../assets/images/no-webcam.png') + webcamImage.src = require('../assets/images/no-webcam.png'); } else { - webcamImage.src = require('../assets/images/webcam.png') + webcamImage.src = require('../assets/images/webcam.png'); } } function toggleMicrophoneImage() { - let micImg = document.getElementById('microphone-status-image') + let micImg = document.getElementById('microphone-status-image'); if (getMicPausedState()) { - micImg.src = require('../assets/images/no-mic.png') + micImg.src = require('../assets/images/no-mic.png'); } else { - micImg.src = require('../assets/images/mic.png') + micImg.src = require('../assets/images/mic.png'); } } // adapted (with ❤️) from Dan Shiffman: https://www.youtube.com/watch?v=rNqaw8LT2ZU async function createSelfView() { const s = (sketch) => { - let video - var vScale = 10 - let ballX = 100 - let ballY = 100 - let velocityX = sketch.random(-5, 5) - let velocityY = sketch.random(-5, 5) - let buffer = 10 + let video; + var vScale = 10; + let ballX = 100; + let ballY = 100; + let velocityX = sketch.random(-5, 5); + let velocityY = sketch.random(-5, 5); + let buffer = 10; sketch.setup = () => { - let canvas = sketch.createCanvas(260, 200) - ballX = sketch.width / 2 - ballY = sketch.height / 2 - sketch.pixelDensity(1) - video = sketch.createCapture(sketch.VIDEO) - video.size(sketch.width / vScale, sketch.height / vScale) - video.hide() - sketch.frameRate(5) - sketch.rectMode(sketch.CENTER) - sketch.ellipseMode(sketch.CENTER) - } + let canvas = sketch.createCanvas(260, 200); + ballX = sketch.width / 2; + ballY = sketch.height / 2; + sketch.pixelDensity(1); + video = sketch.createCapture(sketch.VIDEO); + video.size(sketch.width / vScale, sketch.height / vScale); + video.hide(); + sketch.frameRate(5); + sketch.rectMode(sketch.CENTER); + sketch.ellipseMode(sketch.CENTER); + }; sketch.draw = () => { if (webcamVideoPaused) { // bouncing ball easter egg sketch: - sketch.background(10, 10, 200) - ballX += velocityX - ballY += velocityY + sketch.background(10, 10, 200); + ballX += velocityX; + ballY += velocityY; if (ballX >= sketch.width - buffer || ballX <= buffer) { - velocityX = -velocityX + velocityX = -velocityX; } if (ballY >= sketch.height - buffer || ballY <= buffer) { - velocityY = -velocityY + velocityY = -velocityY; } - sketch.fill(240, 120, 0) - sketch.ellipse(ballX, ballY, 10, 10) + sketch.fill(240, 120, 0); + sketch.ellipse(ballX, ballY, 10, 10); } else { - sketch.background(0) - video.loadPixels() + sketch.background(0); + video.loadPixels(); for (var y = 0; y < video.height; y++) { for (var x = 0; x < video.width; x++) { - var index = (video.width - x + 1 + y * video.width) * 4 - var r = video.pixels[index + 0] - var g = video.pixels[index + 1] - var b = video.pixels[index + 2] - var bright = (r + g + b) / 3 - var w = sketch.map(bright, 0, 255, 0, vScale) - sketch.noStroke() - sketch.fill(255) - sketch.rectMode(sketch.CENTER) - sketch.rect(x * vScale, y * vScale, w, w) + var index = (video.width - x + 1 + y * video.width) * 4; + var r = video.pixels[index + 0]; + var g = video.pixels[index + 1]; + var b = video.pixels[index + 2]; + var bright = (r + g + b) / 3; + var w = sketch.map(bright, 0, 255, 0, vScale); + sketch.noStroke(); + sketch.fill(255); + sketch.rectMode(sketch.CENTER); + sketch.rect(x * vScale, y * vScale, w, w); } } } - } - } - selfViewSketch = new p5(s, document.getElementById('self-view-canvas-container')) - selfViewSketch.canvas.style = 'display: block; margin: 0 auto;' + }; + }; + selfViewSketch = new p5(s, document.getElementById('self-view-canvas-container')); + selfViewSketch.canvas.style = 'display: block; margin: 0 auto;'; } // creates minimap p5 sketch async function createMiniMap() { const s = (sketch) => { - let mapImg = false + let mapImg = false; sketch.setup = () => { - mapImg = sketch.loadImage(require('../assets/images/map.png')) - sketch.createCanvas(300, 300) - sketch.pixelDensity(1) - sketch.frameRate(5) - sketch.ellipseMode(sketch.CENTER) - sketch.imageMode(sketch.CENTER) - sketch.angleMode(sketch.RADIANS) - } + mapImg = sketch.loadImage(require('../assets/images/map.png')); + sketch.createCanvas(300, 300); + sketch.pixelDensity(1); + sketch.frameRate(5); + sketch.ellipseMode(sketch.CENTER); + sketch.imageMode(sketch.CENTER); + sketch.angleMode(sketch.RADIANS); + }; sketch.draw = () => { - sketch.background(0) - sketch.push() + sketch.background(0); + sketch.push(); // translate to center of sketch - sketch.translate(sketch.width / 2, sketch.height / 2) + sketch.translate(sketch.width / 2, sketch.height / 2); //translate to 0,0 position of map and make all translations from there - let playerPosition = yorbScene.getPlayerPosition() - let posX = playerPosition[0][0] - let posZ = playerPosition[0][2] + let playerPosition = yorbScene.getPlayerPosition(); + let posX = playerPosition[0][0]; + let posZ = playerPosition[0][2]; // TODO add in direction... // let myDir = playerPosition[1][1]; // camera rotation about Y in Euler Radians // always draw player at center: - sketch.push() - sketch.fill(255, 255, 0) - sketch.ellipse(0, 0, 7, 7) + sketch.push(); + sketch.fill(255, 255, 0); + sketch.ellipse(0, 0, 7, 7); // TODO add in direction... // sketch.fill(0, 0, 255,150); // sketch.rotate(myDir); // sketch.triangle(0, 0, -10, -30, 10, -30); - sketch.pop() + sketch.pop(); - let mappedX = sketch.map(posZ, 0, 32, 0, -225, false) - let mappedY = sketch.map(posX, 0, 32, 0, 225, false) + let mappedX = sketch.map(posZ, 0, 32, 0, -225, false); + let mappedY = sketch.map(posX, 0, 32, 0, 225, false); // allow for map load time without using preload, which seems to mess with things in p5 instance mode... - sketch.push() - sketch.rotate(Math.PI) - sketch.translate(mappedX, mappedY) + sketch.push(); + sketch.rotate(Math.PI); + sketch.translate(mappedX, mappedY); if (mapImg) { - sketch.image(mapImg, 0, 0, mapImg.width, mapImg.height) + sketch.image(mapImg, 0, 0, mapImg.width, mapImg.height); } for (let id in clients) { - let pos = clients[id].group.position // [x,y,z] array of position - let yPos = sketch.map(pos.x, 0, 32, 0, -225, false) - let xPos = sketch.map(pos.z, 0, 32, 0, 225, false) - sketch.push() - sketch.fill(100, 100, 255) - sketch.translate(xPos, yPos) - sketch.ellipse(0, 0, 5, 5) - sketch.pop() + let pos = clients[id].group.position; // [x,y,z] array of position + let yPos = sketch.map(pos.x, 0, 32, 0, -225, false); + let xPos = sketch.map(pos.z, 0, 32, 0, 225, false); + sketch.push(); + sketch.fill(100, 100, 255); + sketch.translate(xPos, yPos); + sketch.ellipse(0, 0, 5, 5); + sketch.pop(); } - sketch.pop() - sketch.pop() - } - } - miniMapSketch = new p5(s, document.getElementById('mini-map-canvas-container')) - miniMapSketch.canvas.style = 'display: block; margin: 0 auto;' + sketch.pop(); + sketch.pop(); + }; + }; + miniMapSketch = new p5(s, document.getElementById('mini-map-canvas-container')); + miniMapSketch.canvas.style = 'display: block; margin: 0 auto;'; } // remove