From 1b6c3c97a226cfee94f9a8b5dae3cf36a81fc61f Mon Sep 17 00:00:00 2001 From: jlu18 Date: Tue, 15 Feb 2022 13:47:21 -0500 Subject: [PATCH] Revert "Revert "Added documentation for missing functions and some clean up"" This reverts commit 99bd8ec877131e853f9d7e9da13d16698ac5ce59. --- .github/workflows/ci.yml | 2 + src/actions/authActions.js | 11 +- src/actions/collectionActions.js | 52 +- src/actions/courseActions.js | 78 ++- src/actions/editorActions.js | 15 +- src/actions/projectActions.js | 36 +- src/actions/referenceExampleActions.js | 11 +- src/actions/sceneActions.js | 159 ++++- src/components/collection/Collection.js | 68 +- src/components/collection/SelectProject.js | 28 +- src/components/courses/Course.js | 37 +- src/components/courses/CourseSelect.js | 20 +- src/components/editor/Editor.js | 18 +- src/components/editor/KeyboardShortcut.js | 21 + src/components/editor/customCompleter.js | 25 +- src/components/layouts/AssetReference.js | 5 + src/components/layouts/Collection.js | 7 +- src/components/layouts/Guided.js | 5 + src/components/layouts/Ide.js | 5 + src/components/layouts/Reference.js | 5 + src/components/layouts/ReferenceExample.js | 5 + .../reference/AssetReferencePage.js | 6 +- src/components/reference/ModelReferenceTab.js | 2 +- src/components/reference/RefExInfo.js | 24 +- src/components/reference/Reference.js | 54 +- src/components/reference/ReferencePage.js | 95 +-- .../reference/TextureReferenceTab.js | 2 +- src/components/structural/Footer.js | 3 + src/components/structural/Models.js | 3 + src/components/structural/Textures.js | 5 +- src/components/structural/View.js | 110 +++- src/components/structural/WelcomeScene.js | 10 + src/components/structural/WelcomeScreen.js | 56 ++ src/components/structural/header/Banner.js | 27 + src/components/structural/header/Header.js | 57 +- src/components/structural/header/MyrTour.js | 15 + .../structural/header/ProjectView.js | 138 ++-- .../structural/header/SceneConfigMenu.js | 154 +++-- src/constants/ActionTypes.js | 15 +- src/constants/LayoutTypes.js | 4 +- src/containers/Collection.js | 5 +- src/containers/Guided.js | 6 +- src/containers/Ide.js | 4 +- src/containers/Reference.js | 6 +- src/containers/ReferenceExample.js | 4 +- src/containers/TextureReference.js | 39 -- src/css/ModelReferencePage.css | 46 -- src/css/TextureReferencePage.css | 46 -- src/index.js | 3 + src/myr/Group.js | 59 +- src/myr/Myr.js | 604 ++++++++++-------- src/myr/modelReference.js | 5 +- src/myr/reference.js | 147 ++--- src/myr/textureReference.js | 5 +- src/myr/tour.js | 4 + src/reducers/collections.js | 12 +- src/reducers/course.js | 7 + src/reducers/editor.js | 18 +- src/reducers/index.js | 10 + src/reducers/project.js | 6 + src/reducers/referenceExample.js | 5 + src/reducers/scene.js | 75 ++- src/reducers/user.js | 6 + src/routes.js | 4 + src/tests/Myr.test.js | 7 - src/utils/AFramePhysics.js | 57 +- src/utils/AframeRegIndicator.js | 24 +- src/utils/WASDPlusControls.js | 9 + src/utils/browserType.js | 3 + 69 files changed, 1628 insertions(+), 991 deletions(-) delete mode 100644 src/containers/TextureReference.js delete mode 100644 src/css/ModelReferencePage.css delete mode 100644 src/css/TextureReferencePage.css diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60ad77cc..a15ea87b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,8 @@ on: [push, pull_request] jobs: ci-checks: runs-on: ubuntu-latest + env: + NODE_OPTIONS: '--max_old_space_size=4096' container: image: node:12.18 diff --git a/src/actions/authActions.js b/src/actions/authActions.js index a77bb285..e11c65ae 100644 --- a/src/actions/authActions.js +++ b/src/actions/authActions.js @@ -5,7 +5,7 @@ import * as types from "../constants/ActionTypes"; * * @param {obj} user User data from the firebase auth obj * - * @returns reducer action obj with type: LOGIN and user obj + * @returns {object} reducer action obj with type: LOGIN and user obj */ export function login(user) { return { type: types.LOGIN, user }; @@ -14,12 +14,19 @@ export function login(user) { /** * Sends a signal to the reducer to logout the current user * - * @returns reducer action obj with type: LOGOUT + * @returns {object} reducer action obj with type: LOGOUT */ export function logout() { return { type: types.LOGOUT }; } +/** + * Sends a signal to the reducer to refresh the token + * + * @param {object} token + * + * @returns {object} reducer action object with type: REFRESH_TOKEN and token obj + */ export function refreshToken(token) { return { type: types.REFRESH_TOKEN, token }; } diff --git a/src/actions/collectionActions.js b/src/actions/collectionActions.js index 1b91b3b4..11d1e83c 100644 --- a/src/actions/collectionActions.js +++ b/src/actions/collectionActions.js @@ -2,12 +2,19 @@ import * as types from "../constants/ActionTypes"; export const collectRef = "/apiv1/collections"; -export function asyncCollections(id) { + +/** + * Fetch the list of the user collection asynchronously + * Use when user login or added a new collection + * + * @param {*} uid A JWT token to authenticate with the backend + */ +export function asyncCollections(uid) { // fetch user's collections return (dispatch) => { - if (id) { + if (uid) { let userCollections = []; - fetch(collectRef, {headers: {"x-access-token": id}}).then((data) => { + fetch(collectRef, {headers: {"x-access-token": uid}}).then((data) => { data.json().then((data) => { data.forEach((doc) => { userCollections.push(doc); @@ -19,10 +26,23 @@ export function asyncCollections(id) { }; } +/** + * Sends a signal to the reducer to sync the user collections + * + * @param {object} payload List of user collections + * + * @returns {object} reducer action obj with type SYNC_COLLECTIONS with payload + */ export function syncCollections(payload) { - return { type: types.SYNC_CLASSES, payload: payload }; + return { type: types.SYNC_COLLECTIONS, payload: payload }; } +/** + * Fetch the specific collection specify by user + * + * @param {string} collectionID Collection id + * @param {*} uid A JWT token to authenticate with the backend + */ export function asyncCollection(collectionID, uid) { // fetch projects in collection return (dispatch) => { @@ -62,13 +82,27 @@ export function asyncCollection(collectionID, uid) { }; } +/** + * Sends a signal to the reducer to load the retrieved collection + * + * @param {object} payload Data of retrieved collection + * + * @returns {object} reducer action obj with type: SYNC_COLLECTION and payload + */ export function syncCollection(payload) { - return { type: types.SYNC_CLASS, payload: payload }; + return { type: types.SYNC_COLLECTION, payload: payload }; } -export function deleteCollection(id, name = null, uid) { +/** + * Sends a signal to the reducer to delete the specific collection of user + * + * @param {string} collectionID Collection ID + * @param {string} name Name of the collection if exists + * @param {*} uid A JWT token to authenticate with the backend + */ +export function deleteCollection(collectionID, name = null, uid) { return (dispatch) => { - name = (name ? name : id); + name = (name ? name : collectionID); if (window.confirm(`Are you sure you want to delete collection "${name}"?`)) { // Delete Document @@ -77,12 +111,14 @@ export function deleteCollection(id, name = null, uid) { console.error(`Error deleting collection ${name}: ${resp.statusText}`); return; } - dispatch({ type: types.DELETE_CLASS, id: id }); + dispatch({ type: types.DELETE_COLLECTION, id: collectionID }); }); } }; } + /** + * Creates a new collection * * @param {string} name The name of the collection to be created * @param {*} uid A JWT token to authenticate with the backend diff --git a/src/actions/courseActions.js b/src/actions/courseActions.js index c52f4eb4..657de158 100644 --- a/src/actions/courseActions.js +++ b/src/actions/courseActions.js @@ -6,7 +6,7 @@ import * as sceneActions from "./sceneActions"; const courseRef = "/apiv1/courses/"; const header = { headers: { "content-type": "application/json" } }; -let noLessons = { +const noLessons = { name: "", id: -1, prompt: "There are no lessons in this course", @@ -19,9 +19,12 @@ const problem = { code: "" }; -/** +/* * Course Actions */ +/** + * Fetch all the courses available + */ export function fetchCourses() { return (dispatch) => { fetch(courseRef, header) @@ -42,10 +45,22 @@ export function fetchCourses() { }; } +/** + * Sends a signal to the reducer to synchronize the courses + * + * @param {*} payload List of courses retrieved + * + * @returns reducer action object with type: SYNC_COURSE and payload + */ export function syncCourses(payload) { return { type: types.SYNC_COURSES, payload: payload }; } +/** + * Fetch specific course + * + * @param {string} courseId id of the course getting + */ export function fetchCourse(courseId) { return (dispatch) => { fetch(courseRef + courseId, header) @@ -84,16 +99,23 @@ export function fetchCourse(courseId) { }; } +/** + * Sends signal to the reducer to load the course retrieved + * + * @param {*} course Data of course retrieved + * @returns {object} reducer action obj with type: LOAD_COURSE and payload + */ export function loadCourse(course) { - return { - type: types.LOAD_COURSE, - payload: course - }; + return { type: types.LOAD_COURSE, payload: course }; } -/** +/* * Lesson Actions */ +/** + * Fetch the lesson that is supplied by the parameter. + * @param {*} json Lesson data + */ export function fetchLesson(json) { return (dispatch) => { dispatch(loadLesson(json)); @@ -106,10 +128,21 @@ export function fetchLesson(json) { } /** - * Frontend disables option if out of bounds + * Sends signal to the reducer to load a new lesson supplied by parameter + * + * @param {object} lesson Lesson data + * @returns reducer action obj with type: LOAD_LESSON and payload: lesson + */ +export function loadLesson(lesson) { + return { type: types.LOAD_LESSON, payload: lesson }; +} + +/** + * Increment the lesson index and load the next lesson. + * Frontend disables option if out of bounds * - * @param {*} currentIndex !!!DESCRIPTION NEEDED!!! - * @param {*} next !!!DESCRIPTION NEEDED!!! + * @param {number} currentIndex current index of the course + * @param {object} next Object of lesson to be load next */ export function nextLesson(currentIndex, next) { return (dispatch) => { @@ -119,10 +152,11 @@ export function nextLesson(currentIndex, next) { } /** - * Frontend disables option if out of bounds + * Decrement the lesson index and load the previous lesson. + * Frontend disables option if out of bounds * - * @param {*} currentIndex !!!DESCRIPTION NEEDED!!! - * @param {*} prev !!!DESCRIPTION NEEDED!!! + * @param {number} currentIndex current index of the course + * @param {object} prev Object of lesson to be load previous */ export function previousLesson(currentIndex, prev) { return (dispatch) => { @@ -131,18 +165,14 @@ export function previousLesson(currentIndex, prev) { }; } +/** + * Sends signal to the reducer to update the current index of the Course + * + * @param {number} newIndex New index to be set + * @returns {object} reducer action obj with type: SET_INDEX and payload: newIndex + */ export function setCurrentIndex(newIndex) { - return { - type: types.SET_INDEX, - payload: newIndex - }; -} - -export function loadLesson(lesson) { - return { - type: types.LOAD_LESSON, - payload: lesson - }; + return { type: types.SET_INDEX, payload: newIndex }; } export default { diff --git a/src/actions/editorActions.js b/src/actions/editorActions.js index fd0842fb..107bc37c 100644 --- a/src/actions/editorActions.js +++ b/src/actions/editorActions.js @@ -8,7 +8,8 @@ const sceneRef = "/apiv1/scenes"; * Sends a signal to the reducer to render the scene * * @param {string} text Text from the Ace Editor component - * + * @param {*} uid A JWT token to authenticate with the backend + * * @returns reducer action obj with action type and text */ export function render(text, uid) { @@ -19,6 +20,7 @@ export function render(text, uid) { * Sends a signal to the reducer to refresh with the given text * * @param {string} text Text from the Ace Editor component + * @param {*} uid A JWT token to authenticate with the backend * * @returns reducer action obj with action type and text */ @@ -36,8 +38,11 @@ export function recover() { } /** - * This does an async fetch to Firebase to grab the scene, then + * This does an async fetch to backend to grab the scene, then * dispatches the necessary functions to update the state. + * + * @param {string} id scene id + * @param {*} uid A JWT token to authenticate with the backend */ export function fetchScene(id, uid = "anon") { return (dispatch) => { // Return a func that dispatches events after async @@ -89,20 +94,14 @@ export function fetchScene(id, uid = "anon") { * * @returns reducer action obj with action type */ - export function updateSavedText(savedText){ return {type: types.EDITOR_UPDATE_SAVEDTEXT, savedText}; } -export function addPassword(payload) { - return { type: types.ADD_PW, payload }; -} - export default { render, refresh, recover, fetchScene, - addPassword, updateSavedText, }; \ No newline at end of file diff --git a/src/actions/projectActions.js b/src/actions/projectActions.js index 5c2a2e16..a0592947 100644 --- a/src/actions/projectActions.js +++ b/src/actions/projectActions.js @@ -3,11 +3,16 @@ import * as types from "../constants/ActionTypes"; const sceneRef = "/apiv1/scenes"; const previewRef = "/apiv1/preview/id"; -export function asyncUserProj(id) { +/** + * Retrieved the list of user scenes + * + * @param {*} uid A JWT token to authenticate with the backend + */ +export function asyncUserProj(uid) { // fetch user's project return (dispatch) => { - if (id) { - fetch(`${sceneRef}/`, {headers: {"x-access-token": id}}).then((response) =>{ + if (uid) { + fetch(`${sceneRef}/`, {headers: {"x-access-token": uid}}).then((response) =>{ if(response.status === 200){ response.json().then((json) =>{ json.forEach(element => { @@ -21,10 +26,21 @@ export function asyncUserProj(id) { }; } + +/** + * Sends signal to the reducer to sync the user project + * + * @param {*} payload list of user projects + * + * @returns reducer action obj with type: SYNC_USER_PROJ wiht payload + */ export function syncUserProj(payload) { return { type: types.SYNC_USER_PROJ, payload: payload }; } +/** + * Fetch a eample scenes from the backend + */ export const asyncExampleProj = () => { // fetch example projects return (dispatch) => { @@ -41,10 +57,24 @@ export const asyncExampleProj = () => { }; }; + +/** + * Sends signal to the reducer to sync the example project + * @param {*} payload List of the example project + * + * @returns reducer action obj with type: SYNC_EXAMP_PROJ with payload + */ export function syncExampleProj(payload) { return { type: types.SYNC_EXAMP_PROJ, payload: payload }; } +/** + * Delete the specify user project + * + * @param {*} uid A JWT token to authenticate with the backend + * @param {string} id Scene id to be deleted + * @param {string} name Name of the scene + */ export function deleteProj(uid, id, name) { return (dispatch) => { if (window.confirm(`Are you sure you want to delete ${name}?`)) { diff --git a/src/actions/referenceExampleActions.js b/src/actions/referenceExampleActions.js index a6a3cb37..29da2623 100644 --- a/src/actions/referenceExampleActions.js +++ b/src/actions/referenceExampleActions.js @@ -25,9 +25,10 @@ const notFound = { }; /** - * Lesson Actions + * Fetch specific example scene from backend. + * On success, load and render the example scene * - * @param {*} funcName !!!DESCRIPTION NEEDED!!! + * @param {string} funcName Name of the example scene to retrieve */ export function fetchReferenceExample(funcName) { return (dispatch) => { @@ -60,6 +61,12 @@ export function fetchReferenceExample(funcName) { }; } +/** + * Sends a signal to the reducer to load the retrieved scene + * + * @param {object} refEx object of data of example scene + * @returns reducer action obj with type: LOAD_REF_EX with payload:refEx + */ export function loadReferenceExample(refEx) { return { type: types.LOAD_REF_EX, diff --git a/src/actions/sceneActions.js b/src/actions/sceneActions.js index 179982c2..04de974a 100644 --- a/src/actions/sceneActions.js +++ b/src/actions/sceneActions.js @@ -1,7 +1,7 @@ import * as types from "../constants/ActionTypes"; /** - * This function registers the scene"s name with Redux + * This function registers the scene's name with Redux * * @param {string} name the name is given by the user or when a scene is loaded * @@ -12,9 +12,9 @@ export function nameScene(name) { } /** - * This function registers the scene's id with Redux + * This function load data of scene to the redux store * - * @param {string} id the id of the loaded scene + * @param {string} data the id of the loaded scene * * @returns a reducer action with type:LOAD_SCENE */ @@ -22,80 +22,197 @@ export function loadScene(data) { return { type: types.LOAD_SCENE, data }; } +/** + * Sends a signal to the reducer to toggle the coordinate floor + * + * @returns {object} reducer action obj with type: TOGGLE_COORD_SKY + */ export function toggleCoordSky() { return { type: types.TOGGLE_COORD_SKY }; } + +/** + * Sends a signal to the reducer to toggle the default light + * + * @returns {object} reducer action obj with type: TOGGLE_DEFAULT_LIGHT + */ export function toggleDefaultLight() { return { type: types.TOGGLE_DEFAULT_LIGHT }; } + +/** + * Sends a signal to the reducer to toggle the floor + * + * @returns {object} reducer action obj with type: TOGGLE_FLOOR + */ +export function toggleFloor() { + return { type: types.TOGGLE_FLOOR }; +} + +/** + * Sends a signal to the reducer to toggle for light to cast shadow + * + * @returns {object} reducer action obj with type: TOGGLE_CAST_SHADOW + */ export function toggleCastShadow() { return { type: types.TOGGLE_CAST_SHADOW }; } +/** + * Sends a signal to the reducer to toggle for light to show light indicator + * + * @returns {object} reducer action obj with type: TOGGLE_LIGHT_INDICATOR + */ export function toggleLightIndicator(){ return {type: types.TOGGLE_LIGHT_INDICATOR}; } +/** + * Sends a signal to the reducer to change the sky color + * + * @param {string} color Color to be change to + * + * @returns {object} reducer action obj with type: CHANGE_SKY_COLOR with color; + */ export function changeSkyColor(color) { return { type: types.CHANGE_SKY_COLOR, color }; } +/** + * Sends a signal to the reducer to change the sky color + * + * @param {string} color Color to be change to + * + * @returns {object} reducer action obj with type: CHANGE_FLOOR_COLOR with color; + */ export function changeFloorColor(color) { return { type: types.CHANGE_FLOOR_COLOR, color }; } -export function changeCamMode(config) { - return { type: types.CHANGE_CAM_MODE, config }; -} - +/** + * Sends a signal to the reducer to change the position of the camera + * + * @param {number} x X Position + * @param {number} y Y Position + * @param {number} z Z Position + * + * @returns {object} reducer action obj with type: SET_CAMERA with x,y,z position + */ export function setCamera(x, y, z) { return { type: types.SET_CAMERA, x, y, z }; } -export function changePerspective() { - return { type: types.CHANGE_PERSPECTIVE }; -} - +/** + * Sends a signal to the reducer to toggle to be view only(hide the editor) or not + * + * @returns {object} reducer action obj with type: CHANGE_VIEW + */ export function changeView() { return { type: types.CHANGE_VIEW }; } -export function toggleFloor() { - return { type: types.TOGGLE_FLOOR }; -} - +/** + * Sends a signal to the reducer to load the settings sends by the + * + * @returns {object} reducer action obj with type: + */ export function loadSettings(payload) { return { type: types.LOAD_SETTINGS, payload }; } -export function changeSettings(payload) { - return { type: types.CHANGE_SETTINGS, payload }; -} - +/** + * Sends a signal to the reducer to reset the settings to default + * + * @returns {object} reducer action obj with type: RESET_SETTINGS + */ export function resetSettings() { return { type: types.RESET_SETTINGS }; } +/** + * Sends a signal to the reducer to add the scene to the collection + * + * @param {string} payload id of collection to add scene to + * + * @returns {object} reducer action obj with type: ADD_COLLECTION with payload + */ export function addCollectionID(payload) { - return { type: types.ADD_CLASSROOM, payload }; + return { type: types.ADD_COLLECTION, payload }; } +/** + * Sends a signal to the reducer to add the scene to the collection + * + * @param {string} payload id of collection to remove scene to + * + * @returns {object} reducer action obj with type: REMOVE_COLLECTION with payload + */ export function removeCollectionID(payload) { - return { type: types.REMOVE_CLASSROOM, payload}; + return { type: types.REMOVE_COLLECTION, payload}; } +/** + * Sends a signal to the reducer to cahnge the description of the scene + * + * @param {string} payload description of the + * + * @returns {object} reducer action obj with type: SET_DESC with payload + */ export function setDesc(payload) { return { type: types.SET_DESC, payload }; } +/** + * Sends a signal to the reducer to change both name and description + * + * @returns {object} reducer action obj with type: + */ export function setNameDesc(payload) { return { type: types.SET_NAME_DESC, payload }; } +/** + * Sends a signal to the reducer to change the speed of movement + * + * @param {number} speed + * @returns + */ export function updateMoveSpeed(speed) { return { type: types.UPDATE_MOVE_SPEED, speed }; } +/* + * Unused functions + */ +/** + * Sends a signal to the reducer to change the settings + * + * @returns {object} reducer action obj with type: CHANGE_SETTINGS with payload + */ +export function changeSettings(payload) { + return { type: types.CHANGE_SETTINGS, payload }; +} + +/** + * Sends a signal to the reducer to change the mode of the camera + * + * @param {*} config New mode to change + * + * @returns {object} reducer action obj with type: CHANGE_CAM_MODE with config + */ +export function changeCamMode(config) { + return { type: types.CHANGE_CAM_MODE, config }; +} + +/** + * Sends a signal to the reducer to change the perspective + * + * @returns {object} reducer action obj with type: CHANGE_PERSPECTIVE + */ +export function changePerspective() { + return { type: types.CHANGE_PERSPECTIVE }; +} + export default { nameScene, loadScene, diff --git a/src/components/collection/Collection.js b/src/components/collection/Collection.js index 6b845615..6d6aadaf 100644 --- a/src/components/collection/Collection.js +++ b/src/components/collection/Collection.js @@ -30,7 +30,7 @@ function getModalStyle() { /** * CSS for modal * - * @param {*} theme !!!DESCRIPTION NEEDED!!! + * @param {*} theme Will use default theme if not provided */ const modelStyles = theme => ({ paper: { @@ -71,6 +71,9 @@ const btnStyle = { } }; +/** + * React Component for Create Collection Modal to Navigate different options for collection + */ class CollectionModal extends Component { constructor(props) { super(props); @@ -82,10 +85,18 @@ class CollectionModal extends Component { }; } + /** + * Move to selected collection page when selected + * @param {object} selectedCollection passed the data of selected collection + */ handleChange = (selectedCollection) => { window.location.assign(window.origin + "/collection/" + selectedCollection.value); } + /** + * Handle when user deleted the selected collection + * @param {object} selectedCollection passed the data of selected collection + */ handleDelete = (selectedCollection) => { let needsToRedirect = (this.props.openCollection === selectedCollection.label); this.props.collectionActions.deleteCollection(selectedCollection.value, selectedCollection.label, this.props.user.uid); @@ -96,29 +107,49 @@ class CollectionModal extends Component { this.props.deleteCallback(selectedCollection.label); } + /** + * Update the state with the collection name user enter in the field + * @param {string} name name of the state to be change + * @param {object} event Event interface when the onChnage event was dispatched + */ handleTextChange = name => event => { this.setState({ [name]: event.target.value, }); }; - handleAddClassToggle = () => { + /** + * Toggle the addOpen state, whether to open "add collection" option + */ + handleAddCollectionToggle = () => { this.setState({ addOpen: !this.state.addOpen }); } - handleOpenClassToggle = () => { + /** + * Toggle the openOpen state, whether to open "open collection" option + */ + handleOpenCollectionToggle = () => { this.setState({ openOpen: !this.state.openOpen }); } - handleDeleteClassToggle = () => { + /** + * Toggle the deleteOpen state, whether to open "delete collection" option + */ + handleDeleteCollectionToggle = () => { this.setState({ deleteOpen: !this.state.deleteOpen }); } + /** + * Close the collection modal and all options + */ handleCloseAll = () => { this.setState({ addOpen: false, openOpen: false, deleteOpen: false }); this.props.handleCollectionClose(); } + /** + * Returns DOM element for modal to select collections + */ selectCollection = () => { const userCollections = this.props.collections.collections; let optionItems = []; @@ -139,6 +170,9 @@ class CollectionModal extends Component { ); } + /** + * Returns DOM element for modal to delete collections + */ deleteCollection = () => { const userCollections = this.props.collections.collections; let optionItems = []; @@ -159,10 +193,13 @@ class CollectionModal extends Component { ); } + /** + * Add new collection to the backend if possible + */ handleSubmit = () => { if (!this.props.user) { window.alert("You must be signed in to create a collection."); - this.handleAddClassToggle(); + this.handleAddCollectionToggle(); } else { let name = this.state.newcollectionID.toLowerCase(); @@ -190,6 +227,9 @@ class CollectionModal extends Component { } } + /** + * Returns DOM element for modal to add collections + */ addClass = () => (
Please enter a new collection name.
@@ -231,13 +271,13 @@ class CollectionModal extends Component {
{ this.handleOpenClassToggle(); }} > + onClick={() => { this.handleOpenCollectionToggle(); }} > storage Open a Collection { this.handleDeleteClassToggle(); }} > + onClick={() => { this.handleDeleteCollectionToggle(); }} > delete Delete a Collection @@ -245,7 +285,7 @@ class CollectionModal extends Component {
{ this.handleAddClassToggle(); }} > + onClick={() => { this.handleAddCollectionToggle(); }} > add_circle Create a Collection @@ -263,11 +303,11 @@ class CollectionModal extends Component { aria-labelledby="simple-modal-title" aria-describedby="simple-modal-description" open={this.state.addOpen} - onClose={this.handleAddClassToggle} > + onClose={this.handleAddCollectionToggle} >
this.handleAddClassToggle()} > + onClick={() => this.handleAddCollectionToggle()} > clear @@ -277,11 +317,11 @@ class CollectionModal extends Component { aria-labelledby="simple-modal-title" aria-describedby="simple-modal-description" open={this.state.openOpen} - onClose={this.handleOpenClassToggle} > + onClose={this.handleOpenCollectionToggle} >
this.handleOpenClassToggle()} > + onClick={() => this.handleOpenCollectionToggle()} > clear @@ -291,11 +331,11 @@ class CollectionModal extends Component { aria-labelledby="simple-modal-title" aria-describedby="simple-modal-description" open={this.state.deleteOpen} - onClose={this.handleDeleteClassToggle} > + onClose={this.handleDeleteCollectionToggle} >
this.handleDeleteClassToggle()} > + onClick={() => this.handleDeleteCollectionToggle()} > clear diff --git a/src/components/collection/SelectProject.js b/src/components/collection/SelectProject.js index eb641c87..e20d43c9 100644 --- a/src/components/collection/SelectProject.js +++ b/src/components/collection/SelectProject.js @@ -23,21 +23,23 @@ const selectStyle = { ...base, zIndex: "999" }), - }; +/** + * React component for selecting list of projects from collection + */ class SelectProject extends PureComponent { + + /** + * Fetch the selected scene when the project is selected from the collection + * @param {Event} projectID ID of the project to be fetch + */ handleChange = (projectID) => { // show warning if there's unsaved change if(this.hasEditorChanged()){ - if((window.confirm("Are you sure you want to continue?\nYou will lose any unsaved work!"))){ - if (this.props.user && this.props.user.uid) { - this.props.editorActions.fetchScene(projectID.value, this.props.uid); - } else { - this.props.editorActions.fetchScene(projectID.value); - } + if(!window.confirm("Are you sure you want to continue?\nYou will lose any unsaved work!")){ + return; } - return; } if (this.props.user && this.props.user.uid) { @@ -47,6 +49,10 @@ class SelectProject extends PureComponent { } } + /** + * Returns wheter the text in the editor match with the savedText + * @returns {boolean} true if savedText is different from text in editor, false otherwise. + */ hasEditorChanged = () => { let text; try { @@ -62,6 +68,9 @@ class SelectProject extends PureComponent { return true; } + /** + * @returns Returns DOM Elements of drop down list of projects + */ renderSelect = () => { let collection = this.props.collection; const placeholder = "Select a project"; @@ -78,6 +87,9 @@ class SelectProject extends PureComponent { ); } + /** + * @returns Render DOM elements of drop down list of collection + */ render() { return (
diff --git a/src/components/courses/Course.js b/src/components/courses/Course.js index 4f3278d3..ebd9b29a 100644 --- a/src/components/courses/Course.js +++ b/src/components/courses/Course.js @@ -6,31 +6,38 @@ import { Tooltip } from "@material-ui/core"; +/** + * React component for navigating the course lessons and displaying lesson name and description + */ class Lesson extends Component { + /** + * Load next lesson. Give a warning if there's any changes in the editor + */ nextLesson = () => { const currentIndex = this.props.courses.currentIndex; const lessons = this.props.course.lessons; - if(this.hasEditorChanged()){ - if (window.confirm("Are you sure you want to continue?\nYou will lose any unsaved work!")) { - this.props.courseActions.nextLesson(currentIndex, lessons[currentIndex + 1]); - } - }else{ - this.props.courseActions.nextLesson(currentIndex, lessons[currentIndex + 1]); + if(this.hasEditorChanged() && !window.confirm("Are you sure you want to continue?\nYou will lose any unsaved work!")){ + return; } + this.props.courseActions.nextLesson(currentIndex, lessons[currentIndex + 1]); } + /** + * Load previous lesson. Give a warning if there's any changes in the editor + */ lastLesson = () => { const currentIndex = this.props.courses.currentIndex; const lessons = this.props.course.lessons; - if(this.hasEditorChanged()){ - if (window.confirm("Are you sure you want to continue?\nYou will lose any unsaved work!")) { - this.props.courseActions.previousLesson(currentIndex, lessons[currentIndex - 1]); - } - }else{ - this.props.courseActions.previousLesson(currentIndex, lessons[currentIndex - 1]); + if(this.hasEditorChanged() && !window.confirm("Are you sure you want to continue?\nYou will lose any unsaved work!")){ + return; } + this.props.courseActions.previousLesson(currentIndex, lessons[currentIndex - 1]); } + /** + * Returns wheter the text in the editor match with the savedText + * @returns {boolean} true if savedText is different from text in editor, false otherwise. + */ hasEditorChanged = () => { let text; try { @@ -47,6 +54,9 @@ class Lesson extends Component { return true; } + /** + * @returns DOM Elements of button that go to previous or + */ renderBtns = () => { const { course, courses } = this.props; let nextValid = courses && courses.currentIndex !== null && course && course.lessons; @@ -84,6 +94,9 @@ class Lesson extends Component { ); } + /** + * @returns Render DOM elements of course lessons + */ render() { return (
diff --git a/src/components/courses/CourseSelect.js b/src/components/courses/CourseSelect.js index e969a27e..af1eb9e8 100644 --- a/src/components/courses/CourseSelect.js +++ b/src/components/courses/CourseSelect.js @@ -31,8 +31,8 @@ function getModalStyle() { /** * CSS for modal - * - * @param {*} theme !!!DESCRIPTION NEEDED!!! + * + * @param {*} theme Will use default theme if not provided */ const modelStyles = theme => ({ paper: { @@ -48,14 +48,15 @@ const modelStyles = theme => ({ } }); +/** + * React component for creating modal listing courses + */ class CourseSelectModal extends Component { - constructor(props) { - super(props); - this.state = { - // open: false - }; - } - + /** + * Helper function to create card for a course modal. + * @param {object} course Object with course info + * @returns {HTMLElement} Card element of course + */ helper = (course) => { if (course) { let id = course._id; @@ -89,6 +90,7 @@ class CourseSelectModal extends Component { /** * Render all of the elements + * @returns {HTMLElement} Course modal with the list of course cards */ render() { const { classes } = this.props; diff --git a/src/components/editor/Editor.js b/src/components/editor/Editor.js index 62ef4a15..d6041d05 100644 --- a/src/components/editor/Editor.js +++ b/src/components/editor/Editor.js @@ -10,9 +10,15 @@ import KeyboardShortcut from "./KeyboardShortcut.js"; import { browserType } from "../../utils/browserType"; /** - * Editor is a React Component that creat the Ace Editor in the DOM. + * Editor is a React Component that create the Ace Editor in the DOM. */ class Editor extends Component { + /** + * Called when the Edtior is unmounting (Being removed from the DOM) + * + * Editor will unmount when MYR enters ViewOnly mode, and we want to render + * whatever the code that's in the editor. + */ componentWillUnmount() { // Updates state in reducer before closing editor const text = window.ace.edit("ace-editor").getSession().getValue(); @@ -22,6 +28,12 @@ class Editor extends Component { this.props.render(text); } + /** + * Called when the Editor is mounted (component has been rendererd to the DOM) + * + * It sets custom completer of MYR API to editor, + * and add listener to check whether user have unsaved changes. + */ componentDidMount() { try { // eslint-disable-next-line @@ -47,6 +59,10 @@ class Editor extends Component { }); } + /** + * Called when the editor is loaded. + * It sets options to set the maximum error editor accepts and set the EMCAScript version to 6 + */ onLoad() { window.ace.edit("ace-editor").session.$worker.send("setOptions", [{ "maxerr": 1000, diff --git a/src/components/editor/KeyboardShortcut.js b/src/components/editor/KeyboardShortcut.js index cea5bccf..53c367cb 100644 --- a/src/components/editor/KeyboardShortcut.js +++ b/src/components/editor/KeyboardShortcut.js @@ -69,6 +69,9 @@ const scene = [ }, ]; +/** + * React components create the button with KeyboardShortcut window + */ class KeyboardShortcut extends React.Component { constructor(props){ super(props); @@ -78,6 +81,11 @@ class KeyboardShortcut extends React.Component { }; } + /** + * Helper function to convert the shrotcuts to an equivalent DOM elements + * + * @param {array} data + */ shortcutHelper = (data) => { let shortcuts = []; data.shortcut.forEach((key,i)=>{ @@ -89,18 +97,31 @@ class KeyboardShortcut extends React.Component { return (

{shortcuts} {data.description}

); }; + /** + * Update the state when the button is clicked + * + * @param {object} event target to anchor the window + */ handleClick = (event) =>{ this.setState({ open: true, anchorEl: event.target}); }; + /** + * Update the state when the window is closed + * + * @param {object} event target to anchor the window + */ handleClose = () => { this.setState({ open: false, anchorEl: null}); }; + /** + * Creates the keyboard shortcut in the DOM + */ render(){ return(
diff --git a/src/components/editor/customCompleter.js b/src/components/editor/customCompleter.js index 91e6b1d2..b30fecb0 100644 --- a/src/components/editor/customCompleter.js +++ b/src/components/editor/customCompleter.js @@ -2,9 +2,12 @@ import myrReference from "../../myr/reference.js"; import myrTextures from "../structural/Textures.js"; import myrModels from "../structural/Models.js"; +/** + * Creates customCompleter for all MYR references and keywords for JS, color code, and assets + */ export const customCompleter = { getCompletions: function (editor, session, pos, prefix, callback) { - let BasicAutocompleteKeyWords = [ + const BasicAutocompleteKeyWords = [ "const", "yield", "import", @@ -36,25 +39,21 @@ export const customCompleter = { "static" ]; - let texture = myrTextures(); - let Texture = [...texture.TexturePack.map(obj => obj.title), - "group()" - ]; + const texture = myrTextures(); + const Texture = [...texture.TexturePack.map(obj => obj.title)]; - let model = myrModels(); - let Model = [...model.ModelPack.keys(), - "group()" - ]; + const model = myrModels(); + const Model = [...model.ModelPack.keys()]; - let reference = myrReference(); - let keyWords = [...reference.geometry.map(obj => obj.name + "()"), + const reference = myrReference(); + const MYRKeyWords = [...reference.geometry.map(obj => obj.name + "()"), ...reference.transformations.map(obj => obj.name + "()"), ...reference.animations.map(obj => obj.name + "()"), ...reference.lights.map(obj=>obj.name+"()"), "group()" ]; - let Colors = [ + const Colors = [ "aliceblue", "antiquewhite", "aqua", @@ -214,7 +213,7 @@ export const customCompleter = { }; })); - callback(null, keyWords.map(function (word) { + callback(null, MYRKeyWords.map(function (word) { return { caption: word, value: word, diff --git a/src/components/layouts/AssetReference.js b/src/components/layouts/AssetReference.js index daa42a69..d4bcfd89 100644 --- a/src/components/layouts/AssetReference.js +++ b/src/components/layouts/AssetReference.js @@ -5,6 +5,11 @@ import AssetReferencePage from "../reference/AssetReferencePage"; import * as layoutTypes from "../../constants/LayoutTypes.js"; +/** + * Create a layout for model reference page. + * @param {object} param0 List of props that will be use in components + * @returns {HTMLElement} Layout of the model reference page + */ export const AssetReference = ({ editor, editorActions, user, authActions, scene, sceneActions, projectActions, courseActions, projects, courses, match, collectionActions, collections }) => (
(
diff --git a/src/components/layouts/Guided.js b/src/components/layouts/Guided.js index d6bbcee3..aa23176f 100644 --- a/src/components/layouts/Guided.js +++ b/src/components/layouts/Guided.js @@ -7,6 +7,11 @@ import View from "../structural/View"; import * as layoutTypes from "../../constants/LayoutTypes.js"; +/** + * Create a layout for course page. + * @param {object} param0 List of props that will be use in components + * @returns {HTMLElement} Layout of the course page + */ export const Guided = ({ editor, user, scene, editorActions, authActions, projectActions, projects, courseActions, courses, course, match, sceneActions, collectionActions, collections }) => (
(
(
(
+
diff --git a/src/components/reference/ModelReferenceTab.js b/src/components/reference/ModelReferenceTab.js index c82ef5ec..218bef04 100644 --- a/src/components/reference/ModelReferenceTab.js +++ b/src/components/reference/ModelReferenceTab.js @@ -11,7 +11,7 @@ import { TableCell } from "@material-ui/core"; -import "../../css/ModelReferencePage.css"; +import "../../css/ReferencePage.css"; export default class ModelReference extends React.Component { imageHelper = (model) => { diff --git a/src/components/reference/RefExInfo.js b/src/components/reference/RefExInfo.js index d43511b9..958ae2fb 100644 --- a/src/components/reference/RefExInfo.js +++ b/src/components/reference/RefExInfo.js @@ -4,8 +4,16 @@ import { Icon } from "@material-ui/core"; +/** + * Reference Example Box is react component for displaying information about + * API in reference example scene + */ class ReferenceExampleBox extends Component { - + /** + * Check the redux state to see if example has suggested course + * and create elements according to it + * @returns {Button} Button with name of suggested course on it + */ suggestedCourse = () => { const { suggestedCourse, suggestedCourseName } = this.props.referenceExample; return ( @@ -24,6 +32,12 @@ class ReferenceExampleBox extends Component { ); } + /** + * Returns parentheses that includes parameters for the example + * + * @param {array} functionParams array of paremeter names + * @returns {string} list of + */ renderParams = (functionParams) => { let returnString = "("; for (let i = 0; i < functionParams.length; i++) { @@ -34,6 +48,10 @@ class ReferenceExampleBox extends Component { // return returnString; } + /** + * Create header element with function name and parameters + * @returns {HTMLElement} h3 tag with "Function: name(parameters)" + */ renderTitle = () => { const { functionName, functionParams } = this.props.referenceExample; return ( @@ -44,6 +62,9 @@ class ReferenceExampleBox extends Component { ); } + /** + * Render title and description of example scene + */ render() { return (
@@ -56,5 +77,4 @@ class ReferenceExampleBox extends Component { } } - export default ReferenceExampleBox; diff --git a/src/components/reference/Reference.js b/src/components/reference/Reference.js index c269e148..c4e44723 100644 --- a/src/components/reference/Reference.js +++ b/src/components/reference/Reference.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { Component } from "react"; import myrReference from "../../myr/reference"; import * as refFunctions from "../../myr/reference"; @@ -36,8 +36,15 @@ const assetReferenceBtn = { top: 0, right: 95, }; -export default class Reference extends React.Component { +/** + * Reference is a react component that creates drawer contains references + */ +class Reference extends Component { + /** + * Constructor + * value represents the current tab that's opened + */ constructor(props) { super(props); this.state = { @@ -46,10 +53,19 @@ export default class Reference extends React.Component { this.tableData = myrReference(); } + /** + * Handler for when user clicked the tab, it updates the state "value" with value passed in + * + * @param {Event} event + * @param {string} value tab to be changed to. It should be an alphabet + */ handleChange = (event, value) => { this.setState({ value }); }; + /** + * Handler for opening the reference page + */ handleOpen = () => { window.open(window.origin + "/reference"); this.setState({ value: "a" }); @@ -83,6 +99,11 @@ export default class Reference extends React.Component { ); }; + /** + * Create a button that will link to the example scene + * @param {string} example name of the API + * @returns {HTMLElement} IconButton with link to the example scene + */ exampleHelper = (example) => { if (example) { let link = "/reference/" + example; @@ -99,8 +120,13 @@ export default class Reference extends React.Component { } }; + /** + * Create a table of references by retrieve array of references from tableData by category + * + * @param {string} category name of the category + * @returns {Table} DOM elements of table with references with passed category + */ TableEx = (category) => { - return ( @@ -123,6 +149,9 @@ export default class Reference extends React.Component { ); }; + /** + * Reneter Button that will open Drawer of reference with different categories + */ render() { const style = { margin: 2, @@ -177,7 +206,6 @@ export default class Reference extends React.Component { settings_system_daydream -
- {

Key: array bool @@ -276,3 +288,5 @@ export default class Reference extends React.Component { ); } } + +export default Reference; \ No newline at end of file diff --git a/src/components/reference/ReferencePage.js b/src/components/reference/ReferencePage.js index 2f33551d..b39b0381 100644 --- a/src/components/reference/ReferencePage.js +++ b/src/components/reference/ReferencePage.js @@ -1,99 +1,22 @@ import React from "react"; -import myrReference from "../../myr/reference"; -import * as refFunctions from "../../myr/reference"; +import Reference from "./Reference"; import { Tabs, Tab, Icon, - IconButton, - Table, - TableBody, - TableHead, - TableRow, - TableCell, Hidden, } from "@material-ui/core"; import "../../css/ReferencePage.css"; -export default class Reference extends React.Component { - - constructor(props) { - super(props); - this.state = { - value: "a", - }; - this.tableData = myrReference(); - } - - handleToggle = () => this.setState({ open: !this.state.open, value: "a" }); - - handleChange = (event, value) => { - this.setState({ value }); - }; - - exampleHelper = (example) => { - if (example) { - let link = "/reference/" + example; - return ( - - link - - ); - } else { - return null; - } - }; - - nameHelper = (name, parameters) => { - return ( - {name}({(parameters.map((element, i, params) => { - let comma = i < params.length - 1 ? ", " : ""; - switch (element.type) { - case "number": - return {refFunctions.numberText(element.name)}{comma}; - case "string": - return {refFunctions.stringText(element.name)}{comma}; - case "bool": - return {refFunctions.boolText(element.name)}{comma}; - case "array": - return {refFunctions.arrayText(element.name)}{comma}; - case "data": - return {refFunctions.dataText(element.name)}{comma}; - default: - return null; - } - }))}); - ); - }; - - TableEx = (category) => { - - return ( -

- - - Name - Description - Example - - - - {this.tableData[category].map((row, index) => ( - - {this.nameHelper(row.name, row.parameters)} - {row.description} - {this.exampleHelper(row.example)} - - ))} - -
- ); - }; - +/** + * ReferencePage extends Reference class and overrides the render function to create as single page + */ +class ReferencePage extends Reference { + /** + * Render reference page + */ render() { document.title = "Reference | MYR"; return ( @@ -176,3 +99,5 @@ export default class Reference extends React.Component { ); } } + +export default ReferencePage; \ No newline at end of file diff --git a/src/components/reference/TextureReferenceTab.js b/src/components/reference/TextureReferenceTab.js index d399a1ad..0d64f131 100644 --- a/src/components/reference/TextureReferenceTab.js +++ b/src/components/reference/TextureReferenceTab.js @@ -11,7 +11,7 @@ import { TableCell, } from "@material-ui/core"; -import "../../css/TextureReferencePage.css"; +import "../../css/ReferencePage.css"; export default class TextureReference extends React.Component { imageHelper = (image) => { diff --git a/src/components/structural/Footer.js b/src/components/structural/Footer.js index 876b75dd..e6eaeee3 100644 --- a/src/components/structural/Footer.js +++ b/src/components/structural/Footer.js @@ -1,5 +1,8 @@ import React, { Component } from "react"; +/** + * React component class for the footer includes link to about page, privacy policy, TOS, etc. + */ class Footer extends Component { render() { return ( diff --git a/src/components/structural/Models.js b/src/components/structural/Models.js index ec66a713..86b2a0c4 100644 --- a/src/components/structural/Models.js +++ b/src/components/structural/Models.js @@ -1,3 +1,6 @@ +/** + * Map of textures' name and url and img url for retrieval + */ let ModelPack = new Map(); // Models that have been cleared for us to host ModelPack.set("sword", {model: "/models/sword.glb", image: "/img/models/sword.png"}); diff --git a/src/components/structural/Textures.js b/src/components/structural/Textures.js index be39c962..6e43dc44 100644 --- a/src/components/structural/Textures.js +++ b/src/components/structural/Textures.js @@ -1,4 +1,7 @@ -let TexturePack = [ +/** + * List of textures' name and url for retrieval + */ +const TexturePack = [ {title:"bricks",url:"/img/textures/bricks.jpg"}, {title:"bark",url:"/img/textures/bark.jpg"}, {title:"checkerboard",url:"/img/textures/checkerboard.jpg"}, diff --git a/src/components/structural/View.js b/src/components/structural/View.js index 8445b602..791c1819 100644 --- a/src/components/structural/View.js +++ b/src/components/structural/View.js @@ -18,10 +18,21 @@ class View extends Component { welcomeOpen: true }; } + /** + * The timer ID set to check if the welcome screen is open + * It will use it to cancel the timer once the welcome screen is close + */ intervalID = 0; - componentDidMount() { - // Don't show editor if welcome screen is open + /** + * Called when the MYR Scene is mounted (component has been rendererd to the DOM) + * + * It check if the user's first time visiting, then it will set up a interval to see if the welcome screen is closed for every 1000ms + * It also add a event listener to + * stop key press of movement (arrow key and space) to scroll the page + * hide or show "interface" (editor) depends on when user enter or exit the VR(fullscreen) mode. + */ + componentDidMount() { if (!this.getCookie("hasVisited")) { this.intervalID = setInterval(this.checkForWelcomeScreen, 1000); } @@ -45,7 +56,10 @@ class View extends Component { } /** - * This fires off an event when the system is fully rendered. + * Called when MYR Scene is rendererd (DOM elements is changed/updated) + * + * If the welcome screen is closed, it fires an event for "myr-view-rendererd" which added in + * change() & push() in Myr.js but these are unused functions that are not documented in reference. */ componentDidUpdate() { if (!this.state.welcomeOpen) { @@ -54,14 +68,24 @@ class View extends Component { // Dispatch/Trigger/Fire the event document.dispatchEvent(event); - } - + } } + /** + * Called when the MYR Scene is unmounting (Being removed from the DOM) + * + * It will check if the timerID for checking welcome screen is set, + * If so it will clear/stop the timer from checking. + */ componentWillUnmount() { if (this.intervalID !== 0) { clearInterval(this.intervalID); } } + /** + * On every interval (1000ms) it check whether the cookie hasVisited is set to true + * If so, set state "welcomeOpen" to false (so it will render the scene) + * and stop the timer. + */ checkForWelcomeScreen = () => { if (this.getCookie("hasVisited")) { this.setState({ welcomeOpen: false }); @@ -70,6 +94,11 @@ class View extends Component { } } + /** + * Get value of cookie + * @param {string} cookieName name of cookie + * @returns {string} value of cookie if it exist, return empty string otherwise + */ getCookie = (cookieName) => { let name = cookieName + "="; let decodedCookie = decodeURIComponent(document.cookie); @@ -87,9 +116,10 @@ class View extends Component { } /** - * This renders json to aframe entities + * A helper function that converts MYR objects into a corresponded A-Frame DOM elements * - * @param {*} ent + * @param {object} ent MYR object + * @returns {HTMLElement} A-Frame entities */ helper = (ent) => { if (ent) { @@ -142,9 +172,13 @@ class View extends Component { return ; } } - //return elements that contains necessary configuration for light indicator based on light's type and properties + /** + * Helper fuctions that returns A-Frame elements that contains necessary configuration for light indicator based on light's type and properties + * + * @param {object} ent Myr object + * @returns A-Frame entities of light indicator + */ lightIndicatorHelper =(ent)=>{ - //this is a position for passing in to indicatorroation to determine the rotation of the light that use position as vector. let position =`position:${ent.position.x || 0} ${ent.position.y || 0} ${ent.position.z || 0};`; if(ent.light.target){ @@ -169,7 +203,13 @@ class View extends Component { default: } } - //return string that contains necessary configuration for shadow based on light's type + + /** + * Helper function that returns configuration for shadow based on light's type + * + * @param {object} light light properties + * @returns {string} string of aframe configuration of shadow that will attach to the light attribute + */ lightShadowHelper = (light) =>{ let newState = ""; //ambient and hemisphere light doesn't cast shadow @@ -188,12 +228,23 @@ class View extends Component { return newState; } + /** + * Help convert asset(model,image,etc) datas to A-Frame entitiy + * + * @param {object} asset + * @returns {HTMLElement} a-asset-item of the object + */ assetsHelper = (asset) => { return ( ); } + /** + * It creates 2 different A-Frame camera. As for now, it will always be basicMoveCam. + * + * @returns {HTMLElement} Camera elements + */ createCam = () => { switch (this.props.sceneConfig.settings.camConfig) { case 0: @@ -205,6 +256,14 @@ class View extends Component { } } + /** + * Check point cam is a mode where there's a checkpoints in the scene where user can select them to teleport to that position + * to move around the scene compare to the regular movement. + * + * Check point is currently not implemented in MYR to be an usable feature. + * + * @returns {HTMLElement} Camera elements contains checkpoint control + */ checkpointCam = () => { return ( @@ -220,6 +279,18 @@ class View extends Component { ); } + + /** + * It returns camera basic with different movement control depends on the browser type + * Mobile: + * default movement controls with flying enabled + * VR: + * default movement controls with flying disabled + * Desktop: + * custom wasd-plus-control with controllable movement speed + * + * @returns {HTMLElement} A-Frame camera elements with basic movement + */ basicMoveCam = () => { switch(browserType()) { case "mobile": @@ -276,15 +347,17 @@ class View extends Component { /** * Produces the grid on the ground and the coordinate lines + * + * @returns {HTMLElements} A-Frame entitiy containing grid, tube for axies and text to label those axes */ coordinateHelper = () => { if (this.props.sceneConfig.settings.showCoordHelper) { return ( - - - - + + + + { if (this.props.sceneConfig.settings.showFloor) { return ( @@ -331,6 +408,11 @@ class View extends Component { } } + /** + * Main part for Rendering MYR Scene! + * + * @returns {HTMLElement} A-Frame scene containing all the settings and MYR objects + */ render = () => { /* eslint-disable */ return ( diff --git a/src/components/structural/WelcomeScene.js b/src/components/structural/WelcomeScene.js index 5b76ad15..2a8072be 100644 --- a/src/components/structural/WelcomeScene.js +++ b/src/components/structural/WelcomeScene.js @@ -1,7 +1,14 @@ import React, { Component } from "react"; import { browserType } from "../../utils/browserType"; +/** + * Welcome Scene component returns static aframe scene to embed in welcome screen + */ class WelcomeScene extends Component { + /** + * Create basicMoveCam + * Refer to basicMoveCam in View.js for more detail description + */ createCam = () => { switch(browserType()) { case "mobile": @@ -52,6 +59,9 @@ class WelcomeScene extends Component { } } + /** + * @returns aframe scene that same as dropsies scene from example project + */ render() { return ( diff --git a/src/components/structural/WelcomeScreen.js b/src/components/structural/WelcomeScreen.js index f61bab08..1dca3fad 100644 --- a/src/components/structural/WelcomeScreen.js +++ b/src/components/structural/WelcomeScreen.js @@ -15,6 +15,9 @@ import CourseSelect from "../courses/CourseSelect.js"; import { withStyles } from "@material-ui/core/styles"; import "../../css/WelcomeScreen.css"; +/** + * @returns {object} Center the Welcome Screen + */ function getOuterModalStyle() { const top = 50; const left = 50; @@ -65,6 +68,10 @@ const exitBtnStyle = { top: 0, right: 0, }; + +/** + * Welcome Component returns a modal of welcome screen that shows up when user first enter MYR + */ class Welcome extends React.Component { constructor(props) { super(props); @@ -75,12 +82,23 @@ class Welcome extends React.Component { }; } + /** + * Called when the Welcome Screen is mounted (component has been rendererd to the DOM) + * + * Header.js has a state to control whether to show welcome screen or not. By default it's false. + * So if user hasn't visisted the MYR, toggle the state to true. + */ componentDidMount() { if (!this.getCookie("hasVisited")) { this.props.handleWelcomeToggle(); } } + /** + * Get value of cookie + * @param {string} cookieName name of cookie + * @returns {string} value of cookie if it exist, return empty string otherwise + */ getCookie = (cookieName) => { let name = cookieName + "="; let decodedCookie = decodeURIComponent(document.cookie); @@ -97,6 +115,11 @@ class Welcome extends React.Component { return ""; } + /** + * If the user is first visiting the MYR, set "hasVisisted" to true + * and set the expiration date to current date + 24 hrs + * So it will re-appear after 24 hrs + */ setCookie = () => { if (!this.getCookie("hasVisited")) { let date = new Date(); @@ -107,16 +130,26 @@ class Welcome extends React.Component { } } + /** + * Handler for when the welcome screen is close either by close button or clicking outside of modal + */ handleClose = () => { this.setCookie(); this.props.handleWelcomeToggle(); }; + /** + * Handler for when user click "never again" button + * It sets a long expiration date so it will "never" expireds + */ neverAgainCookie = () => { document.cookie = "hasVisited=true; expires=Thu, 31 Dec 2099 12:00:00 UTC;"; this.handleClose(); } + /** + * @returns {*} Button with don't show again option + */ neverAgain = () => { return ( - //

- // Legal disclaimer: This will only slow down people from accessing your work. MYR is not sutiable for sensitive information. - //

- //
- // ); - - // pwProtect = () => ( - //
- //
Please enter a PW.
- // - // - //

- // Legal disclaimer: This will only slow down people from accessing your work. MYR is not sutiable for sensitive information. - //

- //
- // ); + /** + * @returns Email field where user enters addresses they want to share it with + */ shareOptions = () => (
Enter one or more email addresses
@@ -231,6 +219,9 @@ class Project extends React.Component {
); + /** + * @returns Returns the info of the project if it exists + */ infoOpen = () => { let projectId = this.state.projectId; let project; @@ -262,6 +253,9 @@ class Project extends React.Component { ); }; + /** + * @returns QR Code of the link to the project + */ qrCodeOpen = () => { return (
@@ -270,7 +264,13 @@ class Project extends React.Component {
); }; - + + /** + * Helper for creating the project card + * @param {object} proj Porject info + * @param {boolean} canDelete whehter project can be deleted + * @returns Elements of the project card + */ helper = (proj, canDelete) => { if (proj) { let id = proj._id; @@ -331,6 +331,9 @@ class Project extends React.Component { } } + /** + * @returns Create a share menu for QR Code and email + */ sceneMenu = () => ( - {/* { this.handleClose(); this.handlePwToggle(); }}> - - lock - - - */} ); + /** + * Handles the switch between user and example project tab + * @param {*} event + * @param {string} value New tab string + */ handleChange = (event, value) => { this.setState({ value }); }; + /** + * Create project view + */ render() { const { classes } = this.props; let previewToggle = { @@ -503,20 +507,6 @@ class Project extends React.Component {
- -
- this.handlePwToggle()} > - clear - - -
-
diff --git a/src/components/structural/header/SceneConfigMenu.js b/src/components/structural/header/SceneConfigMenu.js index 3421328b..1eed61c3 100644 --- a/src/components/structural/header/SceneConfigMenu.js +++ b/src/components/structural/header/SceneConfigMenu.js @@ -92,7 +92,6 @@ class ConfigModal extends Component { displayFloorColorPicker: false, displayMoveSpeedSlider: false, qrCodeOpen: false, - pwProtectOpen: false, shareOpen: false, addClassOpen: false, defaultLight: true, @@ -129,16 +128,19 @@ class ConfigModal extends Component { }); }; - handleClick = event => { - this.setState({ anchorEl: event.currentTarget, projectId: event.currentTarget.id }); - }; - + /** + * Handles when the text change in the textfield. Use in mail share and collection + * @param {string} name Place where it saved in state + */ handleTextChange = name => event => { this.setState({ [name]: event.target.value, }); }; + /** + * Handles when the user add the new email address to send + */ handleAddEmail = () => { let arr = [].concat(this.state.sendTo); arr.push(this.state.email); @@ -146,40 +148,23 @@ class ConfigModal extends Component { this.setState({ sendTo: arr, email: "" }); }; + /** + * Handles toggle the qrcode menu + */ handleQrToggle = () => { this.setState({ qrCodeOpen: !this.state.qrCodeOpen }); }; - - handlePwToggle = () => { - this.setState({ pwProtectOpen: !this.state.pwProtectOpen }); - }; - + + /** + * Handles toggle the share menu + */ handleShrToggle = () => { this.setState({ shareOpen: !this.state.shareOpen, sendTo: [] }); }; - pwProtect = () => ( -
-
Please enter a PW.
- - -

- Legal disclaimer: This will only slow down people from accessing your work. MYR is not sutiable for sensitive information. -

-
- ); - + /** + * Email field where user enters addresses they want to share it with + */ shareOptions = () => (
Enter one or more email addresses
@@ -209,6 +194,9 @@ class ConfigModal extends Component {
); + /** + * QR Code of the link to the project + */ qrCodeOpen = () => { return (
@@ -225,48 +213,75 @@ class ConfigModal extends Component { this.props.sceneActions.toggleCoordSky(); }; + /** + * Update the state and dispatch an action to change the skycolor + * @param {object} color object contains "hex" key + */ handleSkyChangeComplete = (color) => { this.setState({ skyColor: color.hex }); this.props.sceneActions.changeSkyColor(color.hex); }; + /** + * Update the state and dispatch an action to change the floorcolor + * @param {object} color object contains "hex" key + */ handleFloorChangeComplete = (color) => { this.setState({ floorColor: color.hex }); this.props.sceneActions.changeFloorColor(color.hex); }; + + /** + * Update component state whenever the slider's value changes + * so text displays correctly, only update redux store on + * mouseup when user drags slider + * + * @param {object} e input from mouse + * @param {number} newSpeed updated value + */ handleMoveSpeedUpdate = (e, newSpeed) => { - /* update component state whenever the slider's value changes - * so text displays correctly, only update redux store on - * mouseup when user drags slider */ this.setState({ moveSpeed: newSpeed }); if(!e || e.type === "mouseup") { this.props.sceneActions.updateMoveSpeed(newSpeed); } }; + /** + * Toggle the color picker for skyColor + */ handleSkyColorClick = () => { this.setState({ displaySkyColorPicker: !this.state.displaySkyColorPicker }); }; + /** + * Toggle the color picker for floorColor + */ handleFloorColorClick = () => { this.setState({ displayFloorColorPicker: !this.state.displayFloorColorPicker }); }; + handleMoveSpeedClick = () => { this.setState({ displayMoveSpeedSlider: !this.state.displayMoveSpeedSlider }); }; + /** + * Close the color picker for skyColor + */ handleSkyColorClose = () => { this.setState({ displaySkyColorPicker: false }); }; + /** + * Close the color picker for floorColor + */ handleFloorColorClose = () => { this.setState({ displayFloorColorPicker: false }); }; /** - * Toggles whether the editor is showing + * Return button for toggles whether the editor is showing */ viewToggle = () => { let style = this.props.scene.settings.viewOnly ? btnStyle.off : btnStyle.on; @@ -290,7 +305,9 @@ class ConfigModal extends Component { ); }; - // Toggles the grid on and off + /** + * Return button for toggles the grid on and off + */ gridToggle = () => { let style = this.props.scene.settings.showCoordHelper ? btnStyle.on : btnStyle.off; style = { ...btnStyle.base, ...style }; @@ -311,6 +328,9 @@ class ConfigModal extends Component { ); }; + /** + * Return button for toggles the default light on and off + */ defaultLightToggle = () =>{ let style = this.props.scene.settings.defaultLight ? btnStyle.on : btnStyle.off; style = { ...btnStyle.base, ...style }; @@ -331,7 +351,10 @@ class ConfigModal extends Component { ); }; - + + /** + * Return button for toggles the shadow on and off + */ castShadowToggle = () => { let style = this.props.scene.settings.castShadow ? btnStyle.on : btnStyle.off; style = { ...btnStyle.base, ...style }; @@ -353,6 +376,9 @@ class ConfigModal extends Component { ); }; + /** + * Return button for toggles the light indicator on and off + */ lightIndicatorToggle = () => { let style = this.props.scene.settings.lightIndicator ? btnStyle.on : btnStyle.off; style = { ...btnStyle.base, ...style }; @@ -375,7 +401,7 @@ class ConfigModal extends Component { }; /** - * Toggles the floor on and off + * Return button for toggles the floor on and off */ floorToggle = () => { let style = this.props.scene.settings.showFloor ? btnStyle.on : btnStyle.off; @@ -397,6 +423,9 @@ class ConfigModal extends Component { ); }; + /** + * Return button for toggles addCollection menu + */ addCollectionToggle = () => { return ( { this.setState({ addClassOpen: !this.state.addClassOpen, collectionError: "" }); }; + + /** + * Returns button for shows collection info + */ classInfoToggle = () => { return ( (
Please enter your collection name.
@@ -471,6 +510,9 @@ class ConfigModal extends Component { ); }; + /** + * Returns button for open speed slider + */ updateMoveSpeed = () => { return ( { return ( { return ( { this.setState({ value }); }; + /** + * Create sceneConfig menu + */ render() { const { classes } = this.props; let isDisabled = this.props.layoutType === layoutTypes.REFERENCE; @@ -664,12 +720,6 @@ class ConfigModal extends Component { send Send To - {/* { this.handlePwToggle(); }} > - lock - Add PW - */}
Collection Control
{this.props.displayCollectionConfig ? @@ -723,20 +773,6 @@ class ConfigModal extends Component {
- -
- this.handlePwToggle()} > - clear - - -
-
({ editor: state.editor, @@ -36,7 +35,7 @@ const mapStateToProps = state => ({ /** * This maps dispatch actions to props - * @param {*} dispatch !!!DESCRIPTION NEEDED!!! + * @param {*} dispatch Give dipatch to the store */ const mapDispatchToProps = dispatch => ({ editorActions: bindActionCreators(EditorActions, dispatch), diff --git a/src/containers/Guided.js b/src/containers/Guided.js index 55e0e672..73c8197c 100644 --- a/src/containers/Guided.js +++ b/src/containers/Guided.js @@ -18,6 +18,10 @@ Guided.propTypes = { course: PropTypes.object.isRequired }; +/** + * This makes the values accessible as props + * @param {*} state Entire redux store state + */ const mapStateToProps = state => ({ editor: state.editor, user: state.user.user, @@ -31,7 +35,7 @@ const mapStateToProps = state => ({ /** * This maps dispatch actions to props - * @param {*} dispatch !!!DESCRIPTION NEEDED!!! + * @param {*} dispatch Give dipatch to the store */ const mapDispatchToProps = dispatch => ({ editorActions: bindActionCreators(Actions.EditorActions, dispatch), diff --git a/src/containers/Ide.js b/src/containers/Ide.js index 94fba0e9..135e001f 100644 --- a/src/containers/Ide.js +++ b/src/containers/Ide.js @@ -16,7 +16,7 @@ Ide.propTypes = { /** * This makes the values accessible as props - * @param {*} state !!!DESCRIPTION NEEDED!!! + * @param {*} state Entire redux store state */ const mapStateToProps = state => ({ editor: state.editor, @@ -29,7 +29,7 @@ const mapStateToProps = state => ({ /** * This maps dispatch actions to props - * @param {*} dispatch !!!DESCRIPTION NEEDED!!! + * @param {*} dispatch Give dipatch to the store */ const mapDispatchToProps = dispatch => ({ editorActions: bindActionCreators(Actions.EditorActions, dispatch), diff --git a/src/containers/Reference.js b/src/containers/Reference.js index e7372295..a6e3219c 100644 --- a/src/containers/Reference.js +++ b/src/containers/Reference.js @@ -16,7 +16,7 @@ ReferencePage.propTypes = { /** * This makes the values accessible as props - * @param {*} state !!!DESCRIPTION NEEDED!!! + * @param {*} state Entire redux store state */ const mapStateToProps = state => ({ editor: state.editor, @@ -29,7 +29,7 @@ const mapStateToProps = state => ({ /** * This maps dispatch actions to props - * @param {*} dispatch !!!DESCRIPTION NEEDED!!! + * @param {*} dispatch Give dipatch to the store */ const mapDispatchToProps = dispatch => ({ editorActions: bindActionCreators(Actions.EditorActions, dispatch), @@ -46,4 +46,4 @@ const mapDispatchToProps = dispatch => ({ export default connect( mapStateToProps, mapDispatchToProps -)(ReferencePage); +)(ReferencePage); \ No newline at end of file diff --git a/src/containers/ReferenceExample.js b/src/containers/ReferenceExample.js index c9c8f96b..fbf279ac 100644 --- a/src/containers/ReferenceExample.js +++ b/src/containers/ReferenceExample.js @@ -16,7 +16,7 @@ ReferenceExample.propTypes = { /** * This makes the values accessible as props - * @param {*} state !!!DESCRIPTION NEEDED!!! + * @param {*} state Entire redux store state */ const mapStateToProps = state => ({ editor: state.editor, @@ -30,7 +30,7 @@ const mapStateToProps = state => ({ /** * This maps dispatch actions to props - * @param {*} dispatch !!!DESCRIPTION NEEDED!!! + * @param {*} dispatch Give dipatch to the store */ const mapDispatchToProps = dispatch => ({ editorActions: bindActionCreators(Actions.EditorActions, dispatch), diff --git a/src/containers/TextureReference.js b/src/containers/TextureReference.js deleted file mode 100644 index d45697ac..00000000 --- a/src/containers/TextureReference.js +++ /dev/null @@ -1,39 +0,0 @@ -import PropTypes from "prop-types"; -import TextureReferencePage from "../components/layouts/TextureReference.js"; -import * as Actions from "../actions"; - -import { bindActionCreators } from "redux"; -import { connect } from "react-redux"; - -// This makes sure we are getting what we think we should -TextureReferencePage.propTypes = { - editor: PropTypes.object.isRequired, - user: PropTypes.object, - scene: PropTypes.object.isRequired, -}; - -// This makes the values accessible as props -const mapStateToProps = state => ({ - editor: state.editor, - user: state.user.user, - scene: state.scene, - projects: state.project, - courses: state.courses, - collections: state.collections -}); - -// This maps dispatch actions to props -const mapDispatchToProps = dispatch => ({ - editorActions: bindActionCreators(Actions.EditorActions, dispatch), - authActions: bindActionCreators(Actions.AuthActions, dispatch), - sceneActions: bindActionCreators(Actions.SceneActions, dispatch), - projectActions: bindActionCreators(Actions.ProjectActions, dispatch), - courseActions: bindActionCreators(Actions.CourseActions, dispatch), - collectionActions: bindActionCreators(Actions.CollectionActions, dispatch) -}); - -// This does the binding to the redux store -export default connect( - mapStateToProps, - mapDispatchToProps -)(TextureReferencePage); diff --git a/src/css/ModelReferencePage.css b/src/css/ModelReferencePage.css deleted file mode 100644 index 3e6959f8..00000000 --- a/src/css/ModelReferencePage.css +++ /dev/null @@ -1,46 +0,0 @@ -#modelReference-page { - background: #fff; - min-height: 94vh; - width: 100% -} - -#ref-ex { - padding: 10px !important; - background: #fff !important; -} - -.ref-ex-edit div#ace-editor { - height: 69.5vh !important; -} - -#ref-ex p { - height: 12vh; - margin: 0; - overflow: auto; -} - -#ref-ex fieldset { - height: 16vh; - margin: 0; -} - -.ref-ex-btn .material-icons { - margin: 0 .3em; -} - -a.ref-ex-btn:hover { - color: #fff; -} - -.ref-ex-btn { - margin-top: 1em !important; - margin-bottom: 10px !important; - justify-content: center !important; - padding-left: 1em !important; - width: 100% !important; - text-align: center !important; -} - -#suggested-course { - padding-right: 2em; -} \ No newline at end of file diff --git a/src/css/TextureReferencePage.css b/src/css/TextureReferencePage.css deleted file mode 100644 index f2b0a685..00000000 --- a/src/css/TextureReferencePage.css +++ /dev/null @@ -1,46 +0,0 @@ -#textureReference-page { - background: #fff; - min-height: 94vh; - width: 100% -} - -#ref-ex { - padding: 10px !important; - background: #fff !important; -} - -.ref-ex-edit div#ace-editor { - height: 69.5vh !important; -} - -#ref-ex p { - height: 12vh; - margin: 0; - overflow: auto; -} - -#ref-ex fieldset { - height: 16vh; - margin: 0; -} - -.ref-ex-btn .material-icons { - margin: 0 .3em; -} - -a.ref-ex-btn:hover { - color: #fff; -} - -.ref-ex-btn { - margin-top: 1em !important; - margin-bottom: 10px !important; - justify-content: center !important; - padding-left: 1em !important; - width: 100% !important; - text-align: center !important; -} - -#suggested-course { - padding-right: 2em; -} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 04e52654..dca40430 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,9 @@ import store from "./reducers/index"; import AppRoutes from "./routes"; +/** + * Entry point of MYR + */ ReactDOM.render( diff --git a/src/myr/Group.js b/src/myr/Group.js index 332c87b5..a1e668b5 100644 --- a/src/myr/Group.js +++ b/src/myr/Group.js @@ -1,4 +1,11 @@ +/** Class representing a Group in MYR */ class Group { + /** + * Instantiate a new Group class + * + * @param {Myr} originalMyr MYR instance + * @param {string} id ID assigned for this Group + */ constructor(originalMyr, id) { this.els = []; this.entity = true; @@ -6,14 +13,23 @@ class Group { this.id = id; } + /** + * Add new MYR entity to the Group + * + * @param {(Group|string)} id Instance of Group or ID of MYR entity + */ add = (id) => { if (id instanceof Group) { this.els.push(this.myr.transfer(id.id)); } this.els.push(this.myr.transfer(id)); - } + /** + * Remove MYR entity from the Group + * + * @param {(Group|string)} id Instance of Group or ID of MYR entity + */ remove = (id) => { if (id instanceof Group) { id = id.id; @@ -24,10 +40,25 @@ class Group { this.myr.els.push(el); } + /** + * Retrieve specific MYR entity in the Group + * + * @param {string} outerElId - ID of the entity to retrieve + * @returns {object} MYR object if found, null other wise + */ getEl = (outerElId) => { + if (outerElId.entity) { + outerElId = outerElId.id; + } return this.els[outerElId]; } + /** + * Retrieve the index of specific MYR entity in the Group + * + * @param {string} outerElId - ID of the object to retrieve + * @returns {number} - Index of the array if found, null otherwise. + */ getIndex = (outerElId) => { for (let i in this.els) { if (this.els[i].id === outerElId) { @@ -37,6 +68,13 @@ class Group { return null; } + /** + * Sets the x, y, and z position of the Group + * + * @param {number} x New x position + * @param {number} y New y position + * @param {number} z New z position + */ setPosition = (x = 0, y = 1, z = 0) => { let ent = this.myr.getEl(this.id); ent.position = { @@ -45,6 +83,13 @@ class Group { this.myr.els[this.id] = ent; } + /** + * Sets the x, y, and z scale of the Group + * + * @param {number} x New x scale + * @param {number} y New y scale + * @param {number} z New z scale + */ setScale = (x = 1, y = 1, z = 1) => { let ent = this.myr.getEl(this.id); ent.scale = { @@ -53,6 +98,13 @@ class Group { this.myr.els[this.id] = ent; } + /** + * Sets the x, y, and z rotation of the Group + * + * @param {number} x New x rotation + * @param {number} y New y rotation + * @param {number} z New z rotation + */ setRotation = (x = 0, y = 0, z = 0) => { let ent = this.myr.getEl(this.id); ent.rotation = { @@ -61,13 +113,16 @@ class Group { this.myr.els[this.id] = ent; } + /** + * Return an object with elements of the Group + * @returns {object} Flag indicates it's a Group and elements + */ entObj = () => { return { group: true, els: this.els }; } - } export default Group; diff --git a/src/myr/Myr.js b/src/myr/Myr.js index 5c182f1c..6f9e48b0 100644 --- a/src/myr/Myr.js +++ b/src/myr/Myr.js @@ -6,6 +6,10 @@ import TexturePack from "../components/structural/Textures.js"; import ModelPack from "../components/structural/Models.js"; class Myr { + /** + * Instantiate MYR class + * @param {object} baseEls list of the entities restore to the new MYR + */ constructor(baseEls) { this.counter = 0; this.baseEls = baseEls; @@ -188,6 +192,9 @@ class Myr { }; } + /** + * Reset the transformation properties of the cursor to the default + */ resetTransformationCursor = () => { this.cursor = { ...this.cursor, @@ -212,6 +219,9 @@ class Myr { }; }; + /** + * Reset the animation properties of the cursor to the default + */ resetAnimationCursor = () => { this.cursor = { ...this.cursor, @@ -225,6 +235,9 @@ class Myr { }; }; + /** + * Reset the light properties of the cursor to the default + */ resetLightCursor = () => { this.cursor.light = { intensity: 1.0, @@ -236,6 +249,9 @@ class Myr { }; }; + /** + * Generate unique id that is assigned to each entity + */ genNewId = () => { return this.counter++; }; @@ -474,55 +490,6 @@ class Myr { return { x: this.cursor.rotation.x, y: this.cursor.rotation.y, z: this.cursor.rotation.z }; } - setCursorAttribute = (key = "", value = "") => { - if (typeof (key) !== "string" || key === "") { - console.error("Error: Invalid key"); - return this.cursor; - } - switch (key.toLowerCase()) { - case "color": - this.setColor(value); - break; - case "texture": - this.setTexture(value); - break; - case "position": - this.setPosition(value.x, value.y, value.z); - break; - case "scale": - this.setScale(value.x, value.y, value.z); - break; - case "rotation": - this.setRotation(value.x, value.y, value.z); - break; - case "radius": - this.setRadius(value); - break; - case "philength": - this.setPhiLength(value); - break; - case "loop": - this.setLoop(value); - break; - case "duration": - this.setDuration(value); - break; - case "magnitude": - this.setMagnitude(value); - break; - case "transparency": - this.setTransparency(value); - break; - default: - this.cursor[key] = value; - } - return this.cursor; - } - - getCursorAttribute = (key = "") => { - return this.cursor[key]; - } - /** * Applies a given x rotation to the cursor * @@ -645,6 +612,13 @@ class Myr { return this.cursor.color; } + /** + * Sets the texture of the cursor. Defaults is empty string. + * + * @param {string} texture Specifying the texture. This can be either texture exist in our sever or valid url to the texture + * @param {number} w Number of times to repeat the texture horizontally + * @param {number} h Number of times to repeat the texture vertically + */ setTexture = (texture = "", w = 1, h = 1) => { let textures = TexturePack(); let textureTitle = [...textures.TexturePack.map(obj => obj.title)]; @@ -667,11 +641,22 @@ class Myr { return this.cursor.texture; } + /** + * Sets whether to enable to color the texture or not + * + * @param {boolean} i Enable or disable texture coloring + */ setTextureColoring = (i) => { this.cursor.textureColoring = Boolean(i); return this.cursor.textureColoring; }; + /** + * Sets the existing cursor as well as creates a new custom cursor attributes to apply to entity + * + * @param {string} key Name of the attribute + * @param {any} value Values apply to attribute + */ setCursorAttribute = (key = "", value = "") => { if (typeof (key) !== "string" || key === "") { console.error("Error: Invalid key"); @@ -711,6 +696,12 @@ class Myr { return this.cursor; } + /** + * Get the any values of the exisitng cursor attribute + * + * @param {string} key Name of the cursor attribute + * @returns Value of the cursor attribute if it exists + */ getCursorAttribute = (key = "") => { return this.cursor[key]; } @@ -719,7 +710,7 @@ class Myr { * Returns a random valid color. * * @param {array} colors An array of colors to choose from. If left - * empty then all colors are drawn from + * empty then random hexadecimal color are chosen. */ getRandomColor = (colors = null) => { let color; @@ -744,16 +735,11 @@ class Myr { return this.cursor.color; } - drop = (outerElId) => { - this.getEl(outerElId)["dynamic-body"] = "shape: box; mass: 5"; - return outerElId; - } - /** * Allows the entity to be dropped * - * @param {number} outerElId !!!DESCRIPTION NEEDED!!! - * @param {number} mass !!!DESCRIPTION NEEDED!!! + * @param {string} outerElId Id of the entity to apply the physics + * @param {number} mass Set how heavy the entity is. */ makeDroppable = (outerElId, mass = 2) => { let el = this.getEl(outerElId); @@ -765,7 +751,7 @@ class Myr { /** * Disallows the entity to be dropped * - * @param {number} outerElId !!!DESCRIPTION NEEDED!!! + * @param {string} outerElId Id of the entity to remove the properties */ makeUnDroppable = (outerElId) => { let el = this.getEl(outerElId); @@ -779,8 +765,8 @@ class Myr { /** * Allows the entity to be pushed * - * @param {number} outerElId !!!DESCRIPTION NEEDED!!! - * @param {number} mass !!!DESCRIPTION NEEDED!!! + * @param {string} outerElId Id of the entity to apply the physics + * @param {number} mass Set how heavy the entity is. */ makePushable = (outerElId, mass = 2) => { let el = this.getEl(outerElId); @@ -793,21 +779,7 @@ class Myr { /** * Disallows the entity to be pushed * - * @param {number} outerElId !!!DESCRIPTION NEEDED!!! - */ - makeUnPushable = (outerElId) => { - let el = this.getEl(outerElId); - if (el["force-pushable"]) { - el["dynamic-body"] = null; - el["force-pushable"] = "false"; - } - return outerElId; - } - - /** - * Disallows the entity to be pushed - * - * @param {number} outerElId !!!DESCRIPTION NEEDED!!! + * @param {string} outerElId Id of the entity to remove the properties */ makeUnPushable = (outerElId) => { let el = this.getEl(outerElId); @@ -818,27 +790,10 @@ class Myr { return outerElId; } - push = (outerElId, x, y, z) => { - // Add an event listener - document.addEventListener("myr-view-rendered", () => { - let el = document.querySelector("#" + outerElId); - if (!el) { - return; - } - el.addEventListener("body-loaded", () => { - el.body.applyImpulse( - /* impulse */ new CANNON.Vec3(x, y, z), - /* world position */ new CANNON.Vec3().copy(el.object3D.position) - ); - }); - }); - return outerElId; - } - /** * Render an Aframe box with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ box = (params) => { let base = { @@ -856,7 +811,7 @@ class Myr { /** * Render an Aframe circle with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ circle = (params) => { let base = { @@ -873,7 +828,7 @@ class Myr { /** * Render an Aframe cone with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ cone = (params) => { let base = { @@ -890,7 +845,7 @@ class Myr { /** * Render an Aframe cylinder with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ cylinder = (params) => { let base = { @@ -908,7 +863,7 @@ class Myr { /** * Render an Aframe dodecahedron with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ dodecahedron = (params) => { let base = { @@ -925,7 +880,7 @@ class Myr { /** * Render an Aframe icosahedron with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ icosahedron = (params) => { let base = { @@ -942,7 +897,7 @@ class Myr { /** * Render an Aframe octahedron with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ octahedron = (params) => { let base = { @@ -959,7 +914,8 @@ class Myr { /** * Render an Aframe line with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {string} path String of positions that represents the path in following format: "x1 y1 z1, x2 y2 z2,...,xn yn zn" + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ line = (path, params) => { let base = { @@ -978,7 +934,7 @@ class Myr { /** * Render an Aframe plane with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ plane = (params) => { let base = { @@ -995,7 +951,7 @@ class Myr { /** * Render an Aframe polyhedron with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ prism = (params) => { let base = { @@ -1012,7 +968,7 @@ class Myr { /** * Render an Aframe ring with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ ring = (params) => { let base = { @@ -1029,7 +985,7 @@ class Myr { /** * Render an Aframe sphere with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ sphere = (params) => { let base = { @@ -1046,7 +1002,7 @@ class Myr { /** * Render an Aframe tetrahedron with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ tetrahedron = (params) => { let base = { @@ -1066,6 +1022,9 @@ class Myr { * This is a bit tricky. We need to pass text so we can decide how to render it. * This throws a warning since text is not part of the entity system. * Instead we pass it and then pull it off again if we see it. + * + * @param {string} text Text to display + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ text = (text, params) => { if (typeof text !== "string") { @@ -1092,7 +1051,7 @@ class Myr { /** * Render an Aframe torus with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ torus = (params) => { let base = { @@ -1109,7 +1068,7 @@ class Myr { /** * Render an Aframe torusknot with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ torusknot = (params) => { let base = { @@ -1128,7 +1087,7 @@ class Myr { /** * Render an Aframe triangle with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ triangle = (params) => { let base = { @@ -1145,7 +1104,8 @@ class Myr { /** * Render an Aframe tube with current Myr settings * - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {string} path String of positions that represents the path in following format: "x1 y1 z1, x2 y2 z2,...,xn yn zn" + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib */ tube = (path, params) => { let base = { @@ -1161,11 +1121,12 @@ class Myr { return this.mergeProps(base, params); } - /** + + /** * Load and render a custom glTF model with current Myr settings * * @param {string} src Valid MYR model ID or valid glTF URL - * @param {*} params !!!DESCRIPTION NEEDED!!! + * @param {*} params Parameters that can overwrite the cursor attrib or add custom attrib */ gltfModel = (src, params) => { let id = `gltf-model-${this.genNewId()}`; @@ -1207,6 +1168,11 @@ class Myr { return this.mergeProps(base, params); } + /** + * Render an Ambient light with current cursor light settings + * + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib + */ ambientLight = (params) => { let base = { id: "lgt" + this.genNewId(), @@ -1226,6 +1192,11 @@ class Myr { return this.mergeProps(base, params); } + /** + * Render a Directional light with current cursor light settings + * + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib + */ directionalLight = (params) => { let base = { id: "lgt" + this.genNewId(), @@ -1245,6 +1216,11 @@ class Myr { return this.mergeProps(base, params); } + /** + * Render a Spot light with current cursor light settings + * + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib + */ spotLight = (params) => { let base = { id: "lgt" + this.genNewId(), @@ -1269,6 +1245,11 @@ class Myr { return this.mergeProps(base, params); } + /** + * Render an point light with current cursor light settings + * + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib + */ pointLight = (params) => { let base = { id: "lgt" + this.genNewId(), @@ -1291,7 +1272,12 @@ class Myr { return this.mergeProps(base, params); } - //secondColor == groundColor + /** + * Render an Hemisphere light with current cursor light settings + * + * @param {string} secondColor Secondary color for the hemisphere light + * @param {object} params Parameters that can overwrite the cursor attrib or add custom attrib + */ hemisphereLight = (secondColor="red",params) => { let base = { id: "lgt" + this.genNewId(), @@ -1312,7 +1298,11 @@ class Myr { return this.mergeProps(base, params); } - //beamAngle == angle + /** + * Set the extent of the spotlight + * + * @param {number} beamAngle Angle in degree + */ setBeamAngle=(beamAngle = 60)=>{ if(typeof beamAngle === "number"){ this.cursor.light.beamAngle = beamAngle; @@ -1321,7 +1311,12 @@ class Myr { } } - + + /** + * Set the decay of the light + * + * @param {number} decay Rate of light decay + */ setDecay = (decay = 0.0) =>{ if(typeof decay === "number"){ this.cursor.light.decay = decay; @@ -1330,6 +1325,11 @@ class Myr { } } + /** + * Set the distance of the light dims as it travels + * + * @param {number} distance Length which light dims + */ setDistance = (distance=0.0) =>{ if(typeof distance === "number"){ this.cursor.light.distance = distance; @@ -1337,6 +1337,12 @@ class Myr { console.error("must pass a numeric for setDistance"); } } + + /** + * Set the intensity of the light + * + * @param {number} intensity Number range from 0 to 10+ + */ setIntensity = (intensity = 1.0) =>{ if(typeof intensity === "number"){ this.cursor.light.intensity = intensity; @@ -1345,7 +1351,11 @@ class Myr { } } - //diffusion == penumbra + /** + * Set the diffusion(penumbra) around the edge of the light + * + * @param {number} diffusion Number range from 0 to 1 + */ setDiffusion = (diffusion = 0.0) => { if(typeof diffusion === "number"){ this.cursor.light.diffusion = diffusion; @@ -1354,6 +1364,13 @@ class Myr { } } + /** + * Set the position of where the lights are facing towards + * + * @param {number} x X Position + * @param {number} y Y Position + * @param {number} z Z Position + */ setLightTarget = (x = 0, y = 0, z = 0) => { if(typeof x === "number" && typeof y === "number" && typeof z === "number"){ this.cursor.light.target = { @@ -1368,37 +1385,13 @@ class Myr { /********************* ANIMATIONS *********************/ - /** - * Animate the Aframe element which is passed as arg - * - * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! - */ - animate = (outerElId, magnitude = null, loop = null, duration = null) => { - magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.spin; - loop = loop !== null ? loop : this.cursor.loop; - duration = duration !== null ? duration : this.cursor.duration; - let el = this.getEl(outerElId); - let anim = ` - property: rotation; - dir: alternate; - to: ${el.rotation.x} ${el.rotation.y + magnitude} ${el.rotation.z}; - dur: ${duration}; - loop: ${Boolean(loop)}; - `; - el.animation = anim; - return outerElId; - }; - /** * Apply a spin animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ spin = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.spin; @@ -1421,9 +1414,9 @@ class Myr { * Apply a yoyo animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ yoyo = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1443,11 +1436,11 @@ class Myr { /** * Apply a sideToSide animation to the Aframe element which is passed as arg - * + * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ sideToSide = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1470,9 +1463,9 @@ class Myr { * Apply a goUp animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ goUp = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1494,9 +1487,9 @@ class Myr { * Apply a goDown animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ goDown = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1518,9 +1511,9 @@ class Myr { * Apply a goLeft animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ goLeft = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1542,9 +1535,9 @@ class Myr { * Apply a goRight animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ goRight = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1566,9 +1559,9 @@ class Myr { * Apply a goTowards animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ goTowards = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1590,9 +1583,9 @@ class Myr { * Apply a goAway animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ goAway = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1614,9 +1607,9 @@ class Myr { * Apply a grow animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ grow = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1663,9 +1656,9 @@ class Myr { * Apply a shrink animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ shrink = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1714,9 +1707,9 @@ class Myr { * Apply a fadeOut animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ fadeOut = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.fadeOut; @@ -1754,9 +1747,9 @@ class Myr { * Apply a fadeIn animation to the Aframe element which is passed as arg * * @param {number} outerElId target element ID - * @param {number} magnitude !!!DESCRIPTION NEEDED!!! - * @param {*} loop !!!DESCRIPTION NEEDED!!! - * @param {*} duration !!!DESCRIPTION NEEDED!!! + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last */ fadeIn = (outerElId, magnitude = null, loop = null, duration = null) => { magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.general; @@ -1790,30 +1783,12 @@ class Myr { return outerElId; } - colourNameToHex=(colour)=> - { - let colours = {"aliceblue":"#f0f8ff","antiquewhite":"#faebd7","aqua":"#00ffff","aquamarine":"#7fffd4","azure":"#f0ffff", - "beige":"#f5f5dc","bisque":"#ffe4c4","black":"#000000","blanchedalmond":"#ffebcd","blue":"#0000ff","blueviolet":"#8a2be2","brown":"#a52a2a","burlywood":"#deb887", - "cadetblue":"#5f9ea0","chartreuse":"#7fff00","chocolate":"#d2691e","coral":"#ff7f50","cornflowerblue":"#6495ed","cornsilk":"#fff8dc","crimson":"#dc143c","cyan":"#00ffff", - "darkblue":"#00008b","darkcyan":"#008b8b","darkgoldenrod":"#b8860b","darkgray":"#a9a9a9","darkgreen":"#006400","darkkhaki":"#bdb76b","darkmagenta":"#8b008b","darkolivegreen":"#556b2f", - "darkorange":"#ff8c00","darkorchid":"#9932cc","darkred":"#8b0000","darksalmon":"#e9967a","darkseagreen":"#8fbc8f","darkslateblue":"#483d8b","darkslategray":"#2f4f4f","darkturquoise":"#00ced1", - "darkviolet":"#9400d3","deeppink":"#ff1493","deepskyblue":"#00bfff","dimgray":"#696969","dodgerblue":"#1e90ff", - "firebrick":"#b22222","floralwhite":"#fffaf0","forestgreen":"#228b22","fuchsia":"#ff00ff","gainsboro":"#dcdcdc","ghostwhite":"#f8f8ff","gold":"#ffd700","goldenrod":"#daa520","gray":"#808080","green":"#008000","greenyellow":"#adff2f", - "honeydew":"#f0fff0","hotpink":"#ff69b4","indianred ":"#cd5c5c","indigo":"#4b0082","ivory":"#fffff0","khaki":"#f0e68c", - "lavender":"#e6e6fa","lavenderblush":"#fff0f5","lawngreen":"#7cfc00","lemonchiffon":"#fffacd","lightblue":"#add8e6","lightcoral":"#f08080","lightcyan":"#e0ffff","lightgoldenrodyellow":"#fafad2", - "lightgrey":"#d3d3d3","lightgreen":"#90ee90","lightpink":"#ffb6c1","lightsalmon":"#ffa07a","lightseagreen":"#20b2aa","lightskyblue":"#87cefa","lightslategray":"#778899","lightsteelblue":"#b0c4de", - "lightyellow":"#ffffe0","lime":"#00ff00","limegreen":"#32cd32","linen":"#faf0e6","magenta":"#ff00ff","maroon":"#800000","mediumaquamarine":"#66cdaa","mediumblue":"#0000cd","mediumorchid":"#ba55d3","mediumpurple":"#9370d8","mediumseagreen":"#3cb371","mediumslateblue":"#7b68ee", - "mediumspringgreen":"#00fa9a","mediumturquoise":"#48d1cc","mediumvioletred":"#c71585","midnightblue":"#191970","mintcream":"#f5fffa","mistyrose":"#ffe4e1","moccasin":"#ffe4b5","navajowhite":"#ffdead","navy":"#000080", - "oldlace":"#fdf5e6","olive":"#808000","olivedrab":"#6b8e23","orange":"#ffa500","orangered":"#ff4500","orchid":"#da70d6", - "palegoldenrod":"#eee8aa","palegreen":"#98fb98","paleturquoise":"#afeeee","palevioletred":"#d87093","papayawhip":"#ffefd5","peachpuff":"#ffdab9","peru":"#cd853f","pink":"#ffc0cb","plum":"#dda0dd","powderblue":"#b0e0e6","purple":"#800080", - "rebeccapurple":"#663399","red":"#ff0000","rosybrown":"#bc8f8f","royalblue":"#4169e1","saddlebrown":"#8b4513","salmon":"#fa8072","sandybrown":"#f4a460","seagreen":"#2e8b57","seashell":"#fff5ee","sienna":"#a0522d","silver":"#c0c0c0","skyblue":"#87ceeb","slateblue":"#6a5acd","slategray":"#708090","snow":"#fffafa","springgreen":"#00ff7f","steelblue":"#4682b4", - "tan":"#d2b48c","teal":"#008080","thistle":"#d8bfd8","tomato":"#ff6347","turquoise":"#40e0d0","violet":"#ee82ee","wheat":"#f5deb3","white":"#ffffff","whitesmoke":"#f5f5f5","yellow":"#ffff00","yellowgreen":"#9acd32"}; - - if (typeof colours[colour.toLowerCase()] !== "undefined"){ - return colours[colour.toLowerCase()]; - } - return false; - } + /** + * Apply a colorShift animation toe the Aframe element + * + * @param {string} outerElId target element id + * @param {string} color Color the light shift it to + */ colorShift = (outerElId, color) => { let el = this.getEl(outerElId); //if the element is light @@ -1870,6 +1845,37 @@ class Myr { return outerElId; } + /** + * Change the html color code to the hexadecimal + * + * @param {string} colour HTML color code + * + * @returns {string} Hexadecimal representation of the color, return false if color not found. + */ + colourNameToHex=(colour)=> + { + const colours = {"aliceblue":"#f0f8ff","antiquewhite":"#faebd7","aqua":"#00ffff","aquamarine":"#7fffd4","azure":"#f0ffff", + "beige":"#f5f5dc","bisque":"#ffe4c4","black":"#000000","blanchedalmond":"#ffebcd","blue":"#0000ff","blueviolet":"#8a2be2","brown":"#a52a2a","burlywood":"#deb887", + "cadetblue":"#5f9ea0","chartreuse":"#7fff00","chocolate":"#d2691e","coral":"#ff7f50","cornflowerblue":"#6495ed","cornsilk":"#fff8dc","crimson":"#dc143c","cyan":"#00ffff", + "darkblue":"#00008b","darkcyan":"#008b8b","darkgoldenrod":"#b8860b","darkgray":"#a9a9a9","darkgreen":"#006400","darkkhaki":"#bdb76b","darkmagenta":"#8b008b","darkolivegreen":"#556b2f", + "darkorange":"#ff8c00","darkorchid":"#9932cc","darkred":"#8b0000","darksalmon":"#e9967a","darkseagreen":"#8fbc8f","darkslateblue":"#483d8b","darkslategray":"#2f4f4f","darkturquoise":"#00ced1", + "darkviolet":"#9400d3","deeppink":"#ff1493","deepskyblue":"#00bfff","dimgray":"#696969","dodgerblue":"#1e90ff", + "firebrick":"#b22222","floralwhite":"#fffaf0","forestgreen":"#228b22","fuchsia":"#ff00ff","gainsboro":"#dcdcdc","ghostwhite":"#f8f8ff","gold":"#ffd700","goldenrod":"#daa520","gray":"#808080","green":"#008000","greenyellow":"#adff2f", + "honeydew":"#f0fff0","hotpink":"#ff69b4","indianred ":"#cd5c5c","indigo":"#4b0082","ivory":"#fffff0","khaki":"#f0e68c", + "lavender":"#e6e6fa","lavenderblush":"#fff0f5","lawngreen":"#7cfc00","lemonchiffon":"#fffacd","lightblue":"#add8e6","lightcoral":"#f08080","lightcyan":"#e0ffff","lightgoldenrodyellow":"#fafad2", + "lightgrey":"#d3d3d3","lightgreen":"#90ee90","lightpink":"#ffb6c1","lightsalmon":"#ffa07a","lightseagreen":"#20b2aa","lightskyblue":"#87cefa","lightslategray":"#778899","lightsteelblue":"#b0c4de", + "lightyellow":"#ffffe0","lime":"#00ff00","limegreen":"#32cd32","linen":"#faf0e6","magenta":"#ff00ff","maroon":"#800000","mediumaquamarine":"#66cdaa","mediumblue":"#0000cd","mediumorchid":"#ba55d3","mediumpurple":"#9370d8","mediumseagreen":"#3cb371","mediumslateblue":"#7b68ee", + "mediumspringgreen":"#00fa9a","mediumturquoise":"#48d1cc","mediumvioletred":"#c71585","midnightblue":"#191970","mintcream":"#f5fffa","mistyrose":"#ffe4e1","moccasin":"#ffe4b5","navajowhite":"#ffdead","navy":"#000080", + "oldlace":"#fdf5e6","olive":"#808000","olivedrab":"#6b8e23","orange":"#ffa500","orangered":"#ff4500","orchid":"#da70d6", + "palegoldenrod":"#eee8aa","palegreen":"#98fb98","paleturquoise":"#afeeee","palevioletred":"#d87093","papayawhip":"#ffefd5","peachpuff":"#ffdab9","peru":"#cd853f","pink":"#ffc0cb","plum":"#dda0dd","powderblue":"#b0e0e6","purple":"#800080", + "rebeccapurple":"#663399","red":"#ff0000","rosybrown":"#bc8f8f","royalblue":"#4169e1","saddlebrown":"#8b4513","salmon":"#fa8072","sandybrown":"#f4a460","seagreen":"#2e8b57","seashell":"#fff5ee","sienna":"#a0522d","silver":"#c0c0c0","skyblue":"#87ceeb","slateblue":"#6a5acd","slategray":"#708090","snow":"#fffafa","springgreen":"#00ff7f","steelblue":"#4682b4", + "tan":"#d2b48c","teal":"#008080","thistle":"#d8bfd8","tomato":"#ff6347","turquoise":"#40e0d0","violet":"#ee82ee","wheat":"#f5deb3","white":"#ffffff","whitesmoke":"#f5f5f5","yellow":"#ffff00","yellowgreen":"#9acd32"}; + + if (typeof colours[colour.toLowerCase()] !== "undefined"){ + return colours[colour.toLowerCase()]; + } + return false; + } /********************* GETTERS *********************/ /** @@ -1993,26 +1999,6 @@ class Myr { return this.cursor.magnitude.general; }; - - - // MODELS - addCModel = () => { - let asset = { - id: "c-obj", - src: "/img/c.obj" - }; - let el = { - "obj-model": "obj: #c-obj", - mtl: "c-mtl", - position: this.cursor.position, - scale: this.cursor.scale, - rotation: this.cursor.rotation - }; - this.els.push(el); - this.assets.push(asset); - return el; - } - /** * Gets the element associated with the given element ID * @@ -2025,40 +2011,6 @@ class Myr { return this.els[outerElId]; } - /** - * Interface for setting an object's parameters in the DOM - * the idea is the setup an event listener as an almost DOM ready listener. - * - * @param {string} outerElId target element ID - * @param {string} type what param to change - * @param {*} newParam changes - */ - change = (outerElId, type, newParam) => { - document.addEventListener("myr-view-rendered", () => { - try { - let el = document.querySelector("#" + outerElId); - el.setAttribute(type, newParam); - } catch (error) { - return Error("change() failed execution" + - "Ensure you are passing the proper id to the method" + - `Error msg: ${error}`); - } - }); - } - - syncChange = (outerElId, type, newParam) => { - try { - let el = document.querySelector("#" + outerElId); - el.setAttribute(type, newParam); - } catch (error) { - let err = Error("syncChange() failed execution\n" + - "Ensure you are passing the proper id to the method" + - `Error msg: ${error}`); - console.error(err); - return err; - } - } - /** * This creates an entity w shape of object and merges with supplied params * @@ -2075,10 +2027,6 @@ class Myr { return id; } - sleep = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); - } - /** * Return a Entity that can be used to group elements together */ @@ -2095,9 +2043,9 @@ class Myr { } /** - * Transfer the object from MYR to the Entity + * Transfer the object from MYR to the Entity. Used to add entity to the group * - * @param {number} id !!!DESCRIPTION NEEDED!!! + * @param {string} id Entity id to remove from list and return */ transfer = (id) => { let retVal = this.els[id]; @@ -2105,20 +2053,140 @@ class Myr { return retVal; } - HALT = () => { - // console.log(this); - // console.log("Halted"); + /* + * Functions that are not in reference or used in anywhere + */ + /** + * Animate the Aframe element which is passed as arg, its same as spin but without linear easing + * + * @param {number} outerElId target element ID + * @param {number} magnitude Magnitude of the animation + * @param {boolean} loop Whether to loop the animation + * @param {number} duration How long the animation last + */ + animate = (outerElId, magnitude = null, loop = null, duration = null) => { + magnitude = magnitude !== null ? magnitude : this.cursor.magnitude.spin; + loop = loop !== null ? loop : this.cursor.loop; + duration = duration !== null ? duration : this.cursor.duration; + let el = this.getEl(outerElId); + let anim = ` + property: rotation; + dir: alternate; + to: ${el.rotation.x} ${el.rotation.y + magnitude} ${el.rotation.z}; + dur: ${duration}; + loop: ${Boolean(loop)}; + `; + el.animation = anim; + return outerElId; + }; + + /** + * It looks like a promise that sleep for certain ms and user can set further action after the time out. + * I don't know the original purpose but I imagine it was something like this. + * ex. + * sleep(5000).then(()=>{ + * console.log("box!"); + * box(); + * }); + * But this will not render box on the scene because it adds the box to the list after Scene is renderered + * + * @param {number} ms how long to sleep in ms + * @returns + */ + sleep = (ms) => { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + /** + * Looks like temporary function similar to makePushable that apply force the pass object to x,y,z direction + * Not working. + */ + push = (outerElId, x, y, z) => { + // Add an event listener + document.addEventListener("myr-view-rendered", () => { + let el = document.querySelector("#" + outerElId); + if (!el) { + return; + } + el.addEventListener("body-loaded", () => { + el.body.applyImpulse( + /* impulse */ new CANNON.Vec3(x, y, z), + /* world position */ new CANNON.Vec3().copy(el.object3D.position) + ); + }); + }); + return outerElId; + } + + /** + * Looks like a temporary function that just apply physics with constant mass + * + * @param {string} outerElId + * @returns {string} outerElId + */ + drop = (outerElId) => { + this.getEl(outerElId)["dynamic-body"] = "shape: box; mass: 5"; + return outerElId; + } + + /** + * Interface for setting an object's parameters in the DOM + * the idea is the setup an event listener as an almost DOM ready listener. + * + * Ex. change(box(),"material","color:green;"); + * + * @param {string} outerElId target element ID + * @param {string} type what param to change + * @param {*} newParam changes + * @returns {Error} Return error if query fail to retrieve the passed Id + */ + change = (outerElId, type, newParam) => { + document.addEventListener("myr-view-rendered", () => { + try { + let el = document.querySelector("#" + outerElId); + el.setAttribute(type, newParam); + } catch (error) { + return Error("change() failed execution" + + "Ensure you are passing the proper id to the method" + + `Error msg: ${error}`); + } + }); + } + + /** + * Interface for setting an object's parameters in the DOM w/o the event listener dispatching the events + * It's not working/I don't know how this work" + * + * @param {string} outerElId target element ID + * @param {string} type what param to change + * @param {*} newParam changes + * @returns {Error} Return error if query fail to retrieve the passed Id + */ + syncChange = (outerElId, type, newParam) => { + try { + let el = document.querySelector("#" + outerElId); + el.setAttribute(type, newParam); + } catch (error) { + let err = Error("syncChange() failed execution\n" + + "Ensure you are passing the proper id to the method" + + `Error msg: ${error}`); + console.error(err); + return err; + } } + /** + * Infinite loop detector that's not use in anywhere + */ infiniteLoopDetector = (function () { let map = {}; - + // define an InfiniteLoopError class function InfiniteLoopError(msg) { Error.call(this, msg); this.type = "InfiniteLoopError"; } - + function infiniteLoopDetector(id) { if (id in map) { if (Date.now() - map[id] > 200) { diff --git a/src/myr/modelReference.js b/src/myr/modelReference.js index 0e7e2e90..b395fd9b 100644 --- a/src/myr/modelReference.js +++ b/src/myr/modelReference.js @@ -1,3 +1,6 @@ +/** + * List of model reference + */ const model = [ { name: "sword", @@ -29,4 +32,4 @@ const model = [ }, ]; -export default model; \ No newline at end of file +export default model; diff --git a/src/myr/reference.js b/src/myr/reference.js index fc31b920..2a5847d6 100644 --- a/src/myr/reference.js +++ b/src/myr/reference.js @@ -5,6 +5,9 @@ import { withStyles } from "@material-ui/core"; +/** + * Custom styles that inject to the cue cards + */ const HtmlTooltip = withStyles(theme => ({ tooltip: { maxWidth: 300, @@ -19,6 +22,9 @@ const handleAssetReferenceOpen = (isTexture = false) => { window.open(window.origin + "/asset-reference" + (isTexture ? "?tab=textures" : "")); }; +/** + * Return a react elements contain a cue-card for String data type + */ export const stringText = (text) => { return ( { ); }; + +/** + * Return a react elements contain a cue-card for Number data type + */ export const numberText = (text) => { return ( { ); }; + +/** + * Return a react elements contain a cue-card for Boolean data type + */ export const boolText = (text) => { return ( { ); }; +/** + * Return a react elements contain a cue-card for Array data type + */ export const arrayText = (text) => { return ( { ); }; +/** + * Return a react elements contain a cue-card for dynamic data type + */ export const dataText = (text) => { return ( { ); }; -let geometry = [ +/** + * List of geometry reference + */ +const geometry = [ { name: "box", parameters: [], @@ -172,11 +195,6 @@ let geometry = [ description: The octahedron function makes a polyhedron with eight equilateral triangular faces using the current cursor attributes. This function returns an {stringText("elementID")}., example: "octahedron" }, - // This is out temporarily until better fleshed out - //{ - // name: 'line()', - // description: Renders a line using current internal cursor properties. Returns an element id. - //}, { name: "plane", parameters: [], @@ -237,26 +255,34 @@ let geometry = [ description: The gltfModel function loads a glTF model using the current cursor attributes. This function returns an {stringText("elementID")}. Models can be loaded either by using the name of one of or by inserting a valid url (e.g. "duck" or "https://learnmyr.org/models/duck.glb"). Depending on the policy of the website they’re from, model URLs may not be usable, which will result in no model appearing., example: "model" }, + // This is out temporarily until better fleshed out //{ - // name: tube(), - // description: Renders a tube using current internal cursor properties. Returns an element id., - // example: 'tube' + // name: 'line()', + // description: Renders a line using current internal cursor properties. Returns an element id. //}, - //should this be documented? // { - // name: 'light()', - // description: Renders a light using current internal MYR properties. Returns an element id. + // name: tube(), + // parameters:[], + // description: Renders a tube using current internal cursor properties. Returns an element id., + // example: "tube" // }, - ]; -let transformations = [ +/** + * List of transformation reference + */ +const transformations = [ { name: "resetCursor", parameters: [], description: The resetCursor function resets the properties of the cursor to their defaults. This includes cursor attributes pertaining to Transformations and Animations., example: "resetCursor" }, + { + name: "resetTransformationCursor", + parameters: [], + description: The resetTransformationCursor function resets the transformation properties of the cursor to their defaults., + }, { name: "setColor", parameters: [{ type: "string", name: "color" }], @@ -497,10 +523,13 @@ let transformations = [ name: "resetTransformationCursor", parameters: [], description: The resetTransformationCursor function resets the transformation properties of the cursor to their defaults., - }, + } ]; -let animations = [ +/** + * List of animation reference + */ +const animations = [ { name: "setLoop", parameters: [{ type: "bool", name: "loop" }], @@ -534,6 +563,11 @@ let animations = [ parameters: [], description: The getMagnitude function returns the current magnitude attribute of the cursor. The magnitude can be changed by the setMagnitude function. }, + { + name: "resetAnimationCursor", + parameters: [], + description: The resetAnimationCursor function resets the properties of the cursor that contains animation properties to their defaults., + }, { name: "spin", parameters: [{ type: "string", name: "elementID" }], @@ -617,66 +651,18 @@ let animations = [ parameters: [{ type: "string", name: "elementID" }, { type: "string", name: "color" }], description: The colorShift function shifts the element from its original color to the given color. All colors valid for setColor are applicable., example: "colorShift" - }, + } +]; + +/** + * List of light reference + */ +const lights = [ { - name: "resetAnimationCursor", + name: "resetLightCursor", parameters: [], - description: The resetAnimationCursor function resets the properties of the cursor that contains animation properties to their defaults., + description: The resetLightCursor function resets the properties of the cursor that contains light properties to their defaults. }, - // { - // name: spin(element, magnitude, loop, duration), - // description: Spins the element around the y axis magnitude degrees. - // }, - // { - // name: yoyo(element, magnitude, loop, duration), - // description: Bounces the element magnitude units in a positive direction on the y axis for duration milliseconds. - // }, - // { - // name: sideToSide(element, magnitude, loop, duration), - // description: Shifts the element magnitude units in a negative direction on the x axis and back to the original coordinate over duration milliseconds. - // }, - // { - // name: goUp(element, magnitude, loop, duration), - // description: Translates the element magnitude units in a positive direction on the y axis over duration milliseconds. - // }, - // { - // name: goDown(element, magnitude, loop, duration), - // description: Translates the element magnitude units in a negative direction on the y axis over duration milliseconds. - // }, - // { - // name: goRight(element, magnitude, loop, duration), - // description: Translates the element magnitude units in a positive direction on the x axis over duration milliseconds. - // }, - // { - // name: goLeft(element, magnitude, loop, duration), - // description: Translates the element magnitude units in a negative direction on the x axis over duration milliseconds. - // }, - // { - // name: goTowards(element, magnitude, loop, duration), - // description: Translates the element magnitude units in a positive direction on the z axis over duration milliseconds. - // }, - // { - // name: goAway(element, magnitude, loop, duration), - // description: Translates the element magnitude units in a negative direction on the z axis over duration milliseconds. - // }, - // { - // name: grow(element, magnitude, loop, duration), - // description: Scales the element by a magnitude multiplier over duration milliseconds. - // }, - // { - // name: shrink(element, magnitude, loop, duration), - // description: Scales the element by a 1/magnitude multiplier over duration milliseconds. - // }, - // { - // name: fadeOut(element, magnitude, loop, duration), - // description: Modifies transparency from 1 to magnitude [0,1) over duration milliseconds. - // }, - // { - // name: fadeIn(element, magnitude, loop, duration), - // description: Modifies transparency from 0 to magnitude (0,1] over duration milliseconds. - // }, -]; -let lights = [ { name: "ambientLight", parameters: [], @@ -731,15 +717,13 @@ let lights = [ name: "setLightTarget", parameters: [{ type: "number", name: "x" }, { type: "number", name: "y" }, { type: "number", name: "z" }], description: The setLightTarget function sets the point where the light should be pointed to. The default values are x:0, y:0, z:0. - }, - { - name: "resetLightCursor", - parameters: [], - description: The resetLightCursor function resets the properties of the cursor that contains light properties to their defaults. - }, + } ]; -let groups = [ +/** + * List of group reference + */ +const groups = [ { name: let myGroup = group, parameters: [], @@ -779,6 +763,9 @@ let groups = [ ]; +/** + * Combine lists of refence to single object + */ const reference = { geometry: geometry, transformations: transformations, diff --git a/src/myr/textureReference.js b/src/myr/textureReference.js index a05e62ab..eeefe3b5 100644 --- a/src/myr/textureReference.js +++ b/src/myr/textureReference.js @@ -1,3 +1,6 @@ +/** + * List of texture reference + */ const texture = [ { name: "bricks", @@ -97,4 +100,4 @@ const texture = [ ]; -export default texture; \ No newline at end of file +export default texture; diff --git a/src/myr/tour.js b/src/myr/tour.js index 9add7ad4..45f80d05 100644 --- a/src/myr/tour.js +++ b/src/myr/tour.js @@ -1,3 +1,7 @@ +/** + * Selector: Where to position the tour card. + * Content : Content to display + */ export const TourSteps = [ { selector: "#ace-editor", diff --git a/src/reducers/collections.js b/src/reducers/collections.js index ea674afb..fea52c20 100644 --- a/src/reducers/collections.js +++ b/src/reducers/collections.js @@ -5,19 +5,25 @@ const initial_state = { collection: [] }; +/** + * Collection Reducer + */ export default function classes(state = initial_state, action) { switch (action.type) { - case types.SYNC_CLASSES: + //Update list of collections + case types.SYNC_COLLECTIONS: return { ...state, collections: action.payload }; - case types.SYNC_CLASS: + //Load a collection + case types.SYNC_COLLECTION: return { ...state, collection: action.payload }; - case types.DELETE_CLASS: + //Delete the collection from list + case types.DELETE_COLLECTION: let userClasses = []; userClasses = state.collections.filter(x => { return x._id !== action.id; diff --git a/src/reducers/course.js b/src/reducers/course.js index 2da85a6f..8f86bafa 100644 --- a/src/reducers/course.js +++ b/src/reducers/course.js @@ -12,19 +12,25 @@ const initial_state = { } }; +/** + * Course Reducer + */ export default function course(state = initial_state, action) { let payload; switch (action.type) { + //Update list of courses case types.SYNC_COURSES: return { ...state, courses: action.payload }; + //Load a course case types.LOAD_COURSE: return { ...state, course: action.payload }; + //Load a lesson case types.LOAD_LESSON: payload = action.payload; return { @@ -36,6 +42,7 @@ export default function course(state = initial_state, action) { code: payload.code } }; + //Set the index for the current lesson (Where the lesson is) case types.SET_INDEX: return { ...state, diff --git a/src/reducers/editor.js b/src/reducers/editor.js index 692f1bdd..1fafc3b6 100644 --- a/src/reducers/editor.js +++ b/src/reducers/editor.js @@ -25,13 +25,14 @@ let snapshots = [ ]; -let m = new Myr(); +const m = new Myr(); m.init(); // window.m = m; // Use this to attach it to the window for debugging /** - * ESLint doesn't like this but it is better than eval - * @param {*} text !!!DESCRIPTION NEEDED!!! + * Conver the MYR code supplied from the editor to a function so it can be executed + * ESLint doesn't like this but it is better than eval + * @param {string} text MYR code supplied from editor */ function noEvalEvaluation(text) { // eslint-disable-next-line @@ -41,8 +42,13 @@ function noEvalEvaluation(text) { return func; } + +/** + * Editor Reducer + */ export default function editor(state = initial_state, action) { switch (action.type) { + //Handles the evaluation of the MYR code in editor case types.EDITOR_RENDER: m.reset(); @@ -85,7 +91,7 @@ export default function editor(state = initial_state, action) { assets: m.assets || [], message }; - + //Update the text editor case types.EDITOR_REFRESH: m.reset(); return { @@ -93,7 +99,7 @@ export default function editor(state = initial_state, action) { text: action.text, savedText: state.savedText, }; - + //Recover the code case types.EDITOR_RECOVER: // Start at last snap let stableIndex = snapshots.length - 1; @@ -104,7 +110,7 @@ export default function editor(state = initial_state, action) { // Call editor function again with new params return editor({ ...state }, { type: types.EDITOR_RENDER, text: snapshots[stableIndex].text }); - + //Update save text. savedText use to check whether user made changes to the scene case types.EDITOR_UPDATE_SAVEDTEXT: return { ...state, diff --git a/src/reducers/index.js b/src/reducers/index.js index d453347a..fdc895c6 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -10,6 +10,9 @@ import referenceExample from "./referenceExample"; import thunk from "redux-thunk"; +/** + * @summary This combines all the reducers into a single reducer so it can pass it into store + */ const reducer = combineReducers({ editor, user, @@ -20,8 +23,15 @@ const reducer = combineReducers({ referenceExample }); +/** + * @summary Add third parties library along with the redux compose so it can use with other middleware and enhancers + * Redux devtools extension shows history of the changes to the redux store overtime when debugging. + */ const composeEnhancers = (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true, traceLimit: 25 })) || compose; +/** + * @summary Create a store with the combined reducers and enhancers + */ const store = createStore( reducer, composeEnhancers(applyMiddleware(thunk)) diff --git a/src/reducers/project.js b/src/reducers/project.js index 44bc2307..deebe99b 100644 --- a/src/reducers/project.js +++ b/src/reducers/project.js @@ -5,18 +5,24 @@ const initial_state = { exampleProjs: [] }; +/** + * Project Reducers + */ export default function project(state = initial_state, action) { switch (action.type) { + //Update the list of user projects case types.SYNC_USER_PROJ: return { ...state, userProjs: action.payload }; + //Update the list of example projects case types.SYNC_EXAMP_PROJ: return { ...state, exampleProjs: action.payload }; + //Delete a specific user project case types.DELETE_PROJ: let projs = []; projs = state.userProjs.filter(x => { diff --git a/src/reducers/referenceExample.js b/src/reducers/referenceExample.js index 26fe8126..4ad9d85a 100644 --- a/src/reducers/referenceExample.js +++ b/src/reducers/referenceExample.js @@ -10,8 +10,13 @@ const initial_state = { code: "//Loading" }; + +/** + * Reference Example reducer + */ export default function referenceExample(state = initial_state, action) { switch (action.type) { + //Load specific example scene supplied case types.LOAD_REF_EX: return { ...state, diff --git a/src/reducers/scene.js b/src/reducers/scene.js index 6e1fdf21..92b313a0 100644 --- a/src/reducers/scene.js +++ b/src/reducers/scene.js @@ -25,7 +25,9 @@ const initial_state = { }; - +/** + * Scene Reducers + */ export default function scene(state = initial_state, action) { if (state.settings.name) { delete state.settings.name; @@ -34,15 +36,18 @@ export default function scene(state = initial_state, action) { delete state.settings.id; } switch (action.type) { + //Update the name of the scene case types.NAME_SCENE: return { ...state, name: action.name }; + //Load a new scene case types.LOAD_SCENE: return { ...action.data }; + //Toggle the grid case types.TOGGLE_COORD_SKY: return { ...state, @@ -51,6 +56,7 @@ export default function scene(state = initial_state, action) { showCoordHelper: !state.settings.showCoordHelper } }; + //Update the position of the camera case types.SET_CAMERA: let camPos = `${action.x || 0} ${action.y + (Math.random() / 10) || 1.6} ${action.z || 0}`; return { @@ -60,6 +66,7 @@ export default function scene(state = initial_state, action) { cameraPosition: camPos } }; + //Toggle the viewOnly mode case types.CHANGE_VIEW: return { ...state, @@ -68,6 +75,7 @@ export default function scene(state = initial_state, action) { viewOnly: !state.settings.viewOnly } }; + //Update the color of sky case types.CHANGE_SKY_COLOR: return { ...state, @@ -76,6 +84,7 @@ export default function scene(state = initial_state, action) { skyColor: action.color } }; + //Update the color of floor case types.CHANGE_FLOOR_COLOR: return { ...state, @@ -84,6 +93,7 @@ export default function scene(state = initial_state, action) { floorColor: action.color } }; + //Toggle the floor case types.TOGGLE_FLOOR: return { ...state, @@ -92,64 +102,85 @@ export default function scene(state = initial_state, action) { showFloor: !state.settings.showFloor } }; - case types.ADD_CLASSROOM: + //Toggle the default light + case types.TOGGLE_DEFAULT_LIGHT: return { ...state, settings: { ...state.settings, - collectionID: action.payload + defaultLight: !state.settings.defaultLight } }; - case types.REMOVE_CLASSROOM: + //Toggle the cast of shadow + case types.TOGGLE_CAST_SHADOW: return { ...state, settings: { ...state.settings, - collectionID: null + castShadow: !state.settings.castShadow } }; - case types.LOAD_SETTINGS: + //Toggle the light indicator + case types.TOGGLE_LIGHT_INDICATOR: + return{ + ...state, + settings:{ + ...state.settings, + lightIndicator: !state.settings.lightIndicator + } + }; + //Add the scene to the collection + case types.ADD_COLLECTION: return { ...state, settings: { ...state.settings, - ...action.payload + collectionID: action.payload + } + }; + //Remove the scene from the collection + case types.REMOVE_COLLECTION: + return { + ...state, + settings: { + ...state.settings, + collectionID: null } }; + //Set the description of the scene case types.SET_DESC: return { ...state, desc: action.payload }; + //Set the name and the description of the scene case types.SET_NAME_DESC: return { ...state, name: action.payload.name, desc: action.payload.desc }; - case types.CHANGE_SETTINGS: - const { param, val } = action.payload; + //Load the scene settings + case types.LOAD_SETTINGS: return { ...state, settings: { ...state.settings, - [param]: val + ...action.payload } }; - case types.RESET_SETTINGS: - return { - ...state, - settings: DEF_SETTINGS - }; - case types.TOGGLE_DEFAULT_LIGHT: + //Update the specific scene settings + case types.CHANGE_SETTINGS: + const { param, val } = action.payload; return { ...state, settings: { ...state.settings, - defaultLight: !state.settings.defaultLight + [param]: val } }; - case types.TOGGLE_CAST_SHADOW: + //Reset the settings to the default + case types.RESET_SETTINGS: return { ...state, settings: { @@ -157,14 +188,6 @@ export default function scene(state = initial_state, action) { castShadow: !state.settings.castShadow } }; - case types.TOGGLE_LIGHT_INDICATOR: - return { - ...state, - settings: { - ...state.settings, - lightIndicator: !state.settings.lightIndicator - } - }; case types.UPDATE_MOVE_SPEED: return { ...state, diff --git a/src/reducers/user.js b/src/reducers/user.js index 0125f486..3f10b511 100644 --- a/src/reducers/user.js +++ b/src/reducers/user.js @@ -4,16 +4,22 @@ const initial_state = { user: null, }; +/** + * User Reducers + */ export default function user(state = initial_state, action) { switch (action.type) { + //Save user data to state case types.LOGIN: return { user: action.user }; + //Remove user data from state case types.LOGOUT: return { user: null }; + //Assign new token to the uid case types.REFRESH_TOKEN: return { user: { diff --git a/src/routes.js b/src/routes.js index 2ebbf49a..38ccb437 100644 --- a/src/routes.js +++ b/src/routes.js @@ -7,6 +7,10 @@ import Reference from "./containers/Reference"; import AssetReferencePage from "./containers/AssetReference"; import ReferenceExample from "./containers/ReferenceExample"; +/** + * Create an routers that switch to correct react component for different endpoints + * @returns BrowserRouter with all of available router (except about page) + */ const router = () => { return ( diff --git a/src/tests/Myr.test.js b/src/tests/Myr.test.js index 8c336213..c2cfbcea 100644 --- a/src/tests/Myr.test.js +++ b/src/tests/Myr.test.js @@ -752,13 +752,6 @@ describe("Component Animations", () => { }); describe("Other Myr functionality", () => { - it("should add a model", () => { - myr.reset(); - myr.assets = []; - myr.addCModel(); - expect(myr.assets).toContainEqual({ id: "c-obj", src: "/img/c.obj" }); - }); - it("should drop", () => { myr.reset(); let el = myr.box({ material: "color: blue;", position: { x: 1, y: 1, z: 1 } }); diff --git a/src/utils/AFramePhysics.js b/src/utils/AFramePhysics.js index 2de146ff..88ee6c18 100644 --- a/src/utils/AFramePhysics.js +++ b/src/utils/AFramePhysics.js @@ -1,6 +1,9 @@ import AFRAME from "aframe"; const THREE = AFRAME.THREE; +/** + * @summary Added a pushable effect to the MYR entities + */ AFRAME.registerComponent("force-pushable", { schema: { force: { @@ -26,39 +29,9 @@ AFRAME.registerComponent("force-pushable", { } }); - -//change the type of the material to the MeshBasicMaterial -AFRAME.registerComponent("basicmaterial",{ - schema:{ - default:"" - }, - init: function(){ - const color = this.el.getObject3D("mesh").material.color; - this.el.getObject3D("mesh").material = new THREE.MeshBasicMaterial({ - color:color, - }); - } -}); - -//change the material of a-grid to MeshBasicMaterial -AFRAME.registerComponent("gridmaterial",{ - schema:{ - default:"" - }, - init: function(){ - const texture = new THREE.TextureLoader().load("/img/grid_alpha_0.png"); - texture.repeat = new THREE.Vector2(75,75); - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; - - this.el.getObject3D("mesh").material = new THREE.MeshBasicMaterial({ - map: texture, - transparent: true - }); - } -}); - -//This sets the side where the shadow should be rendered +/** + * @summary This sets the side where the shadow should be cast on entity + */ AFRAME.registerComponent("shadowcustomsetting", { schema:{ default:"" @@ -83,21 +56,11 @@ AFRAME.registerComponent("shadowcustomsetting", { }, }); -//This change necessary properties to entity to create a outline to light indicator -AFRAME.registerComponent("outline",{ - schema:{ - default:"" - }, - init: function(){ - let mesh = this.el.getObject3D("mesh"); - let invertColor = ~mesh.material.color.getHex(); - - mesh.material.color.set(invertColor); - mesh.material.side = THREE.BackSide; - } -}); -//This calculate and sets the rotation of the entity based on 2 points +/** + * @summary Calculate and sets the rotation of the entity based on 2 points + * This is use for the light indicator that has the property of lighttarget (directional and spot light) + */ AFRAME.registerComponent("indicatorrotation",{ schema:{ position:{ diff --git a/src/utils/AframeRegIndicator.js b/src/utils/AframeRegIndicator.js index a2359b1c..10e5b165 100644 --- a/src/utils/AframeRegIndicator.js +++ b/src/utils/AframeRegIndicator.js @@ -2,6 +2,10 @@ import AFRAME from "aframe"; import * as THREE from "three"; import { BufferGeometryUtils } from "three/examples/jsm/utils/BufferGeometryUtils.js"; +/** + * @summary Define spotlight indicator geometry + * Shape: cone + */ AFRAME.registerComponent("spotlightindicator",{ schema:{ color:{ @@ -34,7 +38,6 @@ AFRAME.registerComponent("spotlightindicator",{ let outCone = new THREE.CylinderGeometry(.2,1,1.5,24,1,true); let outCircle = new THREE.CircleGeometry(.2,24); - if(data.target) { outCircle.rotateX(-Math.PI/2); outCircle.translate(0,0.75,0); @@ -62,6 +65,10 @@ AFRAME.registerComponent("spotlightindicator",{ } }); +/** + * @summary Define pointlight indicator geometry + * Shape: sphere + */ AFRAME.registerComponent("pointlightindicator", { schema:{ color:{ @@ -94,6 +101,10 @@ AFRAME.registerComponent("pointlightindicator", { } }); +/** + * @summary Define directionallight indicator geometry + * Shape: arrow + */ AFRAME.registerComponent("directionallightindicator", { schema:{ color:{ @@ -136,9 +147,12 @@ AFRAME.registerComponent("directionallightindicator", { } }); -/* - Weird bug - there's circle exist in up cone and don't know why its there -*/ + +/** + * @summary Define hemispherelight indicator geometry + * Shape: Double arrow + * Weird bug - there's circle exist in up cone and don't know why its there + */ AFRAME.registerComponent("hemispherelightindicator",{ schema: { color:{ @@ -190,6 +204,8 @@ AFRAME.registerComponent("hemispherelightindicator",{ /** + * Return MeshBasicMaterial with the inverse of the color of material from parameter + * * @param {THREE.Material} material */ function CreateOutlineMaterial(material) { diff --git a/src/utils/WASDPlusControls.js b/src/utils/WASDPlusControls.js index a03fd75f..9e17b25e 100644 --- a/src/utils/WASDPlusControls.js +++ b/src/utils/WASDPlusControls.js @@ -14,12 +14,21 @@ const MAX_DELTA = 0.25; const CLAMP_VELOCITY = 0.01; const MOD_Y = 1.5; +/** + * Check if the object is empty or not + * + * @param {object} keys + */ const isEmptyObject = (keys) => { let key; for (key in keys) { return false; } return true; }; + +/** + * @summary Add space and shift controls to the movement + */ AFRAME.registerComponent("wasd-plus-controls", { schema: { acceleration: {type: "number", default : 150}, diff --git a/src/utils/browserType.js b/src/utils/browserType.js index 802d76f2..8bf6421e 100644 --- a/src/utils/browserType.js +++ b/src/utils/browserType.js @@ -1,5 +1,8 @@ import AFRAME from "aframe"; +/** + * @summary Returns type of the device user is using to browse MYR + */ export const browserType = () => { const device = AFRAME.utils.device;