diff --git a/Custom/ControllerComponents.js b/Custom/ControllerComponents.js index a6d6cc3..2b00cbc 100644 --- a/Custom/ControllerComponents.js +++ b/Custom/ControllerComponents.js @@ -76,10 +76,12 @@ AFRAME.registerComponent('trackpad-left',{ this.el.addEventListener('trackpadmoved', this.logTrackpad); }, logTrackpad: function (evt) { - if (evt.detail.y > 0.2) { + trackpadDetail.x = evt.detail.x + trackpadDetail.y = evt.detail.y + if (evt.detail.y > 0.5) { } - if (evt.detail.y < -0.2) { + if (evt.detail.y < -0.5) { } if (evt.detail.x < -0.2) { @@ -98,31 +100,43 @@ init: function () { el.addEventListener('gripdown', function (evt) { displayNext(true); + buttonsDownR['grip'] = true; + }); + + el.addEventListener('gripup', function (evt) { + buttonsDownR['grip'] = false; }); - /*el.addEventListener('gripup', function (evt) { - - });*/ el.addEventListener('triggerdown', function (evt) { - displayNext(true); + buttonsDownR['trigger'] = true; + if(buttonsDownR['trigger'] && ((buttonsDownR['trackpad'] && trackpadDetailR.y > .5) || (buttonsDownR['thumbstick'] && thumbstickDetailR.y > .5))){ + handleAll() + } else if(buttonsDownR['trigger'] && ((buttonsDownR['trackpad'] && trackpadDetailR.y < -.5) || (buttonsDownR['thumbstick'] && thumbstickDetailR.y < -.5))){ + stopAll() + } else { + displayNext(false); + } + }); + + el.addEventListener('triggerup', function (evt) { + buttonsDownR['grip'] = false; }); - /*el.addEventListener('triggerup', function (evt) { - - });*/ el.addEventListener('abuttondown', function (evt) { displayNext(true); + buttonsDownR['abutton'] = true; + }); + el.addEventListener('abuttonup', function (evt) { + buttonsDownR['abutton'] = false; }); - /*el.addEventListener('abuttonup', function (evt) { - - });*/ el.addEventListener('bbuttondown', function (evt) { displayNext(true); + buttonsDownR['bbutton'] = true; + }); + el.addEventListener('bbuttonup', function (evt) { + buttonsDownR['bbutton'] = false; }); - /*el.addEventListener('bbuttonup', function (evt) { - - });*/ /*el.addEventListener('menudown', function (evt) { menuRightPressed = true; @@ -130,21 +144,34 @@ init: function () { });*/ el.addEventListener('thumbstickdown', function (evt) { - displayNext(true); + buttonsDownR['thumbstick'] = true; + if(buttonsDownR['thumbstick'] && ((buttonsDownR['thumbstick'] && trackpadDetailR.y > .5) || (buttonsDownR['thumbstick'] && thumbstickDetailR.y > .5))){ + handleAll() + } else if(buttonsDownR['thumbstick'] && ((buttonsDownR['thumbstick'] && trackpadDetailR.y < -.5) || (buttonsDownR['thumbstick'] && thumbstickDetailR.y < -.5))){ + stopAll() + } else { + displayNext(false); + } + }); + el.addEventListener('thumbstickup', function (evt) { + buttonsDownR['thumbstick'] = false; }); - /*el.addEventListener('thumbstickup', function (evt) { - - });*/ el.addEventListener('trackpaddown', function (evt) { - displayNext(true); + buttonsDownR['trackpad'] = true; + if(buttonsDownR['trackpad'] && ((buttonsDownR['trackpad'] && trackpadDetailR.y > .5) || (buttonsDownR['trackpad'] && thumbstickDetailR.y > .5))){ + handleAll() + } else if(buttonsDownR['trackpad'] && ((buttonsDownR['trackpad'] && trackpadDetailR.y < -.5) || (buttonsDownR['trackpad'] && thumbstickDetailR.y < -.5))){ + stopAll() + } else { + displayNext(false); + } }); -/* + el.addEventListener('trackpadup', function (evt) { - + buttonsDownR['trackpad'] = false; }); - - el.addEventListener('trackpadtouchstart', function (evt) { + /*el.addEventListener('trackpadtouchstart', function (evt) { }); @@ -160,35 +187,47 @@ init: function () { el.addEventListener('gripdown', function (evt) { displayNext(false); + buttonsDownL['grip'] = true; }); - /* + el.addEventListener('gripup', function (evt) { - - });*/ + buttonsDownL['grip'] = false; + }); el.addEventListener('triggerdown', function (evt) { - displayNext(false); + buttonsDownL['trigger'] = true; + if(buttonsDownL['trigger'] && ((buttonsDownL['trackpad'] && trackpadDetailL.y > .5) || (buttonsDownL['thumbstick'] && thumbstickDetailL.y > .5))){ + handleAll() + } else if(buttonsDownL['trigger'] && ((buttonsDownL['trackpad'] && trackpadDetailL.y < -.5) || (buttonsDownL['thumbstick'] && thumbstickDetailL.y < -.5))){ + stopAll() + } else { + displayNext(false); + } }); - /* + el.addEventListener('triggerup', function (evt) { - - });*/ + buttonsDownL['grip'] = false; + }); el.addEventListener('xbuttondown', function (evt) { displayNext(false); + //handleAll() + buttonsDownL['xbutton'] = true; }); - /*el.addEventListener('xbuttonup', function (evt) { - - });*/ + el.addEventListener('xbuttonup', function (evt) { + buttonsDownL['xbutton'] = false; + }); el.addEventListener('ybuttondown', function (evt) { displayNext(false); + //stopAll() + buttonsDownL['ybutton'] = true; }); - /*el.addEventListener('ybuttonup', function (evt) { - - });*/ + el.addEventListener('ybuttonup', function (evt) { + buttonsDownL['ybutton'] = false; + }); /*el.addEventListener('menudown', function (evt) { menuLeftPressed = true; @@ -196,20 +235,34 @@ init: function () { });*/ el.addEventListener('thumbstickdown', function (evt) { - displayNext(false); + buttonsDownL['thumbstick'] = true; + if(buttonsDownL['thumbstick'] && ((buttonsDownL['thumbstick'] && trackpadDetailL.y > .5) || (buttonsDownL['thumbstick'] && thumbstickDetailL.y > .5))){ + handleAll() + } else if(buttonsDownL['thumbstick'] && ((buttonsDownL['thumbstick'] && trackpadDetailL.y < -.5) || (buttonsDownL['thumbstick'] && thumbstickDetailL.y < -.5))){ + stopAll() + } else { + displayNext(false); + } + }); + el.addEventListener('thumbstickup', function (evt) { + buttonsDownL['thumbstick'] = false; }); - /*el.addEventListener('thumbstickup', function (evt) { - - });*/ el.addEventListener('trackpaddown', function (evt) { - displayNext(false); + buttonsDownL['trackpad'] = true; + if(buttonsDownL['trackpad'] && ((buttonsDownL['trackpad'] && trackpadDetailL.y > .5) || (buttonsDownL['trackpad'] && thumbstickDetailL.y > .5))){ + handleAll() + } else if(buttonsDownL['trackpad'] && ((buttonsDownL['trackpad'] && trackpadDetailL.y < -.5) || (buttonsDownL['trackpad'] && thumbstickDetailL.y < -.5))){ + stopAll() + } else { + displayNext(false); + } }); - /*el.addEventListener('trackpadup', function (evt) { - + el.addEventListener('trackpadup', function (evt) { + buttonsDownL['trackpad'] = false; }); - + /* el.addEventListener('trackpadtouchstart', function (evt) { }); @@ -218,4 +271,12 @@ init: function () { });*/ } -}); \ No newline at end of file +}); + +thumbstickDetailL = {x: 0, y: 0} +trackpadDetailL = {x: 0, y: 0} +buttonsDownL = {trigger: false, grip: false, trackpad: false, thumbstick: false, abutton: false, bbutton: false} + +thumbstickDetailR = {x: 0, y: 0} +trackpadDetailR = {x: 0, y: 0} +buttonsDownR = {trigger: false, grip: false, trackpad: false, thumbstick: false, xbutton: false, ybutton: false} \ No newline at end of file diff --git a/Custom/ControllerInputMapping.js b/Custom/ControllerInputMapping.js index 2270d20..1ca6acc 100644 --- a/Custom/ControllerInputMapping.js +++ b/Custom/ControllerInputMapping.js @@ -5,7 +5,7 @@ */ -import data from '../Compatibility/controller_profiles.json' assert { type: "json" }; +//import data from '../Compatibility/controller_profiles.json' assert { type: "json" }; const windows = data[0]['windows'] const oc_touch = data[0]['oc_touch'] const oc_go = data[0]['oc_go'] diff --git a/Custom/README.md b/Custom/README.md index 7518c57..627cbfc 100644 --- a/Custom/README.md +++ b/Custom/README.md @@ -1,168 +1,245 @@ -# Manual User Interface Tests # - -Begin by opening this link: https://didsr.github.io/WebXR-tools/Custom/ - -## Test 1- Adding and editing a package -This test will examine the package and pattern systems. - 1. Add a package with the name "Test 1" by pressing the *plus* icon next to **Packages** - 2. Add three patterns to this package by pressing the *plus* icon next to **Pattern List** - - Name the first pattern "Pattern 1" - - Name the second pattern "Pattern 2" - - Name the third pattern "Pattern 3" - - At this point, the tool should look like this: - ![image](../Images/test1_1.PNG) - - 3. Reorder the patterns so that "Pattern 3" is the first pattern, "Pattern 2" is the second pattern, and "Pattern 1" is the last pattern - - Do this by dragging "Pattern 3" and dropping it in the first position - - Drag "Pattern 2" and drop it in the second position - 4. Switch packages to the "default" package - 5. Multi-select the patterns "crosshair" and "ring_w2" by holding ctrl while clicking on the patterns - 6. Copy these patterns by pressing Ctrl+c - 7. Switch packages to the "Test 1 Package" package - 8. Paste the copied patterns by pressing Ctrl+v - - At this point, the tool should look like this: - ![image](../Images/test1_2.PNG) - -## Test 2- Adding and editing a pattern -This test will examine the pattern and entity systems. - 9. Rename the "crosshair" pattern to "Pattern 4" - - Select the "crosshair" pattern by clicking on it - - Open settings by pressing the *gear* icon at the top right of the tab - - Under **Pattern Settings** select the *Rename* button - - Enter "Pattern 4" in the textbox and press OK - 10. Delete the "ring_w2" pattern by pressing the *trash* icon next to **Pattern List** - - Select OK on the confirmation - 11. Close the settings by pressing the *X* icon at the top right of the tab - 11. Reorder the patterns so that "Pattern 4" is first, "Pattern 3" is second, "Pattern 2" is third, and "Pattern 1" is last - - At this point, the tool should look like this: - ![image](../Images/test1_3.PNG) - - 12. Select "Pattern 3" - 13. Switch the toggle at the top of the tab to be in *Edit* mode - 14. Add a circle, plane, and triangle to this pattern - - Select circle as the type of entity to add from the dropdown next to **Type of entity:** - - Press the *Add to Pattern* button to add it to the pattern - - Repeat for plane and triangle - - The entities will spawn at random places on the screen - 15. Switch the second toggle to *Edit Entity* mode - 16. Edit the Circle - - Click on the circle or select "circle0" from the **Entity** dropdown - - Move the circle so that it is in position (0, 0, 250) - - Change the color of the circle to white by selecting it from the color selector or entering #ffffff - - Increase the radius of the circle to 40m - - Decrease the border size to 15m - 17. Edit the Plane - - Click on the plane or select "plane0" from the **Entity** dropdown - - Move the plane so that it is in position (-20, 100, 250) - - Change the color of the plane to blue by selecting it from the color selector or entering #0000ff - - Increase the height of the plane to 100m - - Decrease the width of the plane to 20m - - If desired, add a texture from the drop down or upload an image file to use as a texture - - If an uploaded texture is added here, one step will change in Part 3 - - Adding a texture will rescale the entity to meet the aspect ratio of the image being used - 18. Edit the Triangle - - Click on the triangle or select "triangle0" from the **Entity** dropdown - - Move the triangle so that it is in position (20, -100, 250) - - Change the color of the triangle to green by selecting it from the color selector or entering #00ff00 - - Change vertex A to be at (0, 50) - - Change vertex B to be at (-50, -50) - - Change vertex C to be at (50, -50) - At this point the tool should look like this: - - ![image](../Images/test2_1.PNG) - - 19. Switch the first toggle to *Display* mode - 20. Select "Pattern 2" - 21. Switch the toggle at the top of the tab to be in *Edit* mode - 22. Add a gradient, checkerboard, and grille to this pattern - - Select gradient as the type of entity to add from the dropdown next to **Type of entity:** - - Press the *Add to Pattern* button to add it to the pattern - - Repeat for checkerboard and grille - - The entities will spawn at random places on the screen - 23. Switch the second toggle to *Edit Entity* mode - 24. Edit the Gradient - - Click on the gradient or select "gradient0" from the **Entity** dropdown - - Move the gradient so that it is in position (0, 150, 250) - - Change the primary color of the gradient to white by selecting it from the color selector or entering #ffffff - - Increase the bar height to 20m - - Decrease the bar width to 3m - - Increase the number of bars to 100 - - Change the secondary color to red by selecting it from the color selector or entering #ff0000 - 25. Edit the Checkerboard - - Click on the checkerboard or select "checkerboard0" from the **Entity** dropdown - - Move the plane so that it is in position (0, 0, 250) - - Change the primary color of the checkerboard to purple by selecting it from the color selector or entering #800080 - - Increase the number of columns to 20 - - Increase the number of rows to 19 - - Increase the size of the tiles to 10m - - Change the secondary color to white by selecting it from the color selector or entering #ffffff - 26. Edit the grille - - Click on the grille or select "grille0" from the **Entity** dropdown - - Move the gradient so that it is in position (0, -150, 250) - - Change the primary color of the grille to orange by selecting it from the color selector or entering #ffa500 - - Decrease the bar height to 20m - - Decrease the bar width to 3m - - Increase the number of bars to 100 - - Change the secondary color to white by selecting it from the color selector or entering #ffffff - At this point the tool should look like this: -![image](../Images/test2_2.png) - - 27. Switch the first toggle to *Display* mode - 28. Select "Pattern 1" - 29. Switch the toggle at the top of the tab to be in *Edit* mode - 30. Add a dot array, circular dot array, and bullseye to this pattern - - Select dot array as the type of entity to add from the dropdown next to **Type of entity:** - - Press the *Add to Pattern* button to add it to the pattern - - Repeat for circular dot array and bullseye - - The entities will spawn at random places on the screen - 31. Switch the second toggle to *Edit Entity* mode - 32. Edit the Dot Array - - Click on the dot array or select "dotarray0" from the **Entity** dropdown - - Move the dot array so that it is in position (-20, -100, 250) - - Change the color of the dot array to green by selecting it from the color selector or entering #00ff00 - - Increase the number of columns to 7 - - Increase the number of rows to 7 - - Increase the radius of the dots to 3m - - Decrease the spacing of the dots to 5m - - Toggle on the center dot being filled - 33. Edit the Circular Dot Array - - Click on the circular dot array or select "circularDotarray0" from the **Entity** dropdown - - Move the circular dot array so that it is in position (0, 0, 249) - - Change the color of the dot array to white by selecting it from the color selector or entering #ffffff - - Increase the number of dots to 15 - - Increase the number of rings to 6 - - Keep the radius of the dots at 2m - - Keep the spacing of the dots at 10m - - Keep the center dot hollow - 34. Edit the bullseye - - Click on the bullseye or select "bullseye0" from the **Entity** dropdown - - Move the bullseye so that it is in position (0, 0, 250) - - Change the primary color of the bullseye to blue by selecting it from the color selector or entering #0000ff - - Increase the number of rings to 6 - - Keep the ring pitch at 5m -At this point the tool should look like this: -![image](../Images/test2_3.PNG) - -## Test 3- Saving and uploading a package -This test will examine the sharing feature of the tool. - - 35. Switch the first toggle to *Display* mode - 36. Select the save package button next to **Packages:** - - Note: if an uploaded texture was used in Test 2, select cancel when prompted to include textures - - Uploaded textures cause generated files to be too large for the link generation service - 37. Make a note of the package id saved in the url after "?id=" ('?id=') - 38. Refresh the page - 39. Ensure that the package "Test 1" is loaded and the patterns are correct - 40. Upload the "Test 1 Comparison" package - - Open settings by hitting the *gear* icon at the top right of the tab - - Press the import button denoted by a cloud with a down arrow - - Paste this link into the textbox: https://didsr.github.io/WebXR-tools/Custom/?id=598zgfm3bqw9 - 41. Check that there is now a package called "Test 1 Comparison" with the same patterns as those created in these tests - 42. To interactively check for correct results, navigate between the two packages and ensure entity values are the same - 43. Close the tab completely - 44. Navigate back to the starting page of the tool (https://didsr.github.io/WebXR-tools/Custom/) - 45. Select "Test 1" and "Test 1 Comparison" from the **Recent Packages** dropdown and ensure that they are correct +# Pattern Generation Tool # +The Pattern Generation Tool provides a user interface for creating, editing, and displaying [WebXR](https://immersiveweb.dev/) scenes. +Scenes consist of 2 and 3 dimensional entities taken from [A-Frame](https://aframe.io/docs/1.4.0/core/entity.html). +These entities can be manipulated in a variety of different ways to create flexible patterns. +Scenes are grouped together in packages that can be downloaded and shared. +### Features +- Create packages of scenes that can be shared via a file or a link. +- Order of scenes within the package can be easily changed. +- Scenes are fully editable upon uploading or downloading. +- Scenes can be switched between using arrow keys or when in immersive mode, the buttons on the left and right controllers. +- Default package available containing commonly used patterns: + - Red: A solid red background + - Green: A solid green background + - Blue: A solid blue background + - White: A solid white background + - Grille: A black and white background + - Crosshair: A white crosshair + - Line: A white vertical line + - Dot Array: A matrix of dots + - Circular Dot Array: A dot array arranged in a circle + - Checkerboard_w: A checkerboard with a white center tile + - Checkerboard_b: A checkerboard with a black center tile + - Ring_w1: A bullseye with a high pitch + - Ring_w2: A bullseye with a medium pitch + - Ring_w5: A bullseye with a low pitch + + +# Directions For Use # +### Packages +1. [Create a Package](#createPackage) +2. Edit a Package +3. Display a Package +4. Save a Package +5. Share a Package + +### Patterns +1. Create a Pattern +2. Edit a Pattern +3. Display a Pattern +4. Save a Pattern +5. Share a Pattern + + +
+## Create a Package + +## Edit a Package + +## Display a Package + +## Save a Package + +## Share a Package + + + + + + + + + +## Displaying Patterns + + + +### Selecting a Pattern +To select a pattern, first ensure that the checkbox for the pattern under ***Pattern List*** has been checked. Then select the desired pattern from the ***Pattern Display*** dropdown. + +### Adding a Pattern +A pattern a can be added using the ***Add Pattern*** button. A name for the added pattern can be specified using textbox above the ***Add Pattern*** button. + +### Removing a Pattern +Using the ***Remove Pattern*** button, the currently displayed pattern can be removed. + +### Selecting Multiple Patterns +To select multiple patterns, check all of the desired checkboxes under ***Pattern List***. +**The order that the patterns are selected in will be the display order** +The current pattern can be rotated through using the up or down arrows on the keyboard or the buttons on the left and right controllers. +Any buttons on the left controller step back one pattern and any buttons on the right controller step forward one pattern. + +### Displaying the Desired Pattern +To display the pattern, hit the ***VR*** button in the bottom right hand corner. +[**Check the demos folder for some basic editable patterns**](./demos) + +### Saving and Uploading a Group of Patterns +Multiple patterns can be saved together by hitting the ***Save Selected Patterns*** button. This will save all currently selected patterns from the ***Pattern List*** as a JSON file. +To upload a group of patterns, press the ***Upload Patterns*** button and select the desired JSON file. This JSON file can contain one or more patterns and will add them all to the ***Pattern List***. + +## Editing Patterns + +### Uploading a Pattern +A JSON file containing a single pattern can be uploaded to the ***Upload a pattern*** input. If a file containing multiple patterns is uploaded, it will be rejected. + +### Uploading images +Image files are treated as entity textures. Here are the steps on how to properly upload these files. + +1. Add a plane to a scene. Planes are the only entities that can be textured. +2. Click the edit entity toggle and locate the input for textures labeled "Upload your textures here." Any number of files can be uploaded here. Images uploaded will be available as textures in the dropdown labeled "Texture". +3. Select the desired texture from the "Texture" dropdown. Selecting a texture will automatically resize the plane to the images aspect ratio. To retain the original image colors, set the plane color to be white. + +### Adding Entities +![plot](../Images/custom.PNG) +To add an entity, make sure the slider at the top left of the webpage is set to ***Edit Pattern*** then move the slider below it to the ***Add Entity***. + +Then, select the type of entity you would like to add using the ***Type of entity*** dropdown and hit the ***Add to Pattern*** button. + +Entities will spawn at a random position within the editor camera field of view with a random color. + +***Entities may appear skewed in the editor but this affect is corrected on the headset. Do not stack entities, it will result in [z-fighting].(https://en.wikipedia.org/wiki/Z-fighting)*** + +#### Types of Entities +- Circle +- Plane +- Triangle +- Gradient +- Checkerboard +- Grille + +### Editing Entities +![plot](../Images/editorExample.PNG) +**In order to access the editor one or more entities must be added to the pattern**. The editing bar can be hidden by pressing the ***Hide Settings*** button. + +Once entities have been added to the pattern, change the slider to ***Edit Entity***. + +To change the entity being edited, either click on the entity or select the desired entity from the dropdown labeled ***Current Entity***. +Entity ID's are automatically generated with the format **\\**. + +Examples: circle0, checkerboard4, plane20. + +The current entity can be removed by hitting the ***Remove from Pattern***. The entire pattern can be reset by hitting the ***Reset Pattern*** button. + +### Saving the Pattern +To save the current pattern, press the ***Save Pattern*** button located at the bottom of the editor tab. The pattern is saved as an editable JSON file. Uploaded textures are preserved without image compression. + +### Background Color +To change the background color, select a new color or enter the hexadecimal code of the desired color. + +### Universal Entity Settings +#### Position: (x deg, y world units) +To edit the position, locate the position text boxes under **Universal Entity Settings**. The left box refers to the x position and the y position. + +The position of an entity refers to where its center point is located. The editor interfaces the three axis in different manners. +Positional data is calculated based on a cylinder that encompasses the camera. The radius of this cylinder cannot be changed, however the cylinder has an infinite height. The x and z axes are responsible for horizontal positioning. The y axis controls the vertical position. + +![plot](../Images/cylinderRadius.PNG) + +- x-axis: + - This axis is in terms of **degrees** where 1 degree references 1 degree of clockwise rotation away from the fixed camera center on the cylinder. +- y-axis: + - This axis is in terms of **world units** where 1 world unit is equal to 1 meter in 3D space. +- z-axis: + - **The z-axis is NOT editable by users.** The location on the z-axis is automatically calculated based on the x-axis angle. + +The reason that the radius of the cylinder is not editable is due to the fact that all entities are 2-dimensional. Changing their depth would essentially have the same effect as making entities smaller or larger. + +#### Rotation: θ deg +To edit the rotation, locate the text box labeled ***Rotation*** under **Universal Entity Settings**. + +For this program, the rotation of an entity refers to rotation around the **z-axis only**. The axis of rotation is located at the center point of entity. The unit for rotation is **degrees** where 1 degree refers to one degree of rotation about the axis of rotation. + +#### Color: #HEXCODE +To edit the color, locate the color selector labeled ***Color*** under **Universal Entity Settings**. + +Select a color using the color slider or input the desired color in hexadecimal format. + +***For checkerboards and grilles, the alternate color will always be black*** + +### Entity Specific Settings +#### Circle +- Radius (m): + - The unit for radius is world units where 1 world unit is equal to 1 meter in 3D space. +- Border Size: + - The unit for border size is world units where 1 world unit is equal to 1 meter in 3D space. By default, the border size is set to be equal to the radius of the circle, meaning the entity is entirely filled in. + +#### Plane +- Texture: + - There are some textures built into the site. [They can be found here.](./textures) Textures can also be uploaded as JPGS or PNGS and added to the list of available textures in the pattern. + - Applying a texture will automatically scale the plane to fit the aspect ratio. +- Height (m): + - The unit for height is world units where 1 world unit is equal to 1 meter in 3D space. +- Width (m): + - The unit for width is world units where 1 world unit is equal to 1 meter in 3D space. +- Border Size: + - The unit for border size is world units where 1 world unit is equal to 1 meter in 3D space. By default, the border size is set to be equal to the radius to the smallest dimension present of the plane, meaning the entity is entirely filled in. + +#### Triangle +![plot](../Images/triangle.PNG) +- Vertex A (x m,y m): + - Position of vertex A in relation to the center point of the entity. The coordinates are in world units where 1 world unit is equal to 1 meter in 3D space. +- Vertex B (x m,y m): + - Position of vertex B in relation to the center point of the entity. The coordinates are in world units where 1 world unit is equal to 1 meter in 3D space. +- Vertex C (x m,y m): + - Position of vertex C in relation to the center point of the entity. The coordinates are in world units where 1 world unit is equal to 1 meter in 3D space. + +#### Gradient +- Individual Bar Height (m): + - The unit for height is world units where 1 world unit is equal to 1 meter in 3D space. +- Indivdual Bar Width (m): + - The unit for width is world units where 1 world unit is equal to 1 meter in 3D space. +- Number of Bars: + - The number of bars in the gradient, the default is 32. + - The color is divided by the number of bars to determine the color of each bar. + +#### Checkerboard +- Tile size (m): + - The unit for width and height of tiles is world units where 1 world unit is equal to 1 meter in 3D space. +- Number of Rows: + - The number of rows in the checkerboard, the default is 16. +- Number of Columns: + - The number of columns in the checkerboard, the default is 16. + +#### Grille +- Individual Bar Height (m): + - The unit for height is world units where 1 world unit is equal to 1 meter in 3D space. +- Indivdual Bar Width (m): + - The unit for width is world units where 1 world unit is equal to 1 meter in 3D space. +- Number of Bars: + - The number of bars in the grille, the default is 32. + +### Other Notes +If you would like to inspect the HTML or JavaScript data of the selected entity: +- Open the inspector with Ctrl + Shift + i +- Enter "selectedEntity" into the command prompt, this will bring up all associated HTML code +- Enter "selectedEntity.getAttribute("\") to see the associated JavaScript data for the desired component + - Ex: selectedEntity.getAttribute("position") to view position or selectedEntity.getAttribute("material") to view texture and color +- Enter "selectedEntity.setAttribute("\",\) to set the associated JavaScript data for the desired component + - Ex: selectedEntity.setAttribute("position",{x: 0, y: 0, z: -125}) to set position to 0,0 on the cylindrical plane + - Ex: selectedEntity.setAttribute("material",{color: "#0000FF", shader: "flat", src: ""}) to set the color to red and remove the texture, ***make sure to include shader: "flat" to remove unnecessary lighting effects*** + + +## JSON File Format +{ +  "scenes": +    { map of scenes }, +   "textures": { +     "uploadedTextureFormats": +            { map of image sizes for uploaded textures }, +     "textureValues": +            [ list of textures associated with patterns being saved], +   } +   "date": "datetime of save" +} + diff --git a/Custom/animation.js b/Custom/animation.js new file mode 100644 index 0000000..1e66928 --- /dev/null +++ b/Custom/animation.js @@ -0,0 +1,145 @@ +function handleAnimationToggle(){ + if(animationButton.children[0].className.includes('fa-play')){ + animationButton.children[0].className = "fa-solid fa-pause"; + selectedEntity.emit('animLoopStart',null,false) + } else { + animationButton.children[0].className = "fa-solid fa-play"; + selectedEntity.emit('animLoopPause',null,false) + } + +} + +/*function handleAll(){ + // if no entities then do nothing + if(els.length <= 0){ + return + } + // loop through each + let status = 0; + if(handleAllButton.children[0].className.includes('fa-play')){ + handleAllButton.children[0].className = "fa-solid fa-pause"; + status = 1; + if(timerNum > 0){ + startTimer() + } + } else { + handleAllButton.children[0].className = "fa-solid fa-play"; + // timer pause + if(timerNum > 0){ + clearInterval(time) + } + } + let i = 0; + while(i < els.length){ + let data = els[i].getAttribute('movement'); + if(data.startPoints.length > 0){ + data.status = status; + els[i].setAttribute('movement',data) + } + + i++; + } + +}*/ + +function startAll(){ + let status = 1; + if(timerNum > 0){ + startTimer() + } + let i = 0; + while(i < els.length){ + let data = els[i].getAttribute('movement'); + if(data.startPoints.length > 0){ + data.status = status; + els[i].setAttribute('movement',data) + } + + i++; + } + + startAllButton.disabled = true + pauseAllButton.disabled = false + stopAllButton.disabled = false +} + +function pauseAll(){ + let status = 0; + if(timerNum > 0){ + clearInterval(time) + } + let i = 0; + while(i < els.length){ + let data = els[i].getAttribute('movement'); + if(data.startPoints.length > 0){ + data.status = status; + els[i].setAttribute('movement',data) + } + + i++; + } + + startAllButton.disabled = false + pauseAllButton.disabled = true + stopAllButton.disabled = false +} + +function stopAll(){ + // if no entities then do nothing + if(els.length <= 0){ + return + } + // set start all button icon to play + //handleAllButton.children[0].className = "fa-solid fa-play"; + // loop through each + let i = 0; + while(i < els.length){ + let data = els[i].getAttribute('movement'); + data.status = -1; + els[i].setAttribute('movement',data) + + i++; + } + // timer pause + if(timerNum > 0){ + clearInterval(time) + timeElapsed = 0; + let timer = document.getElementById('timer0') + let textVal = timer.getAttribute('text') + textVal.value = "00:00.00 " + timer.setAttribute('text',textVal) + } + + startAllButton.disabled = false + pauseAllButton.disabled = true + stopAllButton.disabled = true + + movementIcon.className = "fa-solid fa-play" +} + + +function handleMovementToggle(e){ + e.stopPropagation() + if(movementIcon.className == "fa-solid fa-play"){ + let data = selectedEntity.getAttribute('movement') + data.status = 1 + selectedEntity.setAttribute('movement',data) + movementIcon.className = "fa-solid fa-pause" + } else { + let data = selectedEntity.getAttribute('movement') + data.status = 0 + selectedEntity.setAttribute('movement',data) + movementIcon.className = "fa-solid fa-play" + + } +} + +function stopIndividual(e){ + e.stopPropagation() + let data = selectedEntity.getAttribute('movement') + data.status = -1 + selectedEntity.setAttribute('movement',data) + movementIcon.className = "fa-solid fa-play" + + +} \ No newline at end of file diff --git a/Custom/changeListeners.js b/Custom/changeListeners.js index 14ea9bd..8255852 100644 --- a/Custom/changeListeners.js +++ b/Custom/changeListeners.js @@ -31,6 +31,76 @@ $("#z").change(function() { editEntity(); }); +/* If the textbox for endX value is changed */ +$("#startX").change(function() { + editEntity(); + }); + +/* If the textbox for endY value is changed */ +$("#startY").change(function() { + editEntity(); + }); + +/* If the textbox for endZ value is changed */ +$("#startZ").change(function() { + editEntity(); + }); + +/* If the textbox for endX value is changed */ +$("#endX").change(function() { + editEntity(); + }); + +/* If the textbox for endY value is changed */ +$("#endY").change(function() { + editEntity(); + }); + +/* If the textbox for endZ value is changed */ +$("#endZ").change(function() { + editEntity(); + }); + + /* If the textbox for endX value is changed */ +$("#speedIn").change(function() { + editEntity(); + }); + +/* If the textbox for endY value is changed */ +$("#accelerationIn").change(function() { + editEntity(); + }); + +/* If the textbox for endZ value is changed */ +/*$("#key").change(function(e) { + if(keyBind.value.length > 1 || keyBind.value == 'm'){ + alert('Invalid key, please choose a key other than \'m\' or leave this blank.') + return + } + i = 0; + while(i < entityCanvas.children.length){ + if(entityCanvas.children[i] == selectedEntity){ + break; + } + i++; + } + + if(movementKeyBinds[keyBind.value] == null){ + movementKeyBinds[keyBind.value] = [] + } + movementKeyBinds[keyBind.value].push(i); + mov = selectedEntity.getAttribute('mov') + if(mov.keyBind != ''){ + movementKeyBinds[mov.keyBind].splice(movementKeyBinds[mov.keyBind].indexOf(i), 1); + } + mov.keyBind = keyBind.value + });*/ + +/* If the textbox for endZ value is changed */ +$("#movementTypeIn").change(function() { + editEntity(); + }); + /* If the textbox for color value is changed */ $('#color').minicolors({ control: 'hue', @@ -52,7 +122,7 @@ $('#color2').minicolors({ }, }); -/* If the textbox for x value is changed */ +/* If the textbox for texture value is changed */ $("#texture").change(function() { if(texture.value == "none"){ selectedEntity.setAttribute("material",{color: selectedEntity.getAttribute("material").color, shader: "flat", src: ""}); @@ -81,7 +151,10 @@ $("#texture").change(function() { height.value = selectedEntity.getAttribute("geometry").height; fill.value = selectedEntity.getAttribute("fill").val; fillIn.style.display = "none"; + updateJSON(); } + + }); @@ -311,6 +384,10 @@ $("#ringPitchIn").change(function() { editEntity(); }); +$("#text").change(function() { + editEntity(); +}); + /* sends entity back or forward one layer */ /*function sendBack(isback){ let tmp = null; @@ -567,7 +644,7 @@ function slowLoop(items, loopBody) { }); -keysPressed = {ctrl: false, x: false, c: false, v: false, i: false} +keysPressed = {ctrl: false, x: false, c: false, v: false, i: false, m: false, r: false} /* listens for key presses to change pattern */ document.addEventListener('keyup', (e) => { @@ -605,6 +682,10 @@ document.addEventListener('keyup', (e) => { keysPressed["v"] = false; } else if(e.code === "KeyI"){ keysPressed["i"] = false; + } else if(e.code === "KeyM"){ + keysPressed["m"] = false; + } else if(e.code === "KeyR"){ + keysPressed["r"] = false; } }); @@ -649,5 +730,61 @@ document.addEventListener('keydown', (e) => { // paste document.querySelector("#debug").style.display == 'block' ? document.querySelector("#debug").style.display = 'none' : document.querySelector("#debug").style.display = 'block' } + } else if(e.code === "KeyM"){ + keysPressed['m'] = true; + let i = 0; + while(i < entityCanvas.children.length){ + mov = entityCanvas.children[i].getAttribute('mov') + if(mov.status != 0){ + break; + } + i++; + } + if(i != entityCanvas.children.length){ + stopAllMovement() + } else { + let i = 0; + sum = 0; + while(i < entityCanvas.children.length){ + if((entityCanvas.children[i].getAttribute('position').x == entityCanvas.children[i].getAttribute('mov').startPoint.x && entityCanvas.children[i].getAttribute('position').y == entityCanvas.children[i].getAttribute('mov').startPoint.y && entityCanvas.children[i].getAttribute('position').z == entityCanvas.children[i].getAttribute('mov').startPoint.z) && (entityCanvas.children[i].getAttribute('rotation').x == entityCanvas.children[i].getAttribute('mov').startRotation.x && entityCanvas.children[i].getAttribute('rotation').y == entityCanvas.children[i].getAttribute('mov').startRotation.y && entityCanvas.children[i].getAttribute('rotation').z == entityCanvas.children[i].getAttribute('mov').startRotation.z)){ + sum++; + } + i++; + } + if(sum != i){ + let i = 0; + while(i < entityCanvas.children.length){ + mov = entityCanvas.children[i].getAttribute('mov') + entityCanvas.children[i].setAttribute('position',mov.startPoint) + entityCanvas.children[i].setAttribute('rotation',mov.startRotation) + i++; + } + } else { + startAllMovement() + } + } + } else if(movementKeyBinds[e.key]) { + if(document.activeElement == keyBind){ + return + } + for(const i of movementKeyBinds[e.key]){ + console.log('i') + if(entityCanvas.children[i].getAttribute('mov').status != 0){ + stopMovement(entityCanvas.children[i]) + } else { + if((entityCanvas.children[i].getAttribute('position').x == entityCanvas.children[i].getAttribute('mov').startPoint.x && entityCanvas.children[i].getAttribute('position').y == entityCanvas.children[i].getAttribute('mov').startPoint.y && entityCanvas.children[i].getAttribute('position').z == entityCanvas.children[i].getAttribute('mov').startPoint.z) && (entityCanvas.children[i].getAttribute('rotation').x == entityCanvas.children[i].getAttribute('mov').startRotation.x && entityCanvas.children[i].getAttribute('rotation').y == entityCanvas.children[i].getAttribute('mov').startRotation.y && entityCanvas.children[i].getAttribute('rotation').z == entityCanvas.children[i].getAttribute('mov').startRotation.z)){ + toggleMovement(i) + } else { + mov = entityCanvas.children[i].getAttribute('mov') + entityCanvas.children[i].setAttribute('position',mov.startPoint) + entityCanvas.children[i].setAttribute('rotation',mov.startRotation) + } + + } + } } + + + }); + diff --git a/Custom/drawing.js b/Custom/drawing.js index 8ad463b..3f67b98 100644 --- a/Custom/drawing.js +++ b/Custom/drawing.js @@ -59,11 +59,24 @@ function addEntity(){ el.setAttribute("material",{shader: "flat", color: "#"+R+G+B}); el.setAttribute("arraySpacing", {val: 10}); el.setAttribute("toggleCenterDot", {val: false}); - console.log('toggleCenterDot') } else if ($("#entity :selected").text() == "bullseye"){ el.setAttribute("id","bullseye"+bullseyeNum++); drawBullseye(5,5,"#"+R+G+B,el); el.setAttribute("material",{shader: "flat", color: "#"+R+G+B}); + } else if ($("#entity :selected").text() == "text"){ + el.setAttribute("id","text"+textNum++); + el.setAttribute("text",{"value": "Default Text", "color": "#FFFFFF", width: .25*250, height: .125*250, align:"center", "wrapCount": 12}); + /*el.setAttribute("value","Default Text") + el.setAttribute("color","#FFFFFF") + el.setAttribute("height", .25*2000) + el.setAttribute("width", .125*2000)*/ + } else if ($("#entity :selected").text() == "timer"){ + if(timerNum > 0){ + alert("A timer already exists") + return + } + el.setAttribute("id","timer"+timerNum++); + el.setAttribute("text",{"value": "00:00.00 ", "color": "#FFFFFF", width: .25*250, height: .125*250, align:"center", "wrapCount": 9}); } /* Set default universal stats */ @@ -74,8 +87,10 @@ function addEntity(){ let Y = Math.random() * 30 - 15; // random y position el.setAttribute("position",{x: -250 * Math.sin((THETAX*Math.PI)/180), y: Y, z: -250 * Math.cos((THETAX*Math.PI)/180)}); // set position to random x, random y, distance = 250 el.setAttribute("rotation", {x: 0, y: THETAX, z: 0}); // set rotation to be 0 - el.setAttribute("angle",{x: THETAX, z: -250}); // set angular units to be random x and 250 - + el.setAttribute("angle",{x: THETAX, z: -250}); // set angular units to be random x and + //el.setAttribute("mov",{startPoint: {x: -250 * Math.sin((THETAX*Math.PI)/180), y: Y, z: -250 * Math.cos((THETAX*Math.PI)/180)}, endPoint: {theta: 0, y: 0, r: -250},speed: 10, acceleration: 1, status: 0, type: "None", startRotation: {x: 0, y: THETAX, z: 0}, keyBind: ''}) + el.setAttribute("movement",{'startPoints': [],'endPoints': [],'initialVelocities':[],'accelerations':[],'types':[],'origin': {x: -250 * Math.sin((THETAX*Math.PI)/180), y: Y, z: -250 * Math.cos((THETAX*Math.PI)/180)}, 'rotationOrigin': {x: 0, y: THETAX, z: 0}, 'status': -1, 'index': 0, 'currentVelocity': 0, 'timeElapsed': 0}) + entityCanvas.appendChild(el); /* add entity to scene */ /* adds option to dropdown */ @@ -251,6 +266,7 @@ function drawDotArray(rows,cols,size,spacing,color1,toggle,parent){ } function drawCircularDotArray(radius,circles,dots,size,color1,toggle,parent){ + console.log(parent) let c = 1; let middleDot = document.createElement("a-entity"); middleDot.setAttribute("id",parent.id+"-center"); @@ -310,24 +326,41 @@ function updateJSON(){ const jsonData = {}; jsonData["sky"] = {skyColor: sky.getAttribute("material").color}; els.forEach(element => { + mov = JSON.parse(JSON.stringify(element.components.movement.attrValue)) + mov.status = -1; + console.log(mov) if(element.id.includes("gradient") || element.id.includes("grille")){ - jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, numBars: element.children.length, color2: element.components.color2.attrValue, childGeometry: element.children[0].components.geometry.attrValue, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, numBars: element.children.length, color2: element.components.color2.attrValue, childGeometry: element.children[0].components.geometry.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("checkerboard")){ - jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, rows: element.children.length, cols: element.children[0].children.length, tileSize: element.children[0].children[0].components.geometry.attrValue.width, color2: element.components.color2.attrValue, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, rows: element.children.length, cols: element.children[0].children.length, tileSize: element.children[0].children[0].components.geometry.attrValue.width, color2: element.components.color2.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("plane")){ - jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, widthReal: (element.children.length == 0 ? element.components.geometry.attrValue.width : element.children[2].components.geometry.attrValue.width),fill: element.components.fill.attrValue, geometry: element.components.geometry.attrValue, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + let mat = JSON.parse(JSON.stringify(element.components.material.attrValue)); + for(let i = 0; i < texture.options.length; i++){ + if("#"+texture.options[i].value == mat.src){ + mat.src = texture.options[i].text; + break; + } + } + console.log(mat) + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, widthReal: (element.children.length == 0 ? element.components.geometry.attrValue.width : element.children[2].components.geometry.attrValue.width),fill: element.components.fill.attrValue, geometry: element.components.geometry.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: mat, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("circle")){ - jsonData[element.id]={advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, geometry: element.components.geometry.attrValue, fill: element.components.fill.attrValue, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id]={advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, geometry: element.components.geometry.attrValue, fill: element.components.fill.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("triangle")){ - jsonData[element.id]={advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, geometry: element.components.geometry.attrValue, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id]={advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, geometry: element.components.geometry.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("circularDotarray")){ - jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, toggleCenterDot: element.components.toggleCenterDot.attrValue, circles: element.children.length-1, dots: element.children[1].children.length, arraySpacing: element.components.arraySpacing.attrValue, circleSize: element.children[0].components.geometry.attrValue.radiusOuter, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, toggleCenterDot: element.components.toggleCenterDot.attrValue, circles: element.children.length-1, dots: element.children[1].children.length, arraySpacing: element.components.arraySpacing.attrValue, circleSize: element.children[0].components.geometry.attrValue.radiusOuter, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("dotarray")){ - jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, toggleCenterDot: element.components.toggleCenterDot.attrValue, rows: element.children.length, cols: element.children[0].children.length, circleSize: element.children[0].children[0].components.geometry.attrValue.radiusOuter, spacing: element.components.arraySpacing.attrValue, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, toggleCenterDot: element.components.toggleCenterDot.attrValue, rows: element.children.length, cols: element.children[0].children.length, circleSize: element.children[0].children[0].components.geometry.attrValue.radiusOuter, spacing: element.components.arraySpacing.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; } else if(element.id.includes("bullseye")){ - jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, numRings: element.children.length-1, ringPitch: element.children[0].components.geometry.attrValue.radiusOuter*2, position: element.components.position.attrValue, material: element.components.material.attrValue, rotation: element.components.rotation.attrValue}; + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, numRings: element.children.length-1, ringPitch: element.children[0].components.geometry.attrValue.radiusOuter*2, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, material: element.components.material.attrValue, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; + } else if(element.id.includes("text")){ + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, text: element.components.text.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; + } else if(element.id.includes("timer")){ + text = JSON.parse(JSON.stringify(element.components.text.attrValue)) + text.value = "00:00.000" + jsonData[element.id] = {advanced: element.components.advanced.attrValue, angle: element.components.angle.attrValue, text: element.components.text.attrValue, position: {x: element.components.position.attrValue.x, y: element.components.position.attrValue.y, z: element.components.position.attrValue.z}, rotation: {x: element.components.rotation.attrValue.x, y: element.components.rotation.attrValue.y, z: element.components.rotation.attrValue.z}, movement: mov}; }}); - scenes[packageSelect.value][patternList.children[parseFloat(patternList.getAttribute('selectedIndex'))].textContent] = jsonData + scenes[packageSelect.value][patternList.children[parseFloat(patternList.getAttribute('selectedIndex'))].id] = jsonData } /* converts hex to RGB values */ diff --git a/Custom/editing.js b/Custom/editing.js index 8510ed4..d3b1ae1 100644 --- a/Custom/editing.js +++ b/Custom/editing.js @@ -9,7 +9,7 @@ function editEntity(){ /* checks for valid entries of universal changes */ if(isNaN(parseFloat($("#x").val())) || isNaN(parseFloat($("#y").val())) || isNaN(parseFloat($("#z").val()))){ alert("Please enter a valid position"); - return; + return false; } if(hexToRgb($("#color").val()) == null){ alert("Invalid color (check that the color was entered in hexadecimal format)"); @@ -23,18 +23,127 @@ function editEntity(){ return; } + let p1; + let p2; + let d; /* Checks whether the current entity is advanced or not */ + let animationComponent = selectedEntity.getAttribute('movement') if(selectedEntity.getAttribute('advanced').val){ /* Updates universal settings if advanced */ - selectedEntity.setAttribute("position",{x: parseFloat($("#x").val()), y: parseFloat($("#y").val()), z: -parseFloat($("#z").val())}); + d = (-Math.round(Math.sqrt((parseFloat($("#x").val()))*(parseFloat($("#x").val()))+(parseFloat($("#z").val()))*(parseFloat($("#z").val()))))) selectedEntity.setAttribute("angle",{x: ((Math.asin(parseFloat($("#x").val())/d))*180)/Math.PI, z: d}); selectedEntity.setAttribute("rotation",{x: parseFloat($("#rotationX").val()), y: parseFloat($("#rotationY").val()), z: parseFloat($("#rotationZ").val())}); + stopMovement(selectedEntity); + selectedEntity.setAttribute("position",{x: parseFloat($("#x").val()), y: parseFloat($("#y").val()), z: -parseFloat($("#z").val())}); + + p1 = {x: parseFloat($("#startX").val()), y: parseFloat($("#startY").val()), z: -parseFloat($("#startZ").val())} + p2 = {z: parseFloat($("#endX").val()), y: parseFloat($("#endY").val()), z: -parseFloat($("#endZ").val())} + + let xDelta = p2.x-p1.x + let yDelta = p2.y-p1.y + let zDelta = p2.z-p1.z + d = Math.sqrt((xDelta)*(xDelta) + (yDelta)*(yDelta) + (zDelta)*(zDelta)) + animationComponent.origin = {x: parseFloat($("#x").val()), y: parseFloat($("#y").val()), z: -parseFloat($("#z").val())} + animationComponent.rotationOrigin = {x: parseFloat($("#rotationX").val()), y: parseFloat($("#rotationY").val()), z: parseFloat($("#rotationZ").val())} + } else { /* Updates universal settings if not advanced */ - selectedEntity.setAttribute("position",{x: -parseFloat($("#z").val()) * Math.sin((-parseFloat($("#x").val())*Math.PI)/180), y: parseFloat($("#y").val()), z: -parseFloat($("#z").val()) * Math.cos((-parseFloat($("#x").val())*Math.PI)/180)}); + selectedEntity.setAttribute("angle",{x: -parseFloat($("#x").val()), z: -parseFloat($("#z").val())}) selectedEntity.setAttribute("rotation",{x: 0, y: selectedEntity.getAttribute('angle').x, z: parseFloat($("#rotationZ").val())}); + stopMovement(selectedEntity); + selectedEntity.setAttribute("position",{x: -parseFloat($("#z").val()) * Math.sin((-parseFloat($("#x").val())*Math.PI)/180), y: parseFloat($("#y").val()), z: -parseFloat($("#z").val()) * Math.cos((-parseFloat($("#x").val())*Math.PI)/180)}); + //if($('#animationTypeIn').val() == 'position'){ + p1 = {theta: parseFloat($("#startX").val()), y: parseFloat($("#startY").val()), r: -parseFloat($("#startZ").val())} + p2 = {theta: parseFloat($("#endX").val()), y: parseFloat($("#endY").val()), r: -parseFloat($("#endZ").val())} + let thetaDelta = (p2.theta-p1.theta) + let arcLen = Math.abs(thetaDelta*Math.PI/180)*Math.abs(p2.r); + let yDelta = Math.abs(p2.y-p1.y) + d = Math.sqrt((arcLen)*(arcLen) + (yDelta)*(yDelta)) + let animationComponent = selectedEntity.getAttribute('movement') + animationComponent.origin = {x: -parseFloat($("#z").val()) * Math.sin((-parseFloat($("#x").val())*Math.PI)/180), y: parseFloat($("#y").val()), z: -parseFloat($("#z").val()) * Math.cos((-parseFloat($("#x").val())*Math.PI)/180)} + animationComponent.rotationOrigin = {x: 0, y: selectedEntity.getAttribute('angle').x, z: parseFloat($("#rotationZ").val())} + + + //} + + } + + /* Updates Movement Animation */ + + let selectedIndex = parseFloat(animationList.getAttribute('selectedIndex')) + let i = 0; + let counter = -1; + console.log("Value of selected index: "+selectedIndex) + // have to take into account rebounds from rubberband + while(i < animationComponent.types.length){ + if(animationComponent.types[i] != 'Rebound'){ + counter++; + if(counter == selectedIndex){ + break + } + } + i++; + } + + + console.log("Value of i: "+i) + + if(i < animationComponent.types.length-1 && animationComponent.types[i+1] == 'Rebound'){ + animationComponent.startPoints.splice(i+1,1); + animationComponent.endPoints.splice(i+1,1); + animationComponent.initialVelocities.splice(i+1,1); + animationComponent.accelerations.splice(i+1,1); + animationComponent.types.splice(i+1,1); + } + if($('#movementTypeIn').val() == 'Pause'){ + animationComponent.types[i] = 'Pause' + console.log(parseFloat($("#speed").val())) + animationComponent.initialVelocities[i] = parseFloat($("#startY").val()); + animationComponent.accelerations[i] = 0; + animationComponent.status = -1 + animationComponent.index = 0 + animationComponent.timeElapsed = 0 + animationComponent.currentVelocity = 0 + } else if($('#movementTypeIn').val() == 'Rubberband'){ + animationComponent.startPoints[i] = p1; + animationComponent.startPoints.splice(i+1,0,p2); + animationComponent.endPoints[i] = p2; + animationComponent.endPoints.splice(i+1,0,p1); + animationComponent.initialVelocities[i] = parseFloat($("#speed").val()); + animationComponent.initialVelocities.splice(i+1,0,Math.sqrt(parseFloat($("#speed").val())**2+2*parseFloat($("#acceleration").val())*d)); + animationComponent.accelerations[i] = parseFloat($("#acceleration").val()); + animationComponent.accelerations.splice(i+1,0,parseFloat($("#acceleration").val())); + animationComponent.types[i] = 'Rubberband' + animationComponent.types.splice(i+1,0,'Rebound'); + animationComponent.status = -1 + animationComponent.index = 0 + animationComponent.timeElapsed = 0 + animationComponent.currentVelocity = 0 + + + //selectedEntity.setAttribute("animation__loopStart",{'property': 'position','to': p1Conv, 'from':p2Conv,'dur': dur, 'loop': true, 'startEvents': 'animLoopStart', 'pauseEvents': 'animLoopPause','dir': 'alternate', 'easing': 'linear'}) + //selectedEntity.setAttribute("animation__loopEnd",{'property': 'position','to': p2Conv, 'from':p1Conv,'dur': dur, 'loop': false, 'startEvents': 'animLoopEnd', 'pauseEvents': 'animLoopPause'}) + } else if($('#movementTypeIn').val() != 'None'){ + + animationComponent.startPoints[i] = p1; + animationComponent.endPoints[i] = p2; + animationComponent.initialVelocities[i] = parseFloat($("#speed").val()); + animationComponent.accelerations[i] = parseFloat($("#acceleration").val()); + animationComponent.types[i] = ($('#movementTypeIn').val() == 'Start') ? 'Start' :'Discontinuous' + animationComponent.status = -1 + animationComponent.index = 0 + animationComponent.timeElapsed = 0 + animationComponent.currentVelocity = 0 + + //selectedEntity.setAttribute("animation__loopStart",{'property': 'position','to': p1Conv, 'from':p2Conv, 'loop': false, 'startEvents': 'animLoopStart', 'pauseEvents': 'animLoopPause', 'easing': 'linear'}) + } + selectedEntity.setAttribute('movement',animationComponent) + updateMovementSettings() + + if(animationList.childElementCount != 0){ + animationList.children[selectedIndex].innerText = $('#movementTypeIn').val() } /* Adds a texture if a texture input is selected */ @@ -313,6 +422,50 @@ function editEntity(){ } // draw new boxes drawBullseye(parseFloat($("#ringPitchIn").val()),parseFloat($("#numRingsIn").val()),$("#color").val(),selectedEntity); - } + } else if (selectedEntity.getAttribute("id").includes("text")){ /* text only changes */ + + if(isNaN(parseFloat($("#width").val()))){ + alert("Please enter a valid width"); + return; + } + if(isNaN(parseFloat($("#height").val()))){ + alert("Please enter a valid height"); + return; + } + if(($("#text").val()) == ""){ + alert("Please enter a valid text option"); + return; + } + if(parseFloat($("#height").val()) < 0){ + alert("Please enter a valid height ( >= 0 )"); + return; + } else if(parseFloat($("#width").val()) < 0){ + alert("Please enter a valid width ( >= 0 )"); + return; + } + + selectedEntity.setAttribute('text', {value: $("#text").val(), width: parseFloat($("#width").val()), height: parseFloat($("#height").val()), color: $("#color").val(), wrapCount: $("#text").val().length}) + + } else if (selectedEntity.getAttribute("id").includes("timer")){ /* text only changes */ + + if(isNaN(parseFloat($("#width").val()))){ + alert("Please enter a valid width"); + return; + } + if(isNaN(parseFloat($("#height").val()))){ + alert("Please enter a valid height"); + return; + } + if(parseFloat($("#height").val()) < 0){ + alert("Please enter a valid height ( >= 0 )"); + return; + } else if(parseFloat($("#width").val()) < 0){ + alert("Please enter a valid width ( >= 0 )"); + return; + } + + selectedEntity.setAttribute('text', {value: selectedEntity.getAttribute('text').value, width: parseFloat($("#width").val()), height: parseFloat($("#height").val()), color: $("#color").val(), wrapCount: selectedEntity.getAttribute('text').value.length}) + + } updateJSON() // update the json file of current scene } \ No newline at end of file diff --git a/Custom/entityMovement.js b/Custom/entityMovement.js new file mode 100644 index 0000000..40f5a29 --- /dev/null +++ b/Custom/entityMovement.js @@ -0,0 +1,270 @@ +movementKeyBinds = {} +function calcNextPoint(p1,p2,covered){ + if(p1.r){ + thetaDelta = p2.theta-p1.theta + yDelta = p2.y-p1.y + newPoint = {theta: p1.theta+(thetaDelta*covered), y: p1.y+(yDelta*covered), r: p1.r} + } else { + xDelta = p2.x-p1.x + yDelta = p2.y-p1.y + zDelta = p2.z-p1.z + newPoint = {x: p1.x+(xDelta*covered), y: p1.y+(yDelta*covered), z: p1.z+(zDelta*covered)} + } + + + return newPoint; +} + +function toggleMovement(entPos){ + // Teleport + let ent = entityCanvas.children[entPos]; + if(ent.getAttribute('mov').type == 'Teleport'){ + toggle = false; + var tmp = setInterval((entPos) => { + let ent = entityCanvas.children[entPos]; + if(ent.getAttribute('mov').endPoint.r == null){ + if(toggle == false){ + ent.setAttribute('position',ent.getAttribute('mov').endPoint) + //ent.setAttribute("rotation", {x: 0, y: THETAX, z: 0}); // set rotation to be 0 + } else { + ent.setAttribute('position',ent.getAttribute('mov').startPoint) + } + } else { + if(toggle == false){ + ent.setAttribute('position',{x: -ent.getAttribute('mov').endPoint.r*Math.sin((ent.getAttribute('mov').endPoint.theta*Math.PI)/180), y: ent.getAttribute('mov').endPoint.y, z: ent.getAttribute('mov').endPoint.r * Math.cos((ent.getAttribute('mov').endPoint.theta*Math.PI)/180)}) + ent.setAttribute("rotation", {x: 0, y: -ent.getAttribute('mov').endPoint.theta, z: 0}); // set rotation to be 0 + //ent.setAttribute("rotation", {x: 0, y: THETAX, z: 0}); // set rotation to be 0 + } else { + ent.setAttribute('position',ent.getAttribute('mov').startPoint) + ent.setAttribute("rotation", {x: 0, y: ent.getAttribute('angle').x, z: 0}); // set rotation to be 0 + } + } + + toggle = !toggle; + },ent.getAttribute('mov').speed, entPos) + mov = ent.getAttribute('mov') + mov.status = tmp + ent.setAttribute('mov',mov) + return + } + + + if(ent.getAttribute('mov').endPoint.r == null){ + p1 = ent.getAttribute('mov').startPoint + xDelta = Math.abs(ent.getAttribute('mov').endPoint.x-p1.x) + yDelta = Math.abs(ent.getAttribute('mov').endPoint.y-p1.y) + zDelta = Math.abs(ent.getAttribute('mov').endPoint.z-p1.z) + d = Math.sqrt((xDelta)*(xDelta) + (yDelta)*(yDelta) + (zDelta)*(zDelta)) + steps = d/ent.getAttribute('mov').speed*60 + + } else { + p1 = {r: ent.getAttribute('angle').z, theta: -ent.getAttribute('angle').x, y: ent.getAttribute('mov').startPoint.y} + thetaDelta = (ent.getAttribute('mov').endPoint.theta-p1.theta) + arcLen = Math.abs(thetaDelta*Math.PI/180)*Math.abs(ent.getAttribute('mov').endPoint.r); + yDelta = Math.abs(ent.getAttribute('mov').endPoint.y-p1.y) + d = Math.sqrt((arcLen)*(arcLen) + (yDelta)*(yDelta)) + steps = d/ent.getAttribute('mov').speed*60 + } + console.log(d) + var prev = p1; + var num = 1; + var time = 1; + var toggle = true; + var endPoint = ent.getAttribute('mov').endPoint + var initialVelocity = ent.getAttribute('mov').speed + var entAcceleration = ent.getAttribute('mov').acceleration + var tmp = setInterval((entPos,p1,endPoint) => { + let ent = entityCanvas.children[entPos] + distanceCovered = (initialVelocity)*(num*(.017)) + 0.5*entAcceleration*((num*(.017))*(num*(.017))) + amtCovered = (distanceCovered/d) + if(amtCovered > 1){ + if(ent.getAttribute('mov').type == 'Rubberband'){ + num = 0; + if(toggle){ + //endPoint = Object.assign({},p1) + //p1 = ent.getAttribute('mov').endPoint + toggle = false; + } else { + //p1 = Object.assign({},endPoint) + //endPoint = ent.getAttribute('mov').endPoint + toggle = true; + } + + initialVelocity = initialVelocity + entAcceleration*time*(.017) + distanceCovered = (initialVelocity)*(num*(.017)) + 0.5*entAcceleration*((num*(.017))*(num*(.017))) + + amtCovered = (distanceCovered/d) + + } else { + num = 0; + } + } + + if(!toggle){ + res = calcNextPoint(endPoint,p1,amtCovered) + } else { + res = calcNextPoint(p1,endPoint,amtCovered) + } + + + if(ent.getAttribute('advanced').val){ + ent.setAttribute('position',{x: res.x, y: res.y, z: res.z}) + //ent.setAttribute("rotation", {x: 0, y: THETAX, z: 0}); // set rotation to be 0 + } else { + ent.setAttribute('position',{x: -res.r*Math.sin((res.theta*Math.PI)/180), y: res.y, z: res.r * Math.cos((res.theta*Math.PI)/180)}) + ent.setAttribute("rotation", {x: 0, y: -res.theta, z: 0}); // set rotation to be 0 + } + /*if(toggle){ + num++ + } else { + num-- + }*/ + num++; + time++; + },17,entPos,p1,endPoint) + mov = ent.getAttribute('mov') + mov.status = tmp + ent.setAttribute('mov',mov) +} + +function stopMovement(el){ + mov = el.getAttribute('movement') + clearInterval(mov.status) + mov.status = -1 + el.setAttribute('movement',mov) + movementIcon.className = "fa-solid fa-play"; +} + +/*function handleMovementToggle(e){ + e.stopPropagation() + if(selectedEntity.getAttribute('mov').type == 'None'){ + return + } + i = 0; + while(i < entityCanvas.children.length){ + if(entityCanvas.children[i] == selectedEntity){ + break; + } + i++; + } + if(movementIcon.className == "fa-solid fa-play"){ + toggleMovement(i); + movementIcon.className = "fa-solid fa-pause" + } else { + stopMovement(selectedEntity); + movementIcon.className = "fa-solid fa-play" + } +}*/ + + + function stopAllMovement(){ + let i = 0; + while(i < entityCanvas.children.length){ + mov = entityCanvas.children[i].getAttribute('movement') + mov.status = -1; + i++; + } + } + + function startAllMovement(){ + let i = 0; + while(i < entityCanvas.children.length){ + mov = entityCanvas.children[i].getAttribute('mov') + if(mov.type != 'None'){ + toggleMovement(i) + } + i++; + } + } + + function processConsecutiveMovement(entPos, movementArr){ + let ent = entityCanvas.children[entPos]; + let i = 0; + // movementArr [[startP,endP,speed,acc,type]...] + + if(movementArr[i][1].r == null){ + p1 = movementArr[i][0] + xDelta = Math.abs(movementArr[i][1].x-p1.x) + yDelta = Math.abs(movementArr[i][1].y-p1.y) + zDelta = Math.abs(movementArr[i][1].z-p1.z) + d = Math.sqrt((xDelta)*(xDelta) + (yDelta)*(yDelta) + (zDelta)*(zDelta)) + steps = d/movementArr[i][2]*60 + + } else { + // angle, angle, mov + p1 = movementArr[i][0] + thetaDelta = (movementArr[i][1].theta-p1.theta) + arcLen = Math.abs(thetaDelta*Math.PI/180)*Math.abs(movementArr[i][1].r); + yDelta = Math.abs(movementArr[i][1].y-p1.y) + d = Math.sqrt((arcLen)*(arcLen) + (yDelta)*(yDelta)) + steps = d/movementArr[i][2]*60 + } + console.log(d) + var prev = p1; + var num = 1; + var time = 1; + var toggle = true; + var endPoint = movementArr[i][1] + var initialVelocity = movementArr[i][2] + var entAcceleration = movementArr[i][3] + var tmp = setInterval((entPos,p1,endPoint, movementArr, i) => { + console.log(movementArr) + let ent = entityCanvas.children[entPos] + distanceCovered = (initialVelocity)*(num*(.017)) + 0.5*entAcceleration*((num*(.017))*(num*(.017))) + amtCovered = (distanceCovered/d) + if(amtCovered > 1){ + i++; + if(i > movementArr.length){ + clearInterval(tmp) + } + p1 = movementArr[i][0] + num = 1 + if(movementArr[i][1].r == null){ + p1 = movementArr[i][0] + xDelta = Math.abs(movementArr[i][1].x-p1.x) + yDelta = Math.abs(movementArr[i][1].y-p1.y) + zDelta = Math.abs(movementArr[i][1].z-p1.z) + d = Math.sqrt((xDelta)*(xDelta) + (yDelta)*(yDelta) + (zDelta)*(zDelta)) + steps = d/movementArr[i][2]*60 + + } else { + // angle, angle, mov + p1 = {r: movementArr[i][0].z, theta: -movementArr[i][0].x, y: movementArr[i][0].y} + thetaDelta = (movementArr[i][1].theta-p1.theta) + arcLen = Math.abs(thetaDelta*Math.PI/180)*Math.abs(movementArr[i][1].r); + yDelta = Math.abs(movementArr[i][1].y-p1.y) + d = Math.sqrt((arcLen)*(arcLen) + (yDelta)*(yDelta)) + steps = d/movementArr[i][2]*60 + } + endPoint = movementArr[i][1] + initialVelocity = movementArr[i][2] + entAcceleration = movementArr[i][3] + distanceCovered = (initialVelocity)*(num*(.017)) + 0.5*entAcceleration*((num*(.017))*(num*(.017))) + amtCovered = (distanceCovered/d) + + } + + res = calcNextPoint(endPoint,p1,amtCovered) + + + if(ent.getAttribute('advanced').val){ + ent.setAttribute('position',{x: res.x, y: res.y, z: res.z}) + //ent.setAttribute("rotation", {x: 0, y: THETAX, z: 0}); // set rotation to be 0 + } else { + ent.setAttribute('position',{x: -res.r*Math.sin((res.theta*Math.PI)/180), y: res.y, z: res.r * Math.cos((res.theta*Math.PI)/180)}) + ent.setAttribute("rotation", {x: 0, y: -res.theta, z: 0}); // set rotation to be 0 + } + /*if(toggle){ + num++ + } else { + num-- + }*/ + num++; + time++; + },17,entPos,p1,endPoint) + mov = ent.getAttribute('mov') + mov.status = tmp + ent.setAttribute('mov',mov) + + } + diff --git a/Custom/graphicInterface.js b/Custom/graphicInterface.js index 8cddb61..20a28bb 100644 --- a/Custom/graphicInterface.js +++ b/Custom/graphicInterface.js @@ -50,7 +50,97 @@ function hideEditStats(){ ringPitch.style.display = "none"; numRings.style.display = "none"; toggleCenterDot.style.display = "none"; + textIn.style.display = "none"; } + +function updateMovementSettings(){ + if(movementTypeIn.value == "Pause"){ + // + startHeader.style.display = "block" + startHeader.textContent = 'Time (ms)' + startX.style.display = "none" + startY.style.display = "block" + startZ.style.display = "none" + endHeader.style.display = "none" + endX.style.display = "none" + endY.style.display = "none" + endZ.style.display = "none" + speedHeader.style.display = "none" + //speedHeader.textContent = 'Time (ms)' + accelerationHeader.style.display = "none" + keyHeader.style.display = "none" + speed.style.display = "none" + acceleration.style.display = "none" + //keyBind.style.display = "none" + movementButtonContainer.style.display = "none" + } else if(movementTypeIn.value == "None"){ + if(selectedEntity.getAttribute('advanced').val){ + startHeader.innerHTML = 'Start Point (x: m, y: m, z: m)' + } else { + startHeader.innerHTML = 'Start Point (\u03B1: deg, y: m, r: m):' + } + startHeader.style.display = "none" + startX.style.display = "none" + startY.style.display = "none" + startZ.style.display = "none" + endHeader.style.display = "none" + endX.style.display = "none" + endY.style.display = "none" + endZ.style.display = "none" + speedHeader.style.display = "none" + accelerationHeader.style.display = "none" + keyHeader.style.display = "none" + speed.style.display = "none" + acceleration.style.display = "none" + //keyBind.style.display = "none" + movementButtonContainer.style.display = "none" + } else if(movementTypeIn.value == "Start" || movementTypeIn.value == "Rubberband"){ + if(selectedEntity.getAttribute('advanced').val){ + startHeader.innerHTML = 'Start Point (x: m, y: m, z: m)' + } else { + startHeader.innerHTML = 'Start Point (\u03B1: deg, y: m, r: m):' + } + startHeader.style.display = "block" + startX.style.display = "block" + startY.style.display = "block" + startZ.style.display = "block" + endHeader.style.display = "block" + endX.style.display = "block" + endY.style.display = "block" + endZ.style.display = "block" + speedHeader.style.display = "block" + speedHeader.innerText = "Speed (m/s)" + accelerationHeader.style.display = "block" + //keyHeader.style.display = "block" + speed.style.display = "block" + acceleration.style.display = "block" + //key.style.display = "block" + movementButtonContainer.style.display = "inline" + } else { + if(selectedEntity.getAttribute('advanced').val){ + startHeader.innerHTML = 'Start Point (x: m, y: m, z: m)' + } else { + startHeader.innerHTML = 'Start Point (\u03B1: deg, y: m, r: m):' + } + startHeader.style.display = "block" + startX.style.display = "block" + startY.style.display = "block" + startZ.style.display = "block" + endHeader.style.display = "block" + endX.style.display = "block" + endY.style.display = "block" + endZ.style.display = "block" + speedHeader.style.display = "block" + speedHeader.innerText = "Time (ms)" + accelerationHeader.style.display = "none" + //keyHeader.style.display = "block" + speed.style.display = "block" + acceleration.style.display = "none" + //key.style.display = "block" + movementButtonContainer.style.display = "inline" + } +} + var flag = false; /* updates values in edit section */ function updateStats(){ @@ -59,57 +149,99 @@ function updateStats(){ $('#skyCol').minicolors("value",sky.components.material.attrValue.color); entity = selectedEntity; if(selectedEntity.getAttribute('advanced').val){ + endZ.disabled = false + advanced.style.backgroundColor = '#00FF00' + console.log('advanced') posIn.innerHTML = 'Position (x: m, y: m, z: m):' + startHeader.innerHTML = 'Start Point (x: m, y: m, z: m)' + endHeader.innerHTML = 'End Point (x: m, y: m, z: m)' rotationY.style.display = 'block' rotationX.style.display = 'block' - - $("#x").change(function() { - editEntity(); - }); - - /* If the textbox for y value is changed */ - $("#y").change(function() { - editEntity(); - }); - - /* If the textbox for z value is changed */ - $("#z").change(function() { - editEntity(); - }); xIn.value = (entity.components.position.attrValue.x).toFixed(3); yIn.value = (entity.components.position.attrValue.y).toFixed(3); zIn.value = (-entity.components.position.attrValue.z).toFixed(3); + updateAnimationList(entity) + + if(animationList.getAttribute('selectedIndex') == ""){ + movementTypeIn.value = 'None' + } else { + movementTypeIn.value = entity.components.movement.attrValue.types[0] + updateMovementSettings() + + if(entity.components.movement.attrValue.startPoints.length != 0){ + + startX.value = entity.components.movement.attrValue.startPoints[0].x + startY.value = entity.components.movement.attrValue.startPoints[0].y + startZ.value = -entity.components.movement.attrValue.startPoints[0].z + endX.value = entity.components.movement.attrValue.endPoints[0].x + endY.value = entity.components.movement.attrValue.endPoints[0].y + endZ.value = -entity.components.movement.attrValue.endPoints[0].z + acceleration.value = entity.components.movement.attrValue.accelerations[0] + speed.value = entity.components.movement.attrValue.initialVelocities[0] + if(entity.components.movement.attrValue.types[0] == 'Pause'){ + startY.value = entity.components.movement.attrValue.initialVelocities[0] + } + } + + + } + } else { + endZ.disabled = true + advanced.style.backgroundColor ='' posIn.innerHTML = 'Position (\u03B1: deg, y: m, r: m):' + startHeader.innerHTML = 'Start Point (\u03B1: deg, y: m, r: m):' + endHeader.innerHTML = 'End Point (\u03B1: deg, y: m, r: m):' rotationY.style.display = 'none' rotationX.style.display = 'none' - - $("#x").change(function() { - editEntity(); - }); - - /* If the textbox for y value is changed */ - $("#y").change(function() { - editEntity(); - }); - - /* If the textbox for z value is changed */ - $("#z").change(function() { - editEntity(); - }); xIn.value = (-entity.components.angle.attrValue.x).toFixed(3); yIn.value = (entity.components.position.attrValue.y).toFixed(3); zIn.value = (-entity.components.angle.attrValue.z).toFixed(3); + + if(animationList.getAttribute('selectedIndex') == ""){ + console.log('test 2') + movementTypeIn.value = 'None' + } else { + movementTypeIn.value = entity.components.movement.attrValue.types[0] + updateMovementSettings() + + if(entity.components.movement.attrValue.startPoints.length != 0){ + startX.value = entity.components.movement.attrValue.startPoints[0].theta + startY.value = entity.components.movement.attrValue.startPoints[0].y + startZ.value = -entity.components.movement.attrValue.startPoints[0].r + endX.value = entity.components.movement.attrValue.endPoints[0].theta + endY.value = entity.components.movement.attrValue.endPoints[0].y + endZ.value = -entity.components.movement.attrValue.endPoints[0].r + acceleration.value = entity.components.movement.attrValue.accelerations[0] + speed.value = entity.components.movement.attrValue.initialVelocities[0] + if(entity.components.movement.attrValue.types[0] == 'Pause'){ + startY.value = entity.components.movement.attrValue.initialVelocities[0] + } + } + } + + } + + if(entity.components.movement.attrValue.status == -1){ + movementIcon.className = "fa-solid fa-play" + } else { + movementIcon.className = "fa-solid fa-pause" } rotationZ.value = (entity.components.rotation.attrValue.z).toFixed(3); rotationY.value = (entity.components.rotation.attrValue.y).toFixed(3); rotationX.value = (entity.components.rotation.attrValue.x).toFixed(3); - color.value = entity.components.material.attrValue.color; flag = true; - $('#color').minicolors("value",entity.components.material.attrValue.color); + if(selectedEntity.getAttribute("id").includes("text") || selectedEntity.getAttribute("id").includes("timer")){ + color.value = entity.components.text.attrValue.color; + $('#color').minicolors("value",entity.components.text.attrValue.color); + console.log(entity) + } else { + color.value = entity.components.material.attrValue.color; + $('#color').minicolors("value",entity.components.material.attrValue.color); + } flag = false; - if (entity.components.material.attrValue.src == "" || entity.components.material.attrValue.src == null){ + if (entity.components.text || entity.components.material.attrValue.src == "" || entity.components.material.attrValue.src == null){ texture.selectedIndex = 0; texture.options[0].selected = true; } else { @@ -168,14 +300,23 @@ function updateStats(){ } else if(selectedEntity.getAttribute("id").includes("bullseye")){ numRingsIn.value = (selectedEntity.children.length-1); ringPitchIn.value = selectedEntity.children[0].components.geometry.attrValue.radiusOuter*2; + } else if(selectedEntity.getAttribute("id").includes("text")){ + width.value = entity.components.text.attrValue.width; + height.value = entity.components.text.attrValue.height; + textIn.value = entity.components.text.attrValue.value; + } else if(selectedEntity.getAttribute("id").includes("timer")){ + width.value = entity.components.text.attrValue.width; + height.value = entity.components.text.attrValue.height; } } /* switches between add or edit mode or refreshes current mode display */ function toggleDisplayEdit(swap){ + /* check if swapping modes or refreshing display */ if(swap){ /* if the button to swap was pressed */ + stopAll() boolDisplayEdit = !boolDisplayEdit; /* change current mode */ } utility.checked = false; @@ -187,9 +328,13 @@ function toggleDisplayEdit(swap){ addEditContent.style.display = "none" packageLayout.style.display = "grid" swapContainer.style.width = "" + animationListButtonContainer.style.display = "none" + openAnimationList(true) + //settingsButton.setAttribute('') //scene_input.value = "" //toggleAddEdit(false); } else { /* if add */ + if(!isNaN(parseInt(patternList.getAttribute('selectedIndex')))){ if(coreLayout.style.gridTemplateColumns != "100% 0%"){ openSettings() @@ -197,10 +342,11 @@ function toggleDisplayEdit(swap){ settingsButtonContainer.style.display = "none" addEditContent.style.display = "block" packageLayout.style.display = "none" - swapContainer.style.textAlign = "center" - swapContainer.style.width = "224px" - swapContainer.style.paddingTop = "10px" - swapContainer.style.paddingLeft = "9px" + swapContainer.style.float = "left"; + swapContainer.style.paddingTop = "12px" + swapContainer.style.paddingLeft = "18px" + swapContainer.style.textAlign = "" + //animationListButtonContainer.style.display = "inline-block" //$('#skyCol').minicolors('value', scenes[patternDisplay.value]['sky'].skyColor); } else { alert("You must select a pattern"); @@ -210,7 +356,9 @@ function toggleDisplayEdit(swap){ swapContainer.style.paddingTop = "12px" swapContainer.style.paddingLeft = "18px" swapContainer.style.textAlign = "" + animationListButtonContainer.style.display = "none" } + } } @@ -218,6 +366,7 @@ function toggleDisplayEdit(swap){ function toggleAddEdit(swap){ /* check if swapping modes or refreshing display */ if(swap){ /* if the button to swap was pressed */ + stopAll() if(numAdded == 0){ alert("You must add an entity before editing the scene"); utility.checked = false; @@ -236,11 +385,12 @@ function toggleAddEdit(swap){ } /* check if current mode is add or edit */ if(boolAddEdit){ /* if edit */ + editContent.style.display = 'grid'; addContent.style.display = 'none'; background.style.display = "none"; skyIn.style.display = "none"; - + animationListButtonContainer.style.display = 'inline-block' /* check geometry of object */ @@ -317,7 +467,26 @@ function toggleAddEdit(swap){ numRings.style.display = "flex"; area2.style.display = "block"; ringPitch.style.display = "flex"; + } else if (selectedEntity.getAttribute("id").includes("text")){ + area1.style.display = "block"; + heightIn.style.display = "flex"; + area2.style.display = "block"; + widthIn.style.display = "flex"; + area3.style.display = "block"; + textIn.style.display = "flex"; + } else if (selectedEntity.getAttribute("id").includes("timer")){ + area1.style.display = "block"; + heightIn.style.display = "flex"; + area2.style.display = "block"; + widthIn.style.display = "flex"; } + updateAnimationList(entity) + if(animationList.childElementCount == 0){ + updateAnimationUI(entity,-1) + } else { + updateAnimationUI(entity,0) + } + } else { /* if add */ editContent.style.display = 'none' addContent.style.display = 'block' @@ -325,17 +494,23 @@ function toggleAddEdit(swap){ background.style.display = 'block' entitySelectorText.style.display = 'flex' skyIn.style.display = 'block' + animationListButtonContainer.style.display = 'none' + openAnimationList(true) } } function openSettings(){ if(coreLayout.style.gridTemplateColumns == "100% 0%"){ - coreLayout.style.width = "400px" - coreLayout.style.gridTemplateColumns = "65% 35%" + coreLayout.style.width = "500px" + coreLayout.style.gridTemplateColumns = "52% 48%" settingsButtonContainer.style.paddingRight = "40px" settingsButton.className = "button reset" settingsButton.title = "Close settings" settingsIcon.className = "fa-solid fa-close" + settingsButtonContainer.style.position = 'relative' + settingsButtonContainer.style.float = 'none' + settingsButtonContainer.style.right = '-50px' + } else { coreLayout.style.width = "260px" coreLayout.style.gridTemplateColumns = "100% 0%" @@ -343,6 +518,48 @@ function openSettings(){ settingsButton.className = "button add" settingsButton.title = "Open settings" settingsIcon.className = "fa-solid fa-gear" + settingsButtonContainer.style.float = 'right' + settingsButtonContainer.style.right = '' + settingsButtonContainer.style.position = '' + } +} + +function openAnimationList(forceClose){ + if(forceClose){ + coreLayout.style.width = "260px" + coreLayout.style.gridTemplateColumns = "100% 0%" + settingsButtonContainer.style.paddingRight = "14px" + animationListButton.className = "button add" + animationListButton.title = "Open animation list" + animationListIcon.className = "fa-solid fa-wand-sparkles" + animationListButtonContainer.style.float = 'right' + animationListButtonContainer.style.right = '' + animationListButtonContainer.style.position = '' + settingsLayout.style.gridTemplateRows = '30% 70% 100%' + settingsLayout.style.overflowY = 'hidden' + return + } + if(coreLayout.style.gridTemplateColumns == "100% 0%"){ + coreLayout.style.width = "500px" + coreLayout.style.gridTemplateColumns = "55% 45%" + settingsButtonContainer.style.paddingRight = "40px" + animationListButton.className = "button reset" + animationListButton.title = "Close animation list" + animationListIcon.className = "fa-solid fa-close" + animationListButtonContainer.style.position = 'relative' + animationListButtonContainer.style.float = 'none' + animationListButtonContainer.style.right = '-40px' + settingsLayout.style.gridTemplateRows = '0% 0% 100%' + } else { + coreLayout.style.width = "260px" + coreLayout.style.gridTemplateColumns = "100% 0%" + settingsButtonContainer.style.paddingRight = "14px" + animationListButton.className = "button add" + animationListButton.title = "Open animation list" + animationListIcon.className = "fa-solid fa-wand-sparkles" + animationListButtonContainer.style.float = 'right' + animationListButtonContainer.style.right = '' + animationListButtonContainer.style.position = '' } } @@ -376,10 +593,14 @@ function hideUniversal(){ //universalHeader.style.display = "none"; //uni.style.borderBottom = "0px solid #999"; uni.style.gridTemplateRows = "100% 0% 0% 0% 0% 0%" - if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ - editContent.style.gridTemplateRows = "8% 8% 5%" + if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ + editContent.style.gridTemplateRows = "8% 8% 8% 8%" + } else if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "8% 8% 50% 8%" + } else if(specificSettings.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "8% 50% 8% 8%" } else { - editContent.style.gridTemplateRows = "8% 50% 5%" + editContent.style.gridTemplateRows = "8% 50% 50% 8%" } } else { @@ -398,13 +619,18 @@ function hideUniversal(){ //universalHeader.style.display = "block"; //uni.style.borderBottom = "1px solid #999"; uni.style.gridTemplateRows = "17% 17% 16% 17% 16% 17%" - if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ - editContent.style.gridTemplateRows = "40% 8% 5%" + if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ + editContent.style.gridTemplateRows = "50% 8% 8% 8%" + } else if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "50% 8% 50% 8%" + } else if(specificSettings.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "50% 50% 8% 8%" } else { - editContent.style.gridTemplateRows = "40% 50% 5%" + editContent.style.gridTemplateRows = "50% 50% 50% 8%" } } } + var oldSize = null; function hideSpecific(){ if(specificSettings.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%"){ @@ -417,10 +643,14 @@ function hideSpecific(){ area4.style.display = "none" area5.style.display = "none" specificSettings.style.gridTemplateRows = "100% 0% 0% 0% 0% 0%" - if(uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ - editContent.style.gridTemplateRows = "8% 8% 5%" + if(uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ + editContent.style.gridTemplateRows = "8% 8% 8% 8%" + } else if(uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "8% 8% 50% 8%" + } else if(uni.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "50% 8% 8% 8%" } else { - editContent.style.gridTemplateRows = "40% 8% 5%" + editContent.style.gridTemplateRows = "50% 8% 50% 8%" } } else { @@ -430,10 +660,82 @@ function hideSpecific(){ specificSettings.style.gridTemplateRows = oldSize //universalHeader.style.display = "block"; //uni.style.borderBottom = "1px solid #999"; - if(uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ - editContent.style.gridTemplateRows = "8% 50% 5%" + if(uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ + editContent.style.gridTemplateRows = "8% 50% 8% 8%" + } else if(uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "8% 50% 50% 8%" + } else if(uni.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%" && movement.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "50% 50% 8% 8%" + } else { + editContent.style.gridTemplateRows = "50% 50% 50% 8%" + } + } +} + +function hideMovement(){ + + if(movement.style.gridTemplateRows != "100% 0% 0% 0% 0% 0% 0% 0%"){ + // hide + //hideUniversalIcon.className = "fa-solid fa-chevron-right" + movementType.style.display = "none" + startHeader.style.display = "none" + startX.style.display = "none" + startY.style.display = "none" + startZ.style.display = "none" + endHeader.style.display = "none" + endX.style.display = "none" + endY.style.display = "none" + endZ.style.display = "none" + speedHeader.style.display = "none" + accelerationHeader.style.display = "none" + keyHeader.style.display = "none" + speed.style.display = "none" + acceleration.style.display = "none" + //keyBind.style.display = "none" + movementButtonContainer.style.display = "none" + //universalHeader.style.display = "none"; + //uni.style.borderBottom = "0px solid #999"; + movement.style.gridTemplateRows = "100% 0% 0% 0% 0% 0% 0% 0%" + if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ + editContent.style.gridTemplateRows = "8% 8% 8% 8%" + } else if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && uni.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "50% 8% 8% 8%" + } else if(specificSettings.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%" && uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "8% 50% 8% 8%" + } else { + editContent.style.gridTemplateRows = "50% 50% 8% 8%" + } + + } else { + // show + //hideUniversalIcon.className = "fa-solid fa-chevron-down" + movementType.style.display = "block" + startHeader.style.display = "block" + startX.style.display = "block" + startY.style.display = "block" + startZ.style.display = "block" + endHeader.style.display = "block" + endX.style.display = "block" + endY.style.display = "block" + endZ.style.display = "block" + speedHeader.style.display = "block" + accelerationHeader.style.display = "block" + //keyHeader.style.display = "block" + speed.style.display = "block" + acceleration.style.display = "block" + //key.style.display = "block" + movementButtonContainer.style.display = "inline" + //universalHeader.style.display = "block"; + //uni.style.borderBottom = "1px solid #999"; + movement.style.gridTemplateRows = "11% 13% 11% 13% 11% 13% 12% 12%" + if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%"){ + editContent.style.gridTemplateRows = "8% 8% 50% 8%" + } else if(specificSettings.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%" && uni.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "50% 8% 50% 8%" + } else if(specificSettings.style.gridTemplateRows != "100% 0% 0% 0% 0% 0%" && uni.style.gridTemplateRows == "100% 0% 0% 0% 0% 0%") { + editContent.style.gridTemplateRows = "8% 50% 50% 8%" } else { - editContent.style.gridTemplateRows = "40% 50% 5%" + editContent.style.gridTemplateRows = "50% 50% 50% 8%" } } } @@ -467,11 +769,51 @@ let list; indexDrop = i; } } - console.log(index, indexDrop); if(index > indexDrop) { target.before( dragged ); } else { target.after( dragged ); } } - }); \ No newline at end of file + }); + + function updateAnimationList(entity){ + if(entity == null){ + animationList.innerHTML = "" + animationList.setAttribute('selectedIndex',"") + return + } + + console.log(entity) + let anims = entity.getAttribute('movement').types; + out = [] + let i = 0; + animationList.innerHTML = "" + animationList.setAttribute('selectedIndex',"") + while(i < anims.length){ + if(anims[i] != 'Rebound'){ + let el = document.createElement('li'); + el.innerText = anims[i] + if(i == 0){ + el.style.background ='#F39814' + animationList.setAttribute('selectedIndex',0) + } + + el.setAttribute('draggable',true) + el.addEventListener('dragstart', dragStart) + el.addEventListener('drop', droppedAnim) + el.addEventListener('dragenter', cancelDefault) + el.addEventListener('dragover', cancelDefault) + el.addEventListener('click',selectAnimation) + + animationList.appendChild(el) + animationList.scrollTo({ + top: 1000000000, + left: 0, + behavior: "smooth", + }); + } + i++; + } + + } \ No newline at end of file diff --git a/Custom/index.html b/Custom/index.html index a8f65eb..fe23965 100644 --- a/Custom/index.html +++ b/Custom/index.html @@ -72,7 +72,6 @@ AFRAME.registerComponent("click-checker", { init: function() { this.el.addEventListener("click", (e)=>{ - console.log(this.el); selectNew(this.el); }); this.el.addEventListener("mouseenter", (e) => { @@ -117,7 +116,20 @@ val: {type: 'boolean', default: false} }, }); + AFRAME.registerComponent('mov', { + schema: { + startPoint: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + endPoint: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + speed: {type: 'float', default: 10}, + acceleration: {type: 'float', default: 1}, + status: {type: 'float', default: 0}, + type: {type: 'string', default: "Rubberband"}, + startRotation: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + keyBind: {type: 'string', default: ''} + }, + }); + @@ -141,12 +153,12 @@ -
+
Display - Edit
+ Edit
Packages:
@@ -156,27 +168,28 @@

- Upload Package: + Upload Package:

Recent packages:
Pattern List:
    -
  1. red
  2. -
  3. green
  4. -
  5. blue
  6. -
  7. white
  8. -
  9. grille
  10. -
  11. crosshair
  12. -
  13. line
  14. -
  15. circular dot array
  16. -
  17. dot array
  18. -
  19. checkerboard_w
  20. -
  21. checkerboard_b
  22. -
  23. ring_w1
  24. -
  25. ring_w2
  26. -
  27. ring_w5
  28. +
  29. red
  30. +
  31. green
  32. +
  33. blue
  34. +
  35. white
  36. +
  37. grille
  38. +
  39. crosshair
  40. +
  41. line
  42. +
  43. circular dot array
  44. +
  45. dot array
  46. +
  47. checkerboard_w
  48. +
  49. checkerboard_b
  50. +
  51. ring_w1
  52. +
  53. ring_w2
  54. +
  55. ring_w5
  56. +
  57. Flying Spot
+ + + +
+ + +
Movement Settings
+
Movement Type:
+
Start Point (α: deg, y: m, r: m):
+
+
+
+
End Point (α: deg, y: m, r: m):
+
+
+
+
Speed (m/s)
+
Acceleration (m/s2)
+ +
+
+ + +
@@ -265,6 +360,8 @@ + +

@@ -278,6 +375,12 @@

+

Animation Settings

+

+ + + +

@@ -286,13 +389,13 @@
-
+
Package Settings:
-
+
-
+
Pattern Settings:
@@ -300,6 +403,11 @@
+
+
Animation List:
    +
  1. None
  2. +
+
@@ -309,9 +417,30 @@
-
+ + + + + + + + + + + + + + + + + + + + + + @@ -321,9 +450,12 @@ - - + + + + + diff --git a/Custom/load.js b/Custom/load.js index f75f00f..6e8ff2d 100644 --- a/Custom/load.js +++ b/Custom/load.js @@ -1,36 +1,25 @@ /* Loads in prebuilt scenes and adds them to scenes json */ -import red from './patterns/red.JSON' assert { type: "json" }; scenes['default']['red'] = red['scenes']['default'] -import green from './patterns/green.JSON' assert { type: "json" }; scenes['default']['green'] = green['scenes']['default'] -import blue from './patterns/blue.JSON' assert { type: "json" }; scenes['default']['blue'] = blue['scenes']['default'] -import white from './patterns/white.JSON' assert { type: "json" }; scenes['default']['white'] = white['scenes']['default'] -import grille from './patterns/grille.JSON' assert { type: "json" }; scenes['default']['grille'] = grille['scenes']['default'] -import line from './patterns/line.JSON' assert { type: "json" }; scenes['default']['line'] = line['scenes']['line'] -import checkerboard_w from './patterns/checkerboard_w.JSON' assert { type: "json" }; scenes['default']['checkerboard_w'] = checkerboard_w['scenes']['checkerboard_w'] -import checkerboard_b from './patterns/checkerboard_b.JSON' assert { type: "json" }; scenes['default']['checkerboard_b'] = checkerboard_b['scenes']['checkerboard_b'] -import dot_array from './patterns/dot array.JSON' assert { type: "json" }; scenes['default']['dot array'] = dot_array['scenes']['dot array'] -import circular_dot_array from './patterns/circularDotArray.JSON' assert { type: "json" }; scenes['default']['circular dot array'] = circular_dot_array['scenes']['circularDotArray'] -import crosshair from './patterns/crosshair.JSON' assert { type: "json" }; scenes['default']['crosshair'] = crosshair['scenes']['crosshair'] /*import bullseye from './patterns/bullseye.JSON' assert { type: "json" }; @@ -41,15 +30,16 @@ scenes['default']['ring_w5'] = ring_package['scenes']['ring_w5'] scenes['default']['ring_w10'] = ring_package['scenes']['ring_w10'] scenes['default']['ring_w20'] = ring_package['scenes']['ring_w20']*/ -import ring_w1 from './patterns/ring_w1.JSON' assert { type: "json" }; scenes['default']['ring_w1'] = ring_w1['scenes']['ring_w1'] -import ring_w2 from './patterns/ring_w2.JSON' assert { type: "json" }; scenes['default']['ring_w2'] = ring_w2['scenes']['ring_w2'] -import ring_w5 from './patterns/ring_w5.JSON' assert { type: "json" }; scenes['default']['ring_w5'] = ring_w5['scenes']['ring_w5'] +scenes['default']['Flying Spot'] = flying_spot['scenes']['Flying Spot'] + +console.log('Scenes') +console.log(scenes) /*let arr = Object.keys(scenes) let len = arr.length let i = 0; diff --git a/Custom/movementComponent.js b/Custom/movementComponent.js new file mode 100644 index 0000000..48f0dc8 --- /dev/null +++ b/Custom/movementComponent.js @@ -0,0 +1,232 @@ +AFRAME.registerComponent('movement', { + schema: { + origin: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + rotationOrigin: {type: 'vec3', default: {x: 0, y: 0, z: 0}}, + startPoints: {type: 'array', default: []}, + endPoints: {type: 'array', default: []}, + initialVelocities: {type: 'array', default: []}, + accelerations: {type: 'array', default: []}, + status: {type: 'float', default: -1}, + types: {type: 'array', default: []}, + index: {type: 'float', default: 0}, + currentVelocity: {type: 'float', default: 0}, + timeElapsed: {type: 'float', default: 0}, + }, + + init: function () { + // Do something when component first attached. + + }, + + update: function (oldData) { + // Do something when component's data is updated. + if(oldData.status != -1 && this.data.status == -1){ + // then we have been moved to the stopped status + // restore position to origin and rotation to rotationOrigin + this.el.setAttribute('position',this.data.origin) + this.el.setAttribute('rotation',this.data.rotationOrigin) + } + + }, + + remove: function () { + // Do something the component or its entity is detached. + }, + + tick: function (time, timeDelta) { + // Do something on every scene tick or frame. + if(this.data.status == 1){ + if(this.data.timeElapsed < 0){ + this.data.timeElapsed = 0 + + } else { + this.data.timeElapsed = this.data.timeElapsed + timeDelta + /*if(timerNum > 0){ + console.log(this.data.timeElapsed) + let timer = document.getElementById('timer0') + let textVal = timer.getAttribute('text') + let time = Math.floor(this.data.timeElapsed) + let minutes = Math.floor(time/1000/60) + time -= minutes*1000*60 + if(minutes < 10){ + minutes = "0"+minutes + } else { + minutes = ""+minutes + } + + let seconds = Math.floor(time/1000) + time -= seconds*1000 + if(seconds < 10){ + seconds = "0"+seconds + } else { + seconds = ""+seconds + } + if(time < 10){ + time = "00"+time + } else if(time < 100){ + time = "0"+time + } else { + time = ""+time + } + //console.log(time) + //textVal.value = minutes+":"+seconds+":"+time + textVal.value = minutes+":"+seconds+":"+time[0] + timer.setAttribute('text',textVal) + }*/ + } + this.updatePosition() + + } else if(this.data.status == -1){ + this.data.timeElapsed = -1; + + } + + + + }, + + updatePosition: function (time, timeDelta) { + // this algorithm will ignore cylindical movement to start + let data = this.data + + let startPoint = data.startPoints[data.index] + + // get endPoint + let endPoint = data.endPoints[data.index] + + + if(startPoint.x){ + // get startPoint + let startPoint = data.startPoints[data.index] + + // get endPoint + let endPoint = data.endPoints[data.index] + + if(data.types[data.index] == 'Pause'){ + /*if(this.data.index != 0 && data.types[data.index-1] != 'Pause'){ + this.el.setAttribute('position',data.endPoints[data.index-1]) + }*/ + if(data.timeElapsed >= data.initialVelocities[data.index]){ + //this.el.setAttribute('position',endPoint) + this.data.timeElapsed = 0 + if(data.index < data.startPoints.length-1){ + this.data.index = this.data.index + 1 + } else { + this.data.index = 0; + } + } + + } else if(data.types[data.index] == 'Discontinuous'){ + if(data.timeElapsed >= data.initialVelocities[data.index]){ + this.el.setAttribute('position',endPoint) + if(data.index < data.startPoints.length-1){ + this.data.index = this.data.index + 1 + } else { + this.data.index = 0; + } + } + } else { + // if the current type is start-to-finish or rubberband + // these are handled the same + // get total distance between points and amount of that distance covered + xDelta = endPoint.x-startPoint.x + yDelta = endPoint.y-startPoint.y + zDelta = endPoint.z-startPoint.z + d = Math.sqrt((xDelta)*(xDelta) + (yDelta)*(yDelta) + (zDelta)*(zDelta)) + distanceCovered = (data.initialVelocities[data.index])*(data.timeElapsed/1000) + 0.5*(data.accelerations[data.index])*((data.timeElapsed/1000)**2) + amtCovered = (distanceCovered/d) + if(amtCovered > 1){ + this.data.timeElapsed = 0 + amtCovered = 0 + if(data.index < data.startPoints.length-1){ + this.data.index = this.data.index + 1 + } else { + this.data.index = 0; + } + + } + + res = {x: startPoint.x+(xDelta*amtCovered), y: startPoint.y+(yDelta*amtCovered), z: startPoint.z+(zDelta*amtCovered)} + this.el.setAttribute('position',{x: res.x, y: res.y, z: res.z}) + } + } else { + + + if(data.types[data.index] == 'Pause'){ + /*if(this.data.index != 0 && data.types[data.index-1] != 'Pause'){ + this.el.setAttribute('position',{x: -data.endPoints[data.index-1].r*Math.sin((data.endPoints[data.index-1].theta*Math.PI)/180), y: data.endPoints[data.index-1].y, z: data.endPoints[data.index-1].r * Math.cos((data.endPoints[data.index-1].theta*Math.PI)/180)}) + } + console.log(this.el.getAttribute('position'))*/ + if(data.timeElapsed >= data.initialVelocities[data.index]){ + //this.el.setAttribute('position',endPoint) + this.data.timeElapsed = 0 + if(data.index < data.startPoints.length-1){ + this.data.index = this.data.index + 1 + } else { + this.data.index = 0; + } + } + + } else if(data.types[data.index] == 'Discontinuous'){ + if(data.timeElapsed >= data.initialVelocities[data.index]){ + this.el.setAttribute('position',{x: -endPoint.r*Math.sin((endPoint.theta*Math.PI)/180), y: endPoint.y, z: endPoint.r * Math.cos((endPoint.theta*Math.PI)/180)}) + this.el.setAttribute('rotation',{x: 0, y: -endPoint.theta, z: 0}) + this.data.timeElapsed = 0 + if(data.index < data.startPoints.length-1){ + this.data.index = this.data.index + 1 + } else { + this.data.index = 0; + } + + } + + + } else { + + + thetaDelta = Math.abs(endPoint.theta-startPoint.theta) + arcLen = Math.abs(thetaDelta*Math.PI/180)*Math.abs(endPoint.r); + yDelta = Math.abs(endPoint.y-startPoint.y) + d = Math.sqrt((arcLen)*(arcLen) + (yDelta)*(yDelta)) + + distanceCovered = (data.initialVelocities[data.index])*(data.timeElapsed/1000) + 0.5*(data.accelerations[data.index])*((data.timeElapsed/1000)**2) + + amtCovered = d ? (distanceCovered/d) : 0 + //console.log(amtCovered) + + + if(amtCovered > 1){ + this.data.timeElapsed = 0 + amtCovered = 0 + if(data.index < data.startPoints.length-1){ + this.data.index = this.data.index + 1 + } else { + this.data.index = 0; + } + startPoint = data.startPoints[data.index] + + // get endPoint + endPoint = data.endPoints[data.index] + thetaDelta = Math.abs(endPoint.theta-startPoint.theta) + arcLen = Math.abs(thetaDelta*Math.PI/180)*Math.abs(endPoint.r); + yDelta = Math.abs(endPoint.y-startPoint.y) + d = Math.sqrt((arcLen)*(arcLen) + (yDelta)*(yDelta)) + distanceCovered = (data.initialVelocities[data.index])*(data.timeElapsed/1000) + 0.5*(data.accelerations[data.index])*((data.timeElapsed/1000)**2) + amtCovered = (distanceCovered/d) + + + } + if(this.data.types[this.data.index] != 'Pause'){ + thetaDelta = endPoint.theta-startPoint.theta + yDelta = endPoint.y-startPoint.y + res = {theta: startPoint.theta+(thetaDelta*amtCovered), y: startPoint.y+(yDelta*amtCovered), r: startPoint.r} + + this.el.setAttribute('position',{x: -res.r*Math.sin((res.theta*Math.PI)/180), y: res.y, z: res.r * Math.cos((res.theta*Math.PI)/180)}) + this.el.setAttribute("rotation", {x: 0, y: -res.theta, z: 0}); // set rotation to be 0 + } + + } + } + + } +}); \ No newline at end of file diff --git a/Custom/pastebinInterface.js b/Custom/pastebinInterface.js index ba8309e..d7598c9 100644 --- a/Custom/pastebinInterface.js +++ b/Custom/pastebinInterface.js @@ -1,36 +1,65 @@ -// Contains all code that interfaces with the pastebin.run API +// Contains all code that interfaces with the pastebin.run API and local storage + /* On page load, fetch all packages that are contained within the link. Local storage is updated to reflect links. */ - packages = {default: ''} + window.onload = async function() { + // on page load get rid of the aframe cursor scene.canvas.classList.remove("a-grab-cursor") - let thisPage = new URL(window.location); + // if there is nothing in localStorage, instantiate an empty packages array + if(localStorage.getItem('packages') == null){ + localStorage.setItem('packages',JSON.stringify([])) + } + + // go through url and fetch desired packages + let thisPage = new URL(window.location); if(thisPage.searchParams.size != 0){ - - //let id = window.location.href.split(window.location.origin+'/Custom/index.html?id=')[1].split(',').forEach( async id => { - for (const id of thisPage.searchParams.get('id').split(',')) { - //console.log(id) - if(decodeURIComponent(id) == id){ - const res = await pastebinFetch('https://pastebin.run/'+id+'.txt',true); - } else { - const res = await pastebinFetch(decodeURIComponent(id),true); + // for each search parameter + for (const id of thisPage.searchParams.get('id').split(',')) { + //if the parameter is a pastebin id + + if(encodeURIComponent(id) == id){ + const res = await pastebinFetch('https://didsr.pythonanywhere.com/webxrtools/get?id='+id,true); + } else { + // otherwise the id is an uploaded link + const res = await pastebinFetch(decodeURIComponent(id),true); } } } - - - let i = 1; - while(i < localStorage.length){ + + + // fetch the packages array from localStorage + let localArr = JSON.parse(localStorage.getItem('packages')) + + // for each package in the array + localArr.forEach((package) => { + // get the name of the package + let key = Object.keys(package)[0] + + // add the package as an option to the recent pacakages dropdown var option = document.createElement("option"); - option.text = localStorage.getItem("key"+i) + option.text = key.split(' (')[0] + option.value = key recentPackages.add(option); - i++; - } - recentPackages.selectedIndex = -1 + + }) + recentPackages.selectedIndex = -1 // ensure that there are no selected recent packages + + // update the names dictionary for the default package on load + // done dynamically since we add/remove default patterns + let patternNames = Object.keys(scenes['default']); + patternNames.forEach((patternName) => { + // check if we have some type of name like test (1) and remove the (1) + if(patternName.split(' (').length > 1){ + patternName = patternName.split(' (')[0] + } + names['default'][patternName] = names['default'][patternName] ? names['default'][patternName] + 1 : 1; + }) + }; @@ -38,42 +67,90 @@ window.onload = async function() { Returns true on success and false on failure. */ defaultNum = 1; async function pastebinFetch(url,onload){ -var fileContent = await fetch(url).then((res) => { + + // fetch contents of JSON at url if it exists + var fileContent = await fetch(url).then((res) => { if(res.ok != true){ return null - - } else { - //console.log(url) - return res.json() + + } else { + + return res.json() } - }); + }).catch((error) => alert('Failed to import from: '+url+' with error '+error)); + // if there is no json object then alert and return if(fileContent == null){ alert('No package found') return false; } - //console.log(fileContent['filename']) - const re = /^[a-zA-Z0-9-_ ]+$/ - if(!re.test(fileContent['filename'])){ - alert('Package name is invalid. '+fileContent['filename']+' Limit names to only alphanumerics, -, _, or spaces.') - return false; - } - if(packages[fileContent['filename']] != null){ - if(onload && fileContent['filename'] == 'default'){ - fileContent['filename'] = 'default ('+ defaultNum++ +')' - } else { - alert('A package with this name already exists') + + // Begin name validation + + const re = /^[a-zA-Z0-9-_ ]+$/ // checks that names contain only alphanumerics, dash, underscore, or spaces + + // filename is present for pastebin files, otherwise it is a different link + if(fileContent['filename']){ + + if(!re.test(fileContent['filename'])){ + // failed regex validation indicating the file may have been tampered with + // since this name is not possible in the first place + alert('Package name is invalid. '+fileContent['filename']+' Limit names to only alphanumerics, -, _, or spaces.') return false; } + + // check if there is already a package that has this name + if(packages[fileContent['filename']] != null){ + // get a new name and continously check validate it until it passes or user aborts + let packageName = prompt('A package with the name '+ fileContent['filename'] +' already exists. Enter a new name for the package: ') + while(packageName == null || packageName == "" || !re.test(packageName) || scenes[packageName] != null){ + if(packageName == null){ + return + } else if(packageName == ""){ + packageName = prompt("Enter a valid package name: ") + } else if(!re.test(packageName)){ + packageName = prompt('Package name is invalid. '+ packageName +' Limit names to only alphanumerics, - , _ , or spaces.') + } else if(scenes[packageName] != null){ + packageName = prompt('A package with this name already exists. Enter a new name for the package: '); + } + } + fileContent['filename'] = packageName + } + + } else { + // the link provided was not from pastebin + + // get a new name and continously check validate it until it passes or user aborts + let packageName = prompt('Enter a name for this package: ') + while(packageName == null || packageName == "" || !re.test(packageName) || scenes[packageName] != null){ + if(packageName == null){ + return + } else if(packageName == ""){ + packageName = prompt("Enter a valid package name: ") + } else if(!re.test(packageName)){ + packageName = prompt('Package name is invalid. '+ packageName +' Limit names to only alphanumerics, - , _ , or spaces.') + } else if(scenes[packageName] != null){ + packageName = prompt('A package with this name already exists. Enter a new name for the package: '); + } + } + fileContent['filename'] = packageName } - names[fileContent['filename']] = {} + + names[fileContent['filename']] = {} // create new dictionary in names object to store names of patterns in requested file + + // Validate each pattern name in the package for (const [name, value] of Object.entries(fileContent['scenes'])) { - const re = /^[a-zA-Z0-9-_ ]+( \([0-9]+\))?$/ + const re = /^[a-zA-Z0-9-_ ]+( \([0-9]+\))?$/ // regex to check for a name like test_one-2 (1) + if(!re.test(name)){ + // failed regex validation indicating the file may have been tampered with + // since this name is not possible in the first place alert('Pattern name is invalid. '+name+' Limit names to only alphanumerics, -, _, or spaces.') delete names[fileContent['filename']] return false; } + + // update name dictionary currName = name.split(' (')[0]; if(names[fileContent['filename']][currName]){ currName = currName + ' ('+names[fileContent['filename']][currName]+')' @@ -81,35 +158,35 @@ var fileContent = await fetch(url).then((res) => { } else { names[fileContent['filename']][currName] = 1 } - } - if(url.split("https://pastebin.run/").length > 1){ - let out = manageLocalStorage(fileContent['filename'] + " ("+url.split("https://pastebin.run/")[1].split(".txt")[0]+")") + } + + // handle local storage updates + if(url.split("https://didsr.pythonanywhere.com/webxrtools/get?id=").length > 1){ + // if link came from pastebin, then only save pastebin id + let out = manageLocalStorage(fileContent['filename'] + " ("+url.split("https://didsr.pythonanywhere.com/webxrtools/get?id=")[1]+")", fileContent['scenes']) if(out == false){ return false; } - packages[fileContent['filename']] = url.split("https://pastebin.run/")[1].split(".txt")[0] + packages[fileContent['filename']] = url.split("https://didsr.pythonanywhere.com/webxrtools/get?id=")[1]// save id in packages } else { - let out = manageLocalStorage(fileContent['filename'] + " ("+encodeURIComponent(url)+")") + // if link is not from pastebin, save entire link address + let out = manageLocalStorage(fileContent['filename'] + " ("+encodeURIComponent(decodeURIComponent(url))+")", fileContent['scenes']) if(out == false){ return false; } packages[fileContent['filename']] = url - } - console.log(localStorage) - + } scenes[fileContent['filename']] = fileContent['scenes'] + // update list of textures + textures = fileContent['textures']['textureValues'] // texture images + uploadedTextureFormats = fileContent['textures']['uploadedTextureFormats'] // texture aspect ratios - - textures = fileContent['textures']['textureValues'] - uploadedTextureFormats = fileContent['textures']['uploadedTextureFormats'] - - let arr = Object.keys(scenes) - let len = arr.length + // merge incoming and existing textures let i = 0; - let len2 = texture.options.length; + let len = texture.options.length; currTextures = [] - while(i < len2){ + while(i < len){ currTextures.push(texture.options[i].text) i++; } @@ -127,11 +204,9 @@ var fileContent = await fetch(url).then((res) => { option.value = textures[uploadedTextures.indexOf(text)].val texture.add(option); } - - }) - + // merge incoming and existing texture formats newUploadedTextureFormat = [...new Set([...Object.keys(uploadedTextureFormat),...Object.keys(uploadedTextureFormats)])] tmp = {} newUploadedTextureFormat.forEach(texture => { @@ -143,28 +218,22 @@ var fileContent = await fetch(url).then((res) => { }); uploadedTextureFormat = tmp flag = false; - i = 0; - while(i < packageSelect.options.length){ - if(packageSelect.options[i].value == fileContent['filename']){ - alert('A package with this name already exists'); - return false; - } - i++; - } + // add option to packageSelect packageSelect.options.add(new Option(fileContent['filename'],fileContent['filename'])) packageSelect.value = fileContent['filename'] - changePackage() - return true; + + changePackage() // invokes the function change packages to the uploaded one + return true; // returns success } -// function to compress textures (unused) +// function to compress textures (unused right now) function compressTextures(textures){ textures.forEach( texture => { if(texture['val'].split("url(data:image/png;base64").length > 1){ // compress texture and post it // save id as pastebin() - //let compressed = LZString.compressToBase64(texture.val.split(',')[1].split(')')[0]) + let compressed = LZString.compressToBase64(texture.val.split(',')[1].split(')')[0]) let code = {name: texture['name'], val: texture.val.split(',')[1].split(')')[0]} //console.log(texture.val.split(',')[1].split(')')[0]) fetch('https://pastebin.run/api/v1/pastes', { @@ -183,57 +252,75 @@ function compressTextures(textures){ } }) } - }) + }).catch((error) => alert('Failed to import from: '+url+' with error '+error)) } + /* Posts content to pastebin. Navigates to new link on success and returns false on failure. */ async function pastebinPost(useTextures){ - textures = [] - // get all textures - i = 0; - while(i < texture.options.length){ - textures.push({val: texture.options[i].value, text: texture.options[i].text}); - i++; - } - let code = {filename: packageSelect.value, scenes: {}, textures: {uploadedTextureFormats: {}, textureValues: []}, date: ""} - - //let compressedTextures = compressTextures(textures); + // create object to be posted + let code = {filename: packageSelect.value, scenes: JSON.parse(JSON.stringify(scenes[packageSelect.value])), textures: {uploadedTextureFormats: {}, textureValues: []}, date: ""} + + // if we want to save textures if(useTextures){ + // get all textures + textures = [] + i = 0; + while(i < texture.options.length){ + textures.push({val: texture.options[i].value, text: texture.options[i].text}); + i++; + } code['textures']['textureValues'] = textures code['textures']['uploadedTextureFormats'] = uploadedTextureFormat } else { - console.log('made it') - for (const pattern of Object.keys(scenes[packageSelect.value])){ - for (const ent of Object.keys(scenes[packageSelect.value][pattern])){ + // clear all textures + console.log(code) + for (const pattern of Object.keys(code['scenes'])){ + for (const ent of Object.keys(code['scenes'][pattern])){ if(ent.includes('plane')){ - scenes[packageSelect.value][pattern][ent].material = {shader: scenes[packageSelect.value][pattern][ent].material.shader, color: scenes[packageSelect.value][pattern][ent].material.color, src: ''} + code['scenes'][pattern][ent].material = {shader: code['scenes'][pattern][ent].material.shader, color: code['scenes'][pattern][ent].material.color, src: ''} } } } } - code['scenes'] = scenes[packageSelect.value] - // add date + // save date code['date'] = new Date().toLocaleString(); - const size = new TextEncoder().encode(JSON.stringify(code)).length - if(size >= 9995){ + + // check size of package to ensure it can be posted + const size = new TextEncoder().encode(JSON.stringify(code)).length; + console.log('Package size: '+size) + /*if(size > 100000){ + // if too large then alert and abort alert('Package is too large, no link can be generated'); + return false - } - await fetch('https://pastebin.run/api/v1/pastes', { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' - }, - body: "code="+JSON.stringify(code) -}) - .then(response => {return response.text()}).then( async function (text) { + }*/ + + // attempt to post package + let response = await fetch('https://didsr.pythonanywhere.com/webxrtools/share', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(code) + }).catch((error) => alert('Failed to post with error:\n '+error)); + + if(!response.ok){ + console.log(response) + alert('Failed to post with error:\n '+response.status+"\n"+response.statusText) + return + } + + let text = await response.text(); + try { + // update the link and copy the code to the clipboard let thisPage = new URL(window.location); newUrl = thisPage.origin+thisPage.pathname+"?id="+text - manageLocalStorage(packageSelect.value+" ("+text+")"); + // store the package in local storage + manageLocalStorage(packageSelect.value+" ("+text+")", scenes[packageSelect.value]); tmp = packages[packageSelect.value] packages[packageSelect.value] = text await navigator.clipboard.writeText(newUrl); @@ -245,7 +332,6 @@ async function pastebinPost(useTextures){ let newURL = ''; if(tmp != null && tmp != ''){ newURL = window.location.href.replace(tmp,text) - console.log('test') } else { newURL = window.location.href + "," +text } @@ -256,63 +342,171 @@ async function pastebinPost(useTextures){ console.error('Failed to copy: ', err); return false } - }) -} + } + /* Adds packages to local storage. Returns true on success and throws an error on failure. */ -function manageLocalStorage(key){ - //console.log(key) - let i = localStorage.length < 11 ? localStorage.length : 10; - while(i > 0){ - localStorage.setItem("key"+i,localStorage.getItem("key"+(i-1))) - i--; +function manageLocalStorage(key, value){ + console.log('key '+key) + + // compress the package content + value = LZString.compressToBase64(JSON.stringify(value)) + + // get the contents of localStorage + let localScenes = JSON.parse(localStorage.getItem('packages')) + + // check if replacing existing package + let ind = null; + let j = 0; + localScenes.forEach((package) => { + let name = Object.keys(package)[0] + console.log(name) + if(encodeURIComponent(key.split(' (')[0]) == key.split(' (')[0]){ + // check for exact name match + if(name.split(' (')[0] === key.split(' (')[0]){ + ind = j + } + } else { + // check for link match + if(name.includes(key.split('(')[1].split(')')[0])){ + ind = j + } + } + j++; + }) + + + + sum = 0; + let max = localScenes.length-1 + for(let i = 0; i < max; i++){ + if(ind && i == ind){ + continue; + } + sum += ByteSize(localScenes[i]) + } + + + // create the object + let packageToInsert = {} + packageToInsert[key] = value + // strinify the object + let stringified = JSON.stringify(packageToInsert) + + // check if package is larger than localStorage space allocation + // 2 comes from the opening and closing braces [] + if(ByteSize(stringified) >= 5242880-2){ + alert('The package '+key+' is too large to save.') + return false } - localStorage.setItem("key1",key) - i = 2; - while(i < localStorage.length){ - if(localStorage.getItem("key"+i) == key){ - // delete current entry and shift everything down - while(i < localStorage.length-1){ - localStorage.setItem("key"+i,localStorage.getItem("key"+(i+1))) - i++; + + // if we have space + + // check if we are replacing an existing package with a new one + if(ind != null){ + // prompt if this is ok + console.log(ind) + let allowDelete = confirm('This process will replace the saved package: \n'+ Object.keys(localScenes[ind])[0]+'\nPress OK to confirm.') + if(!allowDelete){ + return true + } + localScenes.splice(ind,1) + console.log("Local Scenes") + console.log(localScenes) + max--; + } else { + let deleteCount = 0 + if(localScenes.length == 20 && sum + 2 + ByteSize(stringified) < 5242880){ + // insert without deleting + deleteCount++; + max--; + } else if(sum + 2 + ByteSize(stringified) >= 5242880){ + // check how many we would need to delete + // not optimal + while(sum + 2 + ByteSize(stringified) >= 5242880){ + sum -= ByteSize(JSON.stringify(localScenes[max])) + deleteCount++; + max--; } - localStorage.removeItem("key"+(localStorage.length-1)) - break; + } - i++; + + // check if user permits delete and then proceed + if(deleteCount > 0){ + let allowDelete = confirm('This process will delete '+ deleteCount +' previously saved packages. Press OK to confirm.') + if(!allowDelete){ + return true + } + localScenes.splice(max+1,deleteCount) + } + } - //console.log(localStorage) - return true; + + // add package to the beginning of localStorage array + localScenes.unshift(packageToInsert) + localStorage.setItem('packages',JSON.stringify(localScenes)) + + return true; // return success } -// Called when a package is selected from the local storage options +// Called when a package is selected from one of the local storage options async function changeUrl(){ if(recentPackages.value == "none"){ return } + // only 10 packages allowed in the browser at once if(packageSelect.options.length == 10){ alert('There are already 10 packages.') return; } - let url = recentPackages.value.split('(')[1].split(')')[0]; - if(decodeURIComponent(url) != url){ - url = decodeURIComponent(url) - } else { - url = 'https://pastebin.run/'+url+'.txt' + + // get contents of local storage + let localArr = JSON.parse(localStorage.getItem('packages')) + + // get the desired package from localStorage + let key = Object.keys(localArr[recentPackages.selectedIndex])[0] + + // prompt user for a name for the package and validate the input + let packageName = prompt("Enter a name for this package: ", key) + const re = /^[a-zA-Z0-9-_ ]+$/ + while(packageName == null || packageName == "" || !re.test(packageName) || scenes[packageName] != null){ + if(packageName == null){ + return + } else if(packageName == ""){ + packageName = prompt("Enter a valid package name: ") + } else if(!re.test(packageName)){ + packageName = prompt('Package name is invalid. Limit names to only alphanumerics, - , _ , or spaces.') + } else if(scenes[packageName] != null){ + packageName = prompt('A pattern with this name already exists'); + } + } - await pastebinFetch(url).then( res => { - if(res){ - if(!window.location.href.includes('?')){ - let newURL = window.location.href + "?id=" +recentPackages.value.split('(')[1].split(')')[0] - window.history.pushState('object', document.title, newURL); - } else { - let newURL = window.location.href + "," +recentPackages.value.split('(')[1].split(')')[0] - window.history.pushState('object', document.title, newURL); - } - } - }) + // add the selected package to the options list + packageSelect.options.add(new Option(packageName,packageName)) + packages[packageName] = '' + scenes[packageName] = JSON.parse(LZString.decompressFromBase64(localArr[recentPackages.selectedIndex][key])) + packageSelect.value = packageName + + // update the link + if(!key.includes('(upload)') && !window.location.href.includes(key.split('(')[1].split(')')[0])){ + if(!window.location.href.includes('?')){ + let newURL = window.location.href + "?id=" +key.split('(')[1].split(')')[0] + window.history.pushState('object', document.title, newURL); + } else { + let newURL = ''; + newURL = window.location.href + "," +key.split('(')[1].split(')')[0] + window.history.pushState('object', document.title, newURL); + } + } + + changePackage(); // invoke the function to change packages to the selected option +} + +// condensed function to get size of a string +function ByteSize(str){ + return new Blob([str]).size } diff --git a/Custom/patterns/Flying_Spot.JSON b/Custom/patterns/Flying_Spot.JSON new file mode 100644 index 0000000..7ee88f5 --- /dev/null +++ b/Custom/patterns/Flying_Spot.JSON @@ -0,0 +1,3326 @@ +{ + "scenes": { + "Flying Spot": { + "sky": { + "skyColor": "#000000" + }, + "circle0": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle1": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle2": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": -80, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 0, + "y": -80, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle3": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle4": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle5": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle6": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle7": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": 80, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 0, + "y": 80, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle8": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle9": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle10": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -20, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -20, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle11": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -10, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -10, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle12": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": 40, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 0, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 0, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 0, + "y": 40, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle13": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 10, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 10, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle14": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 20, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 20, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle15": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -20, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -20, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle16": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -10, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -10, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle17": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 0, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 0, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 0, + "y": 0, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle18": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 10, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 10, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle19": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 20, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 20, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle20": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -20, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -20, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle21": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -10, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -10, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle22": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": -40, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 0, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 0, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 0, + "y": -40, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle23": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 10, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 10, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle24": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 20, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 20, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle26": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle27": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -15, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -15, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle28": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -15, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -15, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle29": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -15, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -15, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle30": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle31": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle32": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -5, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -5, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle33": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -5, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -5, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle34": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -5, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -5, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle35": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle36": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle37": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 5, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 5, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle38": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 5, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 5, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle39": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 5, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 5, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle40": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle41": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle42": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 15, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 15, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle43": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 15, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 15, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle44": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 15, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 15, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle45": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [] + }, + "date": "1/19/2024, 12:41:28 PM" +} \ No newline at end of file diff --git a/Custom/patterns/blue.js b/Custom/patterns/blue.js new file mode 100644 index 0000000..7e7fc74 --- /dev/null +++ b/Custom/patterns/blue.js @@ -0,0 +1,47 @@ +var blue = { + "scenes": { + "default": { + "sky": { + "skyColor": "#0000ff" + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/bullseye.JSON b/Custom/patterns/bullseye.JSON index 424cd59..2ad3852 100644 --- a/Custom/patterns/bullseye.JSON +++ b/Custom/patterns/bullseye.JSON @@ -21,15 +21,28 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } + } }, "textures": { diff --git a/Custom/patterns/bullseye.js b/Custom/patterns/bullseye.js new file mode 100644 index 0000000..e01ed31 --- /dev/null +++ b/Custom/patterns/bullseye.js @@ -0,0 +1,86 @@ +var bullseye = { + "scenes": { + "bullseye": { + "sky": { + "skyColor": "#000000" + }, + "bullseye0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "numRings": 30, + "ringPitch": 5, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/checkerboard_b.JSON b/Custom/patterns/checkerboard_b.JSON index 4959ab8..b618c81 100644 --- a/Custom/patterns/checkerboard_b.JSON +++ b/Custom/patterns/checkerboard_b.JSON @@ -25,13 +25,25 @@ }, "material": { "shader": "flat", - "color": "#000000", - "src": "" + "color": "#000000" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/checkerboard_b.js b/Custom/patterns/checkerboard_b.js new file mode 100644 index 0000000..f07ba58 --- /dev/null +++ b/Custom/patterns/checkerboard_b.js @@ -0,0 +1,89 @@ +var checkerboard_b = { + "scenes": { + "checkerboard_b": { + "sky": { + "skyColor": "#000000" + }, + "checkerboard0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "rows": 17, + "cols": 17, + "tileSize": 10, + "color2": { + "val": "#ffffff" + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#000000" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/checkerboard_w.JSON b/Custom/patterns/checkerboard_w.JSON index 8070d6f..44bcf16 100644 --- a/Custom/patterns/checkerboard_w.JSON +++ b/Custom/patterns/checkerboard_w.JSON @@ -25,13 +25,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/checkerboard_w.js b/Custom/patterns/checkerboard_w.js new file mode 100644 index 0000000..d3fbbc0 --- /dev/null +++ b/Custom/patterns/checkerboard_w.js @@ -0,0 +1,89 @@ +var checkerboard_w = { + "scenes": { + "checkerboard_w": { + "sky": { + "skyColor": "#000000" + }, + "checkerboard0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "rows": 17, + "cols": 17, + "tileSize": 10, + "color2": { + "val": "#000000" + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/circularDotArray.JSON b/Custom/patterns/circularDotArray.JSON index 4620b03..09a5aca 100644 --- a/Custom/patterns/circularDotArray.JSON +++ b/Custom/patterns/circularDotArray.JSON @@ -26,13 +26,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/circularDotArray.js b/Custom/patterns/circularDotArray.js new file mode 100644 index 0000000..5d9eea5 --- /dev/null +++ b/Custom/patterns/circularDotArray.js @@ -0,0 +1,90 @@ +var circular_dot_array = { + "scenes": { + "circularDotArray": { + "sky": { + "skyColor": "#000000" + }, + "circularDotarray0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "toggleCenterDot": {"val": false}, + "circles": 10, + "dots": 20, + "arraySpacing": { + "val": 15 + }, + "circleSize": 1.5, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/crosshair.JSON b/Custom/patterns/crosshair.JSON index c90171a..8b85553 100644 --- a/Custom/patterns/crosshair.JSON +++ b/Custom/patterns/crosshair.JSON @@ -36,6 +36,19 @@ "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } }, "plane1": { @@ -70,6 +83,19 @@ "x": 0, "y": 0, "z": 90 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":90}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/crosshair.js b/Custom/patterns/crosshair.js new file mode 100644 index 0000000..f54c842 --- /dev/null +++ b/Custom/patterns/crosshair.js @@ -0,0 +1,141 @@ +var crosshair = { + "scenes": { + "crosshair": { + "sky": { + "skyColor": "#000000" + }, + "plane0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "widthReal": 1, + "fill": { + "val": 1, + "isFull": true + }, + "geometry": { + "primitive": "plane", + "width": 0, + "height": 15 + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + }, + "plane1": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "widthReal": 1, + "fill": { + "val": 1, + "isFull": true + }, + "geometry": { + "primitive": "plane", + "width": 0, + "height": 15 + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 90 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":90}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/dot array.JSON b/Custom/patterns/dot array.JSON index bf4a9b2..1bf6b90 100644 --- a/Custom/patterns/dot array.JSON +++ b/Custom/patterns/dot array.JSON @@ -26,13 +26,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/dot array.js b/Custom/patterns/dot array.js new file mode 100644 index 0000000..5709f22 --- /dev/null +++ b/Custom/patterns/dot array.js @@ -0,0 +1,90 @@ +var dot_array = { + "scenes": { + "dot array": { + "sky": { + "skyColor": "#000000" + }, + "dotarray0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "toggleCenterDot": {"val": false}, + "rows": 21, + "cols": 21, + "circleSize": 2, + "spacing": { + "val": 3 + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/flying_spot.js b/Custom/patterns/flying_spot.js new file mode 100644 index 0000000..c610555 --- /dev/null +++ b/Custom/patterns/flying_spot.js @@ -0,0 +1,3283 @@ +// this one is a little long + +var flying_spot = { + "scenes": { + "Flying Spot": { + "sky": { + "skyColor": "#000000" + }, + "circle0": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle1": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle2": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": -80, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 0, + "y": -80, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle3": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 43.412044416732584, + "y": -80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle4": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 85.50503583141717, + "y": -80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle5": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle6": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle7": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": 80, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 0, + "y": 80, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle8": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 43.412044416732584, + "y": 80, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle9": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 85.50503583141717, + "y": 80, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle10": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -20, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -20, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle11": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -10, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -10, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle12": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": 40, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 0, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 0, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 0, + "y": 40, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle13": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 10, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 10, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 43.412044416732584, + "y": 40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle14": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 20, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 20, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 85.50503583141717, + "y": 40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle15": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -20, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -20, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle16": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -10, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -10, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle17": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 0, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 0, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 0, + "y": 0, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle18": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 10, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 10, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 43.412044416732584, + "y": 0, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle19": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 20, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 20, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 85.50503583141717, + "y": 0, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle20": { + "advanced": { + "val": false + }, + "angle": { + "x": 20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -20, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -20, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": 20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle21": { + "advanced": { + "val": false + }, + "angle": { + "x": 10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -10, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -10, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": 10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle22": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 0, + "y": -40, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 0, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 0, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 0, + "y": -40, + "z": -250 + }, + "rotationOrigin": { + "x": 0, + "y": 0, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle23": { + "advanced": { + "val": false + }, + "angle": { + "x": -10, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -10, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 10, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 10, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 43.412044416732584, + "y": -40, + "z": -246.201938253052 + }, + "rotationOrigin": { + "x": 0, + "y": -10, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle24": { + "advanced": { + "val": false + }, + "angle": { + "x": -20, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -20, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 20, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 20, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 85.50503583141717, + "y": -40, + "z": -234.9231551964771 + }, + "rotationOrigin": { + "x": 0, + "y": -20, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle26": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle27": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -15, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -15, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle28": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -15, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -15, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle29": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -15, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -15, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle30": { + "advanced": { + "val": false + }, + "angle": { + "x": 15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": 15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle31": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle32": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -5, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": -5, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle33": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -5, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": -5, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle34": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": -5, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": -5, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": -21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle35": { + "advanced": { + "val": false + }, + "angle": { + "x": 5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": -21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": -21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": 5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle36": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 21.78893568691454, + "y": 80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle37": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 5, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 5, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 21.78893568691454, + "y": 40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle38": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 5, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 5, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 21.78893568691454, + "y": 0, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle39": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 5, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 5, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 21.78893568691454, + "y": -40, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle40": { + "advanced": { + "val": false + }, + "angle": { + "x": -5, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -5, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 21.78893568691454, + "y": -80, + "z": -249.04867452293638 + }, + "rotationOrigin": { + "x": 0, + "y": -5, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle41": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 64.70476127563019, + "y": 80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + }, + "circle42": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 15, + "y": 40, + "r": -250 + }, + { + "theta": -65, + "y": 40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 40, + "r": -250 + }, + { + "theta": 15, + "y": 40, + "r": -250 + } + ], + "initialVelocities": [ + 10, + 10 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 64.70476127563019, + "y": 40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle43": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 15, + "y": 0, + "r": -250 + }, + { + "theta": -65, + "y": 0, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": 0, + "r": -250 + }, + { + "theta": 15, + "y": 0, + "r": -250 + } + ], + "initialVelocities": [ + 20, + 20 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 64.70476127563019, + "y": 0, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle44": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [ + { + "theta": 15, + "y": -40, + "r": -250 + }, + { + "theta": -65, + "y": -40, + "r": -250 + } + ], + "endPoints": [ + { + "theta": 65, + "y": -40, + "r": -250 + }, + { + "theta": 15, + "y": -40, + "r": -250 + } + ], + "initialVelocities": [ + 40, + 40 + ], + "accelerations": [ + 0, + 0 + ], + "types": [ + "Start", + "Start" + ], + "origin": { + "x": 64.70476127563019, + "y": -40, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": 0 + } + }, + "circle45": { + "advanced": { + "val": false + }, + "angle": { + "x": -15, + "z": -250 + }, + "geometry": { + "primitive": "ring", + "radiusOuter": 2, + "radiusInner": 0, + "segmentsTheta": 100 + }, + "fill": { + "val": 2, + "isFull": true + }, + "position": { + "x": 64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": -15, + "z": 0 + }, + "movement": { + "startPoints": [], + "endPoints": [], + "initialVelocities": [], + "accelerations": [], + "types": [], + "origin": { + "x": 64.70476127563019, + "y": -80, + "z": -241.4814565722671 + }, + "rotationOrigin": { + "x": 0, + "y": -15, + "z": 0 + }, + "status": -1, + "index": 0, + "currentVelocity": 0, + "timeElapsed": -1 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [] + }, + "date": "1/19/2024, 12:41:28 PM" +} \ No newline at end of file diff --git a/Custom/patterns/green.js b/Custom/patterns/green.js new file mode 100644 index 0000000..f7e9a09 --- /dev/null +++ b/Custom/patterns/green.js @@ -0,0 +1,47 @@ +var green = { + "scenes": { + "default": { + "sky": { + "skyColor": "#00ff00" + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/grille.JSON b/Custom/patterns/grille.JSON index 56a043d..cc0c14d 100644 --- a/Custom/patterns/grille.JSON +++ b/Custom/patterns/grille.JSON @@ -28,13 +28,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/grille.js b/Custom/patterns/grille.js new file mode 100644 index 0000000..42bad2d --- /dev/null +++ b/Custom/patterns/grille.js @@ -0,0 +1,92 @@ +var grille = { + "scenes": { + "default": { + "sky": { + "skyColor": "#000000" + }, + "grille0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "numBars": 100, + "childGeometry": { + "primitive": "plane", + "width": 10, + "height": 450 + }, + "color2": { + "val": "#000000" + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/line.JSON b/Custom/patterns/line.JSON index 50029ea..ea65b7d 100644 --- a/Custom/patterns/line.JSON +++ b/Custom/patterns/line.JSON @@ -36,6 +36,19 @@ "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/line.js b/Custom/patterns/line.js new file mode 100644 index 0000000..89ecb3c --- /dev/null +++ b/Custom/patterns/line.js @@ -0,0 +1,94 @@ +var line = { + "scenes": { + "line": { + "sky": { + "skyColor": "#000000" + }, + "plane0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "widthReal": 1, + "fill": { + "val": 1, + "isFull": true + }, + "geometry": { + "primitive": "plane", + "width": 0, + "height": 1000 + }, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff", + "src": "" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/red.js b/Custom/patterns/red.js new file mode 100644 index 0000000..f863415 --- /dev/null +++ b/Custom/patterns/red.js @@ -0,0 +1,47 @@ +var red = { + "scenes": { + "default": { + "sky": { + "skyColor": "#ff0000" + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/ring_w1.JSON b/Custom/patterns/ring_w1.JSON index 4d4d79d..b77b3ef 100644 --- a/Custom/patterns/ring_w1.JSON +++ b/Custom/patterns/ring_w1.JSON @@ -21,13 +21,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/ring_w1.js b/Custom/patterns/ring_w1.js new file mode 100644 index 0000000..d347508 --- /dev/null +++ b/Custom/patterns/ring_w1.js @@ -0,0 +1,85 @@ +var ring_w1 = { + "scenes": { + "ring_w1": { + "sky": { + "skyColor": "#000000" + }, + "bullseye0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "numRings": 30, + "ringPitch": 1, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/ring_w2.JSON b/Custom/patterns/ring_w2.JSON index e0995ec..3ca1c58 100644 --- a/Custom/patterns/ring_w2.JSON +++ b/Custom/patterns/ring_w2.JSON @@ -21,13 +21,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/ring_w2.js b/Custom/patterns/ring_w2.js new file mode 100644 index 0000000..4e779c5 --- /dev/null +++ b/Custom/patterns/ring_w2.js @@ -0,0 +1,85 @@ +var ring_w2 = { + "scenes": { + "ring_w2": { + "sky": { + "skyColor": "#000000" + }, + "bullseye0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "numRings": 30, + "ringPitch": 2, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/ring_w5.JSON b/Custom/patterns/ring_w5.JSON index 1cbdd04..e5bd642 100644 --- a/Custom/patterns/ring_w5.JSON +++ b/Custom/patterns/ring_w5.JSON @@ -21,13 +21,25 @@ }, "material": { "shader": "flat", - "color": "#ffffff", - "src": "" + "color": "#ffffff" }, "rotation": { "x": 0, "y": 0, "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 } } } diff --git a/Custom/patterns/ring_w5.js b/Custom/patterns/ring_w5.js new file mode 100644 index 0000000..b47faaf --- /dev/null +++ b/Custom/patterns/ring_w5.js @@ -0,0 +1,85 @@ +var ring_w5 = { + "scenes": { + "ring_w5": { + "sky": { + "skyColor": "#000000" + }, + "bullseye0": { + "advanced": { + "val": false + }, + "angle": { + "x": 0, + "z": -250 + }, + "numRings": 30, + "ringPitch": 5, + "position": { + "x": 0, + "y": 0, + "z": -250 + }, + "material": { + "shader": "flat", + "color": "#ffffff" + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + }, + "movement":{ + "startPoints":[], + "endPoints":[], + "initialVelocities":[], + "accelerations":[], + "types":[], + "origin":{"x":0,"y":0,"z":-250}, + "rotationOrigin":{"x":0,"y":0,"z":0}, + "status":-1, + "index":0, + "currentVelocity":0, + "timeElapsed":0 + } + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/patterns/white.js b/Custom/patterns/white.js new file mode 100644 index 0000000..4e199af --- /dev/null +++ b/Custom/patterns/white.js @@ -0,0 +1,47 @@ +var white = { + "scenes": { + "default": { + "sky": { + "skyColor": "#ffffff" + } + } + }, + "textures": { + "uploadedTextureFormats": {}, + "textureValues": [ + { + "val": "none", + "text": "none" + }, + { + "val": "QC", + "text": "TG18-QC.2k_12b" + }, + { + "val": "CH", + "text": "TG18-CH.2k" + }, + { + "val": "MM1", + "text": "TG18-MM1.2k" + }, + { + "val": "MM2", + "text": "TG18-MM2.2k" + }, + { + "val": "sQC", + "text": "TG270sQC" + }, + { + "val": "PQC", + "text": "TG18-PQC.2k_12b" + }, + { + "val": "BR", + "text": "TG18-BR.2k_12b" + } + ] + }, + "date": "6/15/2023, 10:54:47 PM" +} \ No newline at end of file diff --git a/Custom/script.js b/Custom/script.js index 187d1e7..9aa58d4 100644 --- a/Custom/script.js +++ b/Custom/script.js @@ -146,6 +146,8 @@ const numRingsIn = document.getElementById("numRingsIn"); /* number of rings inp const ringPitch = document.getElementById("ringPitch"); /* ring pitch container paragraph */ const ringPitchIn = document.getElementById("ringPitchIn"); /* ring pitch input */ +const textIn = document.getElementById("text"); + const settingsButtonContainer = document.getElementById("settingsButtonContainer"); const settingsButton = document.getElementById("settingsButton"); const settingsIcon = document.getElementById("settingsIcon"); @@ -187,6 +189,41 @@ const editPatternLayout = document.getElementById('editPatternLayout'); const packageSelect = document.getElementById('packageDisplay') const recentPackages = document.getElementById('recentPackages') +const movement = document.getElementById('movementSettings'); +const movementButton = document.getElementById('movementButton'); +const movementButtonContainer = document.getElementById('movementButtonContainer'); +const stopIndividualButton = document.getElementById('stopIndividualButton'); +const movementIcon = document.getElementById('movementIcon'); +const movementType = document.getElementById('movementType'); +const movementTypeIn = document.getElementById('movementTypeIn'); +const movementHeader = document.getElementById('movementHeader'); +const startHeader = document.getElementById('startHeader'); +const endHeader = document.getElementById('endHeader'); +const startX = document.getElementById('startX'); +const startY = document.getElementById('startY'); +const startZ = document.getElementById('startZ'); +const endX = document.getElementById('endX'); +const endY = document.getElementById('endY'); +const endZ = document.getElementById('endZ'); +const speedHeader = document.getElementById('speedHeader'); +const accelerationHeader = document.getElementById('accelerationHeader'); +//const keyHeader = document.getElementById('keyHeader'); +const speed = document.getElementById('speed'); +const acceleration = document.getElementById('acceleration'); +//const keyBind = document.getElementById('key'); + +const animationButton = document.getElementById('animationButton') +const animationList = document.getElementById('movementAnims-list') +const animationListIcon = document.getElementById('animationListIcon') +const animationListButton = document.getElementById('animationListButton') +const animationListButtonContainer = document.getElementById('animationListButtonContainer') +const settingsLayout = document.getElementById('settingsLayout') + +const startAllButton = document.getElementById('startAllButton') +const pauseAllButton = document.getElementById('pauseAllButton') +const stopAllButton = document.getElementById('stopAllButton') + + /* Local Variables */ var el = null; /* recently created entity */ var els = new Array(); /* array of all created entities */ @@ -205,6 +242,8 @@ var grilleNum = 0; var dotarrayNum = 0; var circularDotarrayNum = 0; var bullseyeNum = 0; +var textNum = 0; +var timerNum = 0; var textureNum = 0; var numAdded = 0; /* total entities added */ @@ -216,6 +255,9 @@ var fileContent = null; /* contents of uploaded JSON file */ var uploadedTextureFormat = {}; var scenes = {default: {}}; +const packages = {default: ''} // dictionary of packages and their respective links +const names = {default: {}} // list of packages and the names and count of names of each pattern within + patternList.setAttribute('multi-select',false); @@ -234,21 +276,42 @@ items.forEach(item => { let i = 0; let reorderedScene = {} while(i < patternList.children.length){ - reorderedScene[patternList.children[i].innerHTML] = scenes[packageSelect.value][patternList.children[i].innerHTML] + reorderedScene[patternList.children[i].id] = scenes[packageSelect.value][patternList.children[i].id] i++; } scenes[packageSelect.value] = reorderedScene // handles a pattern being selected from the pattern list function selectPattern (e){ - if(e.target.style.background == 'rgb(243, 152, 20)'){ // if selected pattern is highlighted, unselect it + stopAllMovement() + if(e.target.style.background == 'rgb(243, 152, 20)' && patternList.getAttribute("multi-select") == false){ // if selected pattern is highlighted, unselect it e.target.style.background = '#FFF' patternList.setAttribute("selectedIndex","") patternList.setAttribute("multi-select",false); revertChanges() //nameIn.value = packageSelect.value; return; + } else if(e.target.style.background == 'rgb(243, 152, 20)' && patternList.getAttribute("multi-select") == 'true'){ + e.target.style.background = '#FFF'; + first = true; + items.forEach(item => { // changes displayed pattern to selected pattern + if(item.style.background == 'rgb(243, 152, 20)' && first) { + first = false; + patternList.setAttribute("selectedIndex",$(item).index()) + + revertChanges() + addEntitiesFromScene(scenes[packageSelect.value][patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].id]) + //nameIn.value = patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].textContent; + if(els.length > 0){ + selectedEntity = els[0] + } + } else if(item.style.background == 'rgb(243, 152, 20)' && !first){ + patternList.setAttribute("multi-select",true); + } + }) + return; } + e.target.style.background = '#F39814' // highlights selected pattern items = document.querySelectorAll('#items-list > li'); if(keysPressed['ctrl'] && !isNaN(parseInt(patternList.getAttribute('selectedIndex')))){ // checks for multiselect @@ -262,16 +325,39 @@ function selectPattern (e){ patternList.setAttribute("selectedIndex",$(item).index()) patternList.setAttribute("multi-select",false); revertChanges() - addEntitiesFromScene(scenes[packageSelect.value][patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].textContent]) + addEntitiesFromScene(scenes[packageSelect.value][patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].id]) //nameIn.value = patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].textContent; if(els.length > 0){ selectedEntity = els[0] } } }) + /*let i = 0; + while(i < els.length){ + if(!els[i].getAttribute('movement')){ + els[i].setAttribute("movement",{'startPoints': [],'endPoints': [],'initialVelocities':[],'accelerations':[],'types':[],'origin': els[i].getAttribute('position'), 'rotationOrigin': els[i].getAttribute('rotation'), 'status': -1, 'index': 0, 'currentVelocity': 0, 'timeElapsed': 0}) + } + i++; + }*/ + + setTimeout(() => { + if(els[0] && els[0].getAttribute('movement').types.length > 0){ + updateAnimationList(els[0]) + animationList.setAttribute('selectedIndex',0) + updateStats() + + } else { + updateAnimationList(els[0]) + } + + },200) + + } + + /* Code to make pattern list elements draggable */ function dragStart (e) { var index = $(e.target).index() @@ -301,7 +387,7 @@ function dropped (e) { let i = 0; let reorderedScene = {} while(i < patternList.children.length){ - reorderedScene[patternList.children[i].innerHTML] = scenes[packageSelect.value][patternList.children[i].innerHTML] + reorderedScene[patternList.children[i].id] = scenes[packageSelect.value][patternList.children[i].id] i++; } scenes[packageSelect.value] = reorderedScene @@ -315,6 +401,278 @@ function cancelDefault (e) { } +// animation list functionality + +let animations = document.querySelectorAll('#movementAnims-list > li'); + +animations.forEach(item => { + $(item).prop('draggable', true) + item.addEventListener('dragstart', dragStart) + item.addEventListener('drop', droppedAnim) + item.addEventListener('dragenter', cancelDefault) + item.addEventListener('dragover', cancelDefault) + item.addEventListener('click',selectAnimation) +}) + +let j = 0; + + +// handles a pattern being selected from the pattern list +function selectAnimation (e){ + stopMovement(selectedEntity) + if(e.target.style.background == 'rgb(243, 152, 20)'){ // if selected pattern is highlighted, unselect it + e.target.style.background = '#FFF' + animationList.setAttribute("selectedIndex","") + movementTypeIn.disabled = true + //revertChanges() + //nameIn.value = packageSelect.value; + return; + } + e.target.style.background = '#F39814' // highlights selected pattern + items = document.querySelectorAll('#movementAnims-list > li'); + items.forEach(item => { // changes displayed pattern to selected pattern + if(item != e.target){ + item.style.background = '#FFF' + } else { + animationList.setAttribute("selectedIndex",$(item).index()) + movementTypeIn.disabled = false + updateAnimationUI(selectedEntity,$(item).index()) + + + // add in functionality that will update animation info based on selected + + } + }) +} + +function updateAnimationUI(entity, ind) { + if(ind == -1){ + movementTypeIn.value = "None" + movementTypeIn.disabled = true + updateMovementSettings() + return + } + + let mov = entity.getAttribute('movement') + let i = 0; + let counter = -1; + + // have to take into account rebounds from rubberband + while(i < mov.types.length){ + if(mov.types[i] != 'Rebound'){ + counter++; + if(counter == ind){ + break + } + } + i++; + } + + if(entity.getAttribute('advanced').val){ + startX.value = mov.startPoints[i].x + startY.value = mov.startPoints[i].y + startZ.value = -mov.startPoints[i].z + endX.value = mov.endPoints[i].x + endY.value = mov.endPoints[i].y + endZ.value = -mov.endPoints[i].z + } else { + startX.value = mov.startPoints[i].theta + startY.value = mov.startPoints[i].y + startZ.value = -mov.startPoints[i].r + endX.value = mov.endPoints[i].theta + endY.value = mov.endPoints[i].y + endZ.value = -mov.endPoints[i].r + } + + movementTypeIn.value = mov.types[i] + acceleration.value = mov.accelerations[i] + speed.value = mov.initialVelocities[i] + movementTypeIn.disabled = false + if(mov.types[i] == 'Pause'){ + startY.value = mov.initialVelocities[i] + } + updateMovementSettings() + +} + +function droppedAnim (e) { + cancelDefault(e) + stopMovement(selectedEntity) + + // get new and old index + let oldIndex = e.dataTransfer.getData('text/plain') + let target = $(e.target) + let newIndex = target.index() + + // find oldIndex equivalent and newIndex equivalent in types + let i = 0; + let oldI = -1; + let newI = -1; + let counterOld = -1; + let counterNew = -1; + + let movementComponent = selectedEntity.getAttribute('movement') + // have to take into account rebounds from rubberband + while(i < movementComponent.types.length){ + if(movementComponent.types[i] != 'Rebound'){ + if(counterOld == oldIndex && counterNew == newIndex){ + break + } + + if(counterOld != oldIndex){ + counterOld++; + if(counterOld == oldIndex){ + oldI = i + } + } + if(counterNew != newIndex){ + counterNew++; + if(counterNew == newIndex){ + newI = i + } + } + } + i++; + } + + + // remove dropped items at old place + if(newIndex != oldIndex){ + let dropped = $(this).parent().children().eq(oldIndex).remove() + + // insert the dropped items at new place + if (newIndex < oldIndex) { + target.before(dropped) + } else { + target.after(dropped) + } + if(animationList.getAttribute('selectedIndex') == oldIndex){ + animationList.setAttribute('selectedIndex',newIndex); + } + } + + if(movementComponent.types[newIndex] == 'Rubberband'){ + // insert at newIndex+2 + newIndex += 1; + } + + if(oldI > newI){ + if(movementComponent.types[oldI] == 'Rubberband'){ + // remove both oldI and oldI+1 + let points = movementComponent.startPoints.splice(oldI,2); + let points2 = movementComponent.endPoints.splice(oldI,2); + let vels = movementComponent.initialVelocities.splice(oldI,2); + let accelerations = movementComponent.accelerations.splice(oldI,2); + let types = movementComponent.types.splice(oldI,2); + + movementComponent.startPoints.splice(newI,0,...points) + movementComponent.endPoints.splice(newI,0,...points2) + movementComponent.initialVelocities.splice(newI,0,...vels) + movementComponent.accelerations.splice(newI,0,...accelerations) + movementComponent.types.splice(newI,0,...types) + + } else { + // remove oldI + let points = movementComponent.startPoints.splice(oldI,1); + let points2 = movementComponent.endPoints.splice(oldI,1); + let vels = movementComponent.initialVelocities.splice(oldI,1); + let accelerations = movementComponent.accelerations.splice(oldI,1); + let types = movementComponent.types.splice(oldI,1); + + movementComponent.startPoints.splice(newI,0,...points) + movementComponent.endPoints.splice(newI,0,...points2) + movementComponent.initialVelocities.splice(newI,0,...vels) + movementComponent.accelerations.splice(newI,0,...accelerations) + movementComponent.types.splice(newI,0,...types) + } + + } else if(newI > oldI) { + // remove then insert at newI - 1 or - 2 if newI + if(movementComponent.types[oldI] == 'Rubberband'){ + // remove both oldI and oldI+1 + let points = movementComponent.startPoints.splice(oldI,2); + let points2 = movementComponent.endPoints.splice(oldI,2); + let vels = movementComponent.initialVelocities.splice(oldI,2); + let accelerations = movementComponent.accelerations.splice(oldI,2); + let types = movementComponent.types.splice(oldI,2); + + if(movementComponent.types[newI-1] == 'Rubberband'){ + movementComponent.startPoints.splice(newI,0,...points) + movementComponent.endPoints.splice(newI,0,...points2) + movementComponent.initialVelocities.splice(newI,0,...vels) + movementComponent.accelerations.splice(newI,0,...accelerations) + movementComponent.types.splice(newI,0,...types) + } else { + movementComponent.startPoints.splice(newI-1,0,...points) + movementComponent.endPoints.splice(newI-1,0,...points2) + movementComponent.initialVelocities.splice(newI-1,0,...vels) + movementComponent.accelerations.splice(newI-1,0,...accelerations) + movementComponent.types.splice(newI-1,0,...types) + } + + } else { + // remove oldI + let points = movementComponent.startPoints.splice(oldI,1); + let points2 = movementComponent.endPoints.splice(oldI,1); + let vels = movementComponent.initialVelocities.splice(oldI,1); + let accelerations = movementComponent.accelerations.splice(oldI,1); + let types = movementComponent.types.splice(oldI,1); + + if(movementComponent.types[newI-1] == 'Rubberband'){ + movementComponent.startPoints.splice(newI+1,0,...points) + movementComponent.endPoints.splice(newI+1,0,...points2) + movementComponent.initialVelocities.splice(newI+1,0,...vels) + movementComponent.accelerations.splice(newI+1,0,...accelerations) + movementComponent.types.splice(newI+1,0,...types) + } else { + movementComponent.startPoints.splice(newI,0,...points) + movementComponent.endPoints.splice(newI,0,...points2) + movementComponent.initialVelocities.splice(newI,0,...vels) + movementComponent.accelerations.splice(newI,0,...accelerations) + movementComponent.types.splice(newI,0,...types) + } + } + + } + + /*if(oldIndex < movementComponent.types.length-1 && movementComponent.types[oldIndex+1] == 'Rebound'){ + // remove both oldIndex and oldIndex+1 + let points = movementComponent.startPoints.splice(oldIndex,2); + let points2 = movementComponent.endPoints.splice(oldIndex,2); + let vels = movementComponent.initialVelocities.splice(oldIndex,2); + let accelerations = movementComponent.accelerations.splice(oldIndex,2); + let types = movementComponent.types.splice(oldIndex,2); + + movementComponent.startPoints.splice(newIndex,0,...points) + movementComponent.endPoints.splice(newIndex,0,...points2) + movementComponent.initialVelocities.splice(newIndex,0,...vels) + movementComponent.accelerations.splice(newIndex,0,...accelerations) + movementComponent.types.splice(newIndex,0,...types) + + } else { + let points = movementComponent.startPoints.splice(oldIndex,1); + let points2 = movementComponent.endPoints.splice(oldIndex,1); + let vels = movementComponent.initialVelocities.splice(oldIndex,1); + let accelerations = movementComponent.accelerations.splice(oldIndex,1); + let types = movementComponent.types.splice(oldIndex,1); + + movementComponent.startPoints.splice(newIndex,0,...points) + movementComponent.endPoints.splice(newIndex,0,...points2) + movementComponent.initialVelocities.splice(newIndex,0,...vels) + movementComponent.accelerations.splice(newIndex,0,...accelerations) + movementComponent.types.splice(newIndex,0,...types) + + }*/ + + + + updateJSON() + //scenes[packageSelect.value] = reorderedScene + +} + + + // SOURCE https://stackoverflow.com/questions/16616722/sending-all-javascript-console-output-into-a-dom-element // Writes console information to the debug div which can be opened by pressing ctrl+i diff --git a/Custom/sharing.js b/Custom/sharing.js index 47b8b05..32ed0f7 100644 --- a/Custom/sharing.js +++ b/Custom/sharing.js @@ -43,12 +43,12 @@ async function handleImport(){ return res; }) if(res2){ - if(url.includes('pastebin')){ + if(url.includes('https://didsr.pythonanywhere.com/webxrtools/get?id=')){ if(!window.location.href.includes('?')){ - let newURL = window.location.href + "?id=" +url.split("https://pastebin.run/")[1].split(".txt")[0] + let newURL = window.location.href + "?id=" +url.split("https://didsr.pythonanywhere.com/webxrtools/get?id=")[1] window.history.pushState('object', document.title, newURL); } else { - let newURL = window.location.href + "," +url.split("https://pastebin.run/")[1].split(".txt")[0] + let newURL = window.location.href + "," +url.split("https://didsr.pythonanywhere.com/webxrtools/get?id=")[1] window.history.pushState('object', document.title, newURL); } } else { @@ -83,7 +83,7 @@ async function localLinkImport(url){ let i = 0; while(i < ids.length){ console.log(ids[i]) - var res = pastebinFetch("https://pastebin.run/"+ids[i]+".txt").then((result) => { + var res = pastebinFetch("https://didsr.pythonanywhere.com/webxrtools/get?id="+ids[i]).then((result) => { return result }); if(!res){ @@ -105,7 +105,7 @@ async function validateLink(url){ console.log(url) return res.json() } - }); + }).catch((error) => alert('Failed to fetch from: '+url+' with error '+error)); if(fileContent == null || !fileContent.hasOwnProperty('filename') || !fileContent.hasOwnProperty('date') || !fileContent.hasOwnProperty('scenes') || !fileContent.hasOwnProperty('textures')){ return false; } @@ -113,3 +113,19 @@ async function validateLink(url){ } + + + // go through each property + // if property is not filename, date, scenes, or textures JSON has been tampered with + + + + + + // if scenes + + + // if textures + // check that texture urls do not lead to dangerous place and image does not contain malicious code + + diff --git a/Custom/uploading.js b/Custom/uploading.js index 8cb97a9..65c91ca 100644 --- a/Custom/uploading.js +++ b/Custom/uploading.js @@ -127,6 +127,7 @@ function entityLoader(fileContent,name,def,isSingle){ /* adds entities from json to current scene */ function addEntitiesFromScene(scene){ // go through each key in the scene + console.log(scenes) Object.keys(scene).forEach(key => { // handle adding entity similar to drawing entity if(key.includes("sky")){ @@ -184,17 +185,40 @@ function addEntitiesFromScene(scene){ } else if (key.includes("bullseye")){ el.setAttribute("id", "bullseye"+bullseyeNum++); drawBullseye(scene[key].ringPitch,scene[key].numRings,scene[key].material.color,el); + } else if (key.includes("text")){ + el.setAttribute("id", "text"+textNum++); + el.setAttribute("text",scene[key].text) + } else if (key.includes("timer")){ + el.setAttribute("id", "timer"+timerNum++); + console.log(timerNum) + el.setAttribute("text",scene[key].text) } /* sets stats */ el.setAttribute("angle", scene[key].angle); el.setAttribute("advanced", scene[key].advanced); el.setAttribute("position", {x: scene[key].position.x, y: scene[key].position.y, z: scene[key].position.z}); - el.setAttribute("material", scene[key].material); + let mat = null; + if(scene[key].material){ + mat = JSON.parse(JSON.stringify(scene[key].material)) + + for(let i = 0; i < texture.options.length; i++){ + if(texture.options[i].text == mat.src){ + mat.src = "#"+texture.options[i].value; + break; + } + } + } + + + console.log(mat) + el.setAttribute("material", mat); el.setAttribute("rotation", scene[key].rotation); + el.setAttribute("movement",JSON.parse(JSON.stringify(scene[key].movement))) el.setAttribute("click-checker",""); numAdded++; entityCanvas.appendChild(el); /* adds entity to scene */ + /* adds option to dropdown */ var option = document.createElement("option"); option.text = el.getAttribute("id"); @@ -204,4 +228,4 @@ function addEntitiesFromScene(scene){ pool.push(el.object3D); } }) -} \ No newline at end of file +} diff --git a/Custom/utility.js b/Custom/utility.js index d3e9430..fccba60 100644 --- a/Custom/utility.js +++ b/Custom/utility.js @@ -21,6 +21,12 @@ function selectNew(clickedEntity){ hideEditStats(); /* hide section briefly */ updateStats(); /* update stats */ toggleAddEdit(null); /* re-display section */ + updateAnimationList(selectedEntity) + if(animationList.childElementCount == 0){ + animationList.setAttribute('selectedIndex',"") + } else { + animationList.setAttribute('selectedIndex',0) + } highlightSelection(selectedEntity); } @@ -37,7 +43,7 @@ function removeEntity(){ } els.splice(els.indexOf(selectedEntity),1); pool.splice(pool.indexOf(selectedEntity.object3D),1); - if(selectedEntity.id.includes("plane")){ + /*if(selectedEntity.id.includes("plane")){ planeNum--; } else if(selectedEntity.id.includes("circle")){ circleNum--; @@ -53,7 +59,7 @@ function removeEntity(){ circularDotarrayNum--; } else if(selectedEntity.id.includes("dotarray")){ dotarrayNum--; - } + }*/ entityCanvas.removeChild(selectedEntity); for (var i=0; i 20){ + textContent = currName.substring(0,20)+"..." + } scenes[packageSelect.value][currName] = {sky: {skyColor: '#000000'}} - var toggle_button = '
  • '+currName+'
  • '; + var toggle_button = '
  • '+textContent+'
  • '; $('#items-list').append(toggle_button) @@ -296,6 +340,93 @@ function addPattern(){ patternList.children[patternList.children.length-1].dispatchEvent(new Event('click',{target: patternList.children[parseInt(patternList.getAttribute('selectedIndex'))+1]})); } +function addMovementAnim(){ + var toggle_button = '
  • Pause
  • '; + let el = document.createElement('li'); + el.innerText = "Pause" + + el.setAttribute('draggable',true) + el.addEventListener('dragstart', dragStart) + el.addEventListener('drop', droppedAnim) + el.addEventListener('dragenter', cancelDefault) + el.addEventListener('dragover', cancelDefault) + el.addEventListener('click',selectAnimation) + + animationList.appendChild(el) + + + + + + animationList.scrollTo({ + top: 1000000000, + left: 0, + behavior: "smooth", + }); + let movementComponent = selectedEntity.getAttribute('movement'); + if(selectedEntity.getAttribute('advanced').val){ + movementComponent.startPoints.push({x: 0, y: 0, z: -250}); + movementComponent.endPoints.push({x: 0, y: 0, z: -250}); + movementComponent.initialVelocities.push(0); + movementComponent.accelerations.push(0); + movementComponent.types.push('Pause'); + } else { + movementComponent.startPoints.push({theta: 0, y: 0, r: -250}); + movementComponent.endPoints.push({theta: 0, y: 0, r: -250}); + movementComponent.initialVelocities.push(0); + movementComponent.accelerations.push(0); + movementComponent.types.push('Pause'); + } + + + +} + +function removeMovementAnim(){ + // remove animation from entity + if(animationList.childElementCount == 0){ + return + } + stopMovement(selectedEntity) + + let index = parseInt(animationList.getAttribute('selectedIndex')) + let i = 0; + let counter = -1; + let movementComponent = selectedEntity.getAttribute('movement'); + // have to take into account rebounds from rubberband + while(i < movementComponent.types.length){ + if(movementComponent.types[i] != 'Rebound'){ + counter++; + if(counter == index){ + break + } + } + i++; + } + + + if(movementComponent.types[i] == 'Rubberband'){ + // need to remove this and also and rebound entry + movementComponent.types.splice(i,2) + movementComponent.startPoints.splice(i,2) + movementComponent.endPoints.splice(i,2) + movementComponent.initialVelocities.splice(i,2) + movementComponent.accelerations.splice(i,2) + } else { + movementComponent.types.splice(i,1) + movementComponent.startPoints.splice(i,1) + movementComponent.endPoints.splice(i,1) + movementComponent.initialVelocities.splice(i,1) + movementComponent.accelerations.splice(i,1) + } + animationList.removeChild(animationList.children[i]) + animationList.setAttribute('selectedIndex',"") + updateAnimationUI(selectedEntity,-1) + movementTypeIn.disabled = true + + updateJSON(); +} + /* removes current pattern from pattern list */ function removePattern(){ if(patternList.childElementCount == 0 || isNaN(parseInt(patternList.getAttribute('selectedIndex')))){ @@ -317,7 +448,7 @@ function removePattern(){ children = [] revertChanges() indices.forEach(ind => { - delete scenes[packageSelect.value][patternList.children[ind].textContent] + delete scenes[packageSelect.value][patternList.children[ind].id] //if(names[packageSelect.value][patternList.children[ind].textContent] == 1){ // delete names[packageSelect.value][patternList.children[ind].textContent] //} @@ -332,6 +463,7 @@ function removePattern(){ /* function used to remove changes made to a scene */ function revertChanges(){ sky.setAttribute('material',{color: '#000000'}) + stopAll() while(entityCanvas.childElementCount != 0){ entityCanvas.removeChild(entityCanvas.children[0]) } @@ -350,11 +482,14 @@ function revertChanges(){ circularDotarrayNum = 0; bullseyeNum = 0; textureNum = 0; + timerNum = 0; + textNum = 0; numAdded = 0; selectedEntity = null; + movementKeyBinds = {} } -names = {'default' : {'red':1,'green':1,'blue':1,'white':1,'grille':1,'crosshair':1,'line':1,'circular dot array':1,'dot array':1,'checkerboard (w)':1,'checkerboard (b)':1,'ring_w5':1,'ring_w10':1,'ring_w20':1,'bullseye':1}} + var colorChange = true; /* handles switches to advanced mode */ @@ -363,9 +498,27 @@ function switchToAdvanced(e){ e.stopPropagation() newVal = !selectedEntity.getAttribute('advanced').val selectedEntity.setAttribute('advanced', {val: newVal}); + mov = selectedEntity.getAttribute('movement') + let i = 0; + while(i < mov.types.length){ + if(newVal){ + if(mov.endPoints[i].r != null){ + mov.endPoints[i] = {x: -mov.endPoints[i].r*Math.sin((mov.endPoints[i].theta*Math.PI)/180), y: mov.endPoints[i].y, z: mov.endPoints[i].r * Math.cos((mov.endPoints[i].theta*Math.PI)/180)} + mov.startPoints[i] = {x: -mov.startPoints[i].r*Math.sin((mov.startPoints[i].theta*Math.PI)/180), y: mov.startPoints[i].y, z: mov.startPoints[i].r * Math.cos((mov.startPoints[i].theta*Math.PI)/180)} + } + } else { + if(mov.endPoints[i].r == null){ + mov.endPoints[i] = {r: Math.sqrt(mov.endPoints[i].x*mov.endPoints[i].x+mov.endPoints[i].z*mov.endPoints[i].z), theta: Math.atan(mov.endPoints[i].z/mov.endPoints[i].x), y: mov.endPoints[i].y} + mov.startPoints[i] = {r: Math.sqrt(mov.startPoints[i].x*mov.startPoints[i].x+mov.startPoints[i].z*mov.startPoints[i].z), theta: Math.atan(mov.startPoints[i].z/mov.startPoints[i].x), y: mov.startPoints[i].y} + } + } + i++; + } + selectedEntity.setAttribute('movement',mov) + endZ.disabled = !endZ.disabled advanced.style.backgroundColor == '' ? advanced.style.backgroundColor = '#00FF00' : advanced.style.backgroundColor ='' updateStats() - editEntity() + //editEntity() } /* listens for entering vr and removes restrictions on clicking through patterns */ @@ -423,7 +576,13 @@ async function highlightSelection(ent){ colNum = ent.children[0].children.length; //tileSizeNum = ent.children[0].children[0].components.geometry.attrValue.width; newGeom = {primitive: 'ring', radiusOuter: ent.children[0].components.geometry.attrValue.radiusOuter*1.5, radiusInner: 0}; - } + } else if(selectedEntity.id.includes("text") || selectedEntity.id.includes("timer")){ + console.log(ent.components.text.attrValue.wrapCount) + let width = ent.components.text.attrValue.value.length * (ent.components.text.attrValue.width / ent.components.text.attrValue.wrapCount); + let height = ent.components.text.attrValue.height; + newGeom = {primitive: 'plane', width: width, height: height}; + } + tmp = document.createElement('a-entity'); tmp.setAttribute('id','tmp') tmp.setAttribute("geometry",newGeom); @@ -461,6 +620,10 @@ function renamePattern(){ alert('No pattern selected') return } + if(patternList.getAttribute('multi-select') == "true"){ + alert('Multiple patterns selected') + return + } let patternName = prompt("Enter a pattern name: ") if(patternName == null){ return @@ -477,7 +640,7 @@ function renamePattern(){ alert('A pattern with this name already exists'); return; } - oldName = patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].textContent + oldName = patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].id currScene = scenes[packageSelect.value][oldName] currName = '' if(Object.keys(names).indexOf(patternName) == -1){ @@ -490,7 +653,13 @@ function renamePattern(){ scenes[packageSelect.value][currName] = currScene delete scenes[packageSelect.value][oldName] - patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].textContent = currName + patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].id = currName + + if(currName.length > 20){ + patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].innerText = currName.substring(0,20)+"..." + } else { + patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].innerText = currName + } } let clipboard; @@ -509,7 +678,7 @@ function copyPattern(){ } clipboard = {} indices.forEach(ind => { - clipboard[patternList.children[ind].textContent] = scenes[packageSelect.value][patternList.children[ind].textContent] + clipboard[patternList.children[ind].id] = scenes[packageSelect.value][patternList.children[ind].id] }) } @@ -598,7 +767,12 @@ function changePackage(){ patternList.removeChild(patternList.children[0]) } Object.keys(scenes[packageSelect.value]).forEach(currName =>{ - var toggle_button = '
  • '+currName+'
  • '; + let textContent = currName; + if(currName.length > 20){ + textContent = currName.substring(0,20)+"..." + } + + var toggle_button = '
  • '+textContent+'
  • '; $('#items-list').append(toggle_button) @@ -646,7 +820,7 @@ function renamePackage(){ delete scenes[packageSelect.value] packageSelect.options[packageSelect.selectedIndex].value = packageName packageSelect.options[packageSelect.selectedIndex].text = packageName - //patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].textContent = currName + //patternList.children[parseInt(patternList.getAttribute('selectedIndex'))].id = currName } function pastePattern(){ @@ -662,11 +836,21 @@ function pastePattern(){ if(names[packageSelect.value][currName]){ currName = currName + ' ('+names[packageSelect.value][currName]+')' names[packageSelect.value][name.split(' (')[0]] = names[packageSelect.value][name.split(' (')[0]] + 1 + } else { names[packageSelect.value][currName] = 1 } + + console.log(currName) + console.log(clipboard[name]) + scenes[packageSelect.value][currName] = clipboard[name] - var toggle_button = '
  • '+currName+'
  • '; + let textContent = currName; + if(currName.length > 20){ + textContent = currName.substring(0,20)+"..." + } + + var toggle_button = '
  • '+textContent+'
  • '; $('#items-list').append(toggle_button) @@ -697,3 +881,41 @@ function cutPattern(){ removePattern() } + +var time; +var timeElapsed = 0; +function startTimer(){ + time = setInterval(() => { + timeElapsed += 10; + let timer = document.getElementById('timer0') + let textVal = timer.getAttribute('text') + let time = Math.floor(timeElapsed) + let minutes = Math.floor(time/1000/60) + time -= minutes*1000*60 + if(minutes < 10){ + minutes = "0"+minutes + } else { + minutes = ""+minutes + } + + let seconds = Math.floor(time/1000) + time -= seconds*1000 + if(seconds < 10){ + seconds = "0"+seconds + } else { + seconds = ""+seconds + } + if(time < 10){ + time = "00"+time + } else if(time < 100){ + time = "0"+time + } else { + time = ""+time + } + //console.log(time) + //textVal.value = minutes+":"+seconds+":"+time + textVal.value = minutes+":"+seconds+":"+time[0]+time[1]+" " + timer.setAttribute('text',textVal) + + },10) +} \ No newline at end of file diff --git a/Custom/validator.js b/Custom/validator.js new file mode 100644 index 0000000..034619b --- /dev/null +++ b/Custom/validator.js @@ -0,0 +1,590 @@ +function validateJSON(file){ + let properties = Object.keys(file); + for(let i = 0; i < properties.length; i++){ + let currProperty = properties[i]; + if(currProperty == 'filename'){ + const re = /^[a-zA-Z0-9-_ ]+$/ + if(!re.test(file[currProperty])){ + // if filename + // check that filename is valid + alert('Package name is invalid.') + return false; + } + + } else if(currProperty == 'date'){ + // if date + if(Number.isNaN(Date.parse(file[currProperty]))){ + // check for valid date + alert('Invalid file date.') + return false; + } + } else if(currProperty == 'scenes'){ + // go through each scene + let currScenes = Object.keys(file[currProperty]); + for(let j = 0; j < currScenes.length; j++){ + if(!validateScene(file[currProperty][currScenes[j]], currScenes[j])){ + return false + } + } + + + + + + // check if entity contents are valid for given type + + } else if(currProperty == 'textures'){ + + } else { + return false; + } + } + return true; +} + + + +function validateScene(scene, name){ + // check valid scene name + const re = /^[a-zA-Z0-9-_ ]+( \([0-9]+\))?$/ // regex to check for a name like test_one-2 (1) + + if(!re.test(name)){ + // failed regex validation indicating the file may have been tampered with + return false; + } + let skyEntCount = 0; // check that sky element is there exactly once + let timerEntCount = 0; // check at most one timer + + + + // for each entity in scene + // check if entity is of a valid type and id + // given type, check valid for valid inputs + + + let colorRe = /^\#[a-fA-F0-9]{6}$/ + + + let properties = Object.keys(scene) + for(let i = 0; i < properties.length; i++) { + + let key = properties[i]; + + // handle adding entity similar to drawing entity + + let skyRe = /^sky$/; + + if(key.includes("sky")){ + skyEntCount++; + if(skyEntCount > 1){ + return false + } + + // for each property, check if it is valid for this entity + let attributes = Object.keys(scene[key]); + + if(attributes.length != 1 || attributes[0] != 'skyColor' || !colorRe.test(scene[key]['skyColor'] || !skyRe.test(key))){ + return false + } + + + } else if(key.includes("circle")){ /* validate circle */ + let attributes = Object.keys(scene[key]); + let circleRe = /^circle[0-9]+$/; + if(attributes.length != 8 || !circleRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('geometry') || !scene[key].hasOwnProperty('fill')){ + return false + } + + let fill = Object.keys(scene[key]['fill']) + if(fill.length != 2 || !scene[key]['fill'].hasOwnProperty('val') || !scene[key]['fill'].hasOwnProperty('isFull') || typeof scene[key]['fill']['val'] != 'number' || typeof scene[key]['fill']['isFull'] != 'boolean'){ + return false + } + + let geom = Object.keys(scene[key]['geometry']) + if(geom.length != 4 || !scene[key]['geometry'].hasOwnProperty('primitive') || !scene[key]['geometry'].hasOwnProperty('radiusOuter') || !scene[key]['geometry'].hasOwnProperty('radiusInner') || !scene[key]['geometry'].hasOwnProperty('segmentsTheta') || scene[key]['geometry']['primitive'] != 'ring' || typeof scene[key]['geometry']['radiusOuter'] != 'number' || typeof scene[key]['geometry']['radiusInner'] != 'number' || typeof scene[key]['geometry']['segmentsTheta'] != 'number'){ + + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + + } else if(key.includes("plane")){ /* validate plane */ + + let attributes = Object.keys(scene[key]); + let planeRe = /^plane[0-9]+$/; + if(attributes.length != 9 || !planeRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('geometry')){ + return false + } else { + let geom = Object.keys(scene[key]['geometry']) + if(geom.length != 3 || !scene[key]['geometry'].hasOwnProperty('primitive') || !scene[key]['geometry'].hasOwnProperty('width') || !scene[key]['geometry'].hasOwnProperty('height') || scene[key]['geometry']['primitive'] != 'plane' || typeof scene[key]['geometry']['width'] != 'number' || typeof scene[key]['geometry']['height'] != 'number'){ + return false + } + } + + if(!scene[key].hasOwnProperty('widthReal') || typeof scene[key]['widthReal'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('fill')){ + return false + } + + let fill = Object.keys(scene[key]['fill']) + if(fill.length != 2 || !scene[key]['fill'].hasOwnProperty('val') || !scene[key]['fill'].hasOwnProperty('isFull') || typeof scene[key]['fill']['val'] != 'number' || typeof scene[key]['fill']['isFull'] != 'boolean'){ + return false + } + + if(!scene[key].hasOwnProperty('material')){ + return false + } else { + let mat = Object.keys(scene[key]['material']) + if(mat.length == 3){ + if(!scene[key]['material'].hasOwnProperty('shader') || !scene[key]['material'].hasOwnProperty('color') || !scene[key]['material'].hasOwnProperty('src') || scene[key]['material']['shader'] != 'flat' || !colorRe.test(scene[key]['material']['color']) || typeof scene[key]['material']['src'] != 'string'){ + console.log(scene[key]['material']) + return false + } + } + + } + + if(!validateUniversal(scene, key, attributes, true)){ + return false + } + + } else if(key.includes("triangle")){ /* validate triangle */ + let attributes = Object.keys(scene[key]); + let triangleRe = /^triangle[0-9]+$/; + if(attributes.length != 7 || !triangleRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('geometry')){ + return false + } + + let geom = Object.keys(scene[key]['geometry']) + if(geom.length != 4 || !scene[key]['geometry'].hasOwnProperty('primitive') || !scene[key]['geometry'].hasOwnProperty('vertexA') || !scene[key]['geometry'].hasOwnProperty('vertexB') || !scene[key]['geometry'].hasOwnProperty('vertexC') || scene[key]['geometry']['primitive'] != 'triangle' || typeof scene[key]['geometry']['vertexA'] != 'object' || typeof scene[key]['geometry']['vertexB'] != 'object' || typeof scene[key]['geometry']['vertexC'] != 'object'){ + return false + } else { + + let vA = scene[key]['geometry']['vertexA']; + if(Object.keys(vA).length != 3 || !vA.hasOwnProperty('x') || !vA.hasOwnProperty('y') || !vA.hasOwnProperty('z') || typeof vA.x != 'number' || typeof vA.y != 'number' || typeof vA.z != 'number'){ + return false + } + + let vB = scene[key]['geometry']['vertexB']; + if(Object.keys(vB).length != 3 || !vB.hasOwnProperty('x') || !vB.hasOwnProperty('y') || !vB.hasOwnProperty('z') || typeof vB.x != 'number' || typeof vB.y != 'number' || typeof vB.z != 'number'){ + return false + } + + let vC = scene[key]['geometry']['vertexC']; + if(Object.keys(vC).length != 3 || !vC.hasOwnProperty('x') || !vC.hasOwnProperty('y') || !vC.hasOwnProperty('z') || typeof vC.x != 'number' || typeof vC.y != 'number' || typeof vC.z != 'number'){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + } + + + + } else if (key.includes("gradient") || key.includes("grille")){ + // "gradient0": { + //"advanced": {"val": false}, + // "angle": {"x": 21.952849732450886, "z": -250}, + // "numBars": 32, + // "color2": {"val": "#000000"}, + // "childGeometry": {"primitive": "plane", "width": 6.25, "height": 18.75}, + // "position": {"x": -93.4608654121603, "y": 6.252609149761575, "z": -231.8729536543882}, + // "material": {"shader": "flat", "color": "#3EE43F"}, + // "rotation": {"x": 0, "y": 21.952849732450886, "z": 0}, + // "movement": {"startPoints": [], "endPoints": [], "initialVelocities": [], "accelerations": [], "types": [], "origin": {"x": -93.4608654121603, "y": 6.252609149761575, "z": -231.8729536543882}, "rotationOrigin": {"x": 0, "y": 21.952849732450886, "z": 0}, "status": -1, "index": 0, "currentVelocity": 0, "timeElapsed": 0}} + + + let attributes = Object.keys(scene[key]); + if(key.includes("gradient")){ + + let gradientRe = /^gradient[0-9]+$/; + if(attributes.length != 9 || !gradientRe.test(key)){ + return false + } + } else { + let grilleRe = /^grille[0-9]+$/; + if(attributes.length != 9 || !grilleRe.test(key)){ + return false + } + } + + + + if(!scene[key].hasOwnProperty('childGeometry')){ + return false + } + + let geom = Object.keys(scene[key]['childGeometry']) + if(geom.length != 3 || !scene[key]['childGeometry'].hasOwnProperty('primitive') || !scene[key]['childGeometry'].hasOwnProperty('width') || !scene[key]['childGeometry'].hasOwnProperty('height') || scene[key]['childGeometry']['primitive'] != 'plane' || typeof scene[key]['childGeometry']['width'] != 'number' || typeof scene[key]['childGeometry']['height'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('numBars') || typeof scene[key]['numBars'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('color2') || Object.keys(scene[key]['color2']).length != 1 || !scene[key]['color2'].hasOwnProperty('val') || typeof scene[key]['color2']['val'] != 'string' || !colorRe.test(scene[key]['color2']['val'])){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + } else if (key.includes("checkerboard")){ + // "checkerboard0": { + //"advanced": {"val": false}, + // "angle": {"x": -30.60631205347506, "z": -250}, + // "rows": 16, + // "cols": 16, + // "tileSize": 5, + // "color2": {"val": "#000000"}, + // "position": {"x": 127.28405931672665, "y": -1.9060721175742223, "z": -215.17148566633082}, + // "material": {"shader": "flat", "color": "#058551"}, + // "rotation": {"x": 0, "y": -30.60631205347506, "z": 0}, + // "movement": {"startPoints": [], "endPoints": [], "initialVelocities": [], "accelerations": [], "types": [], "origin": {"x": 127.28405931672665, "y": -1.9060721175742223, "z": -215.17148566633082}, "rotationOrigin": {"x": 0, "y": -30.60631205347506, "z": 0}, "status": -1, "index": 0, "currentVelocity": 0, "timeElapsed": 0}} + + let attributes = Object.keys(scene[key]); + let checkerboardRe = /^checkerboard[0-9]+$/; + if(attributes.length != 10 || !checkerboardRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('rows') || typeof scene[key]['rows'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('cols') || typeof scene[key]['cols'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('tileSize') || typeof scene[key]['tileSize'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('color2') || Object.keys(scene[key]['color2']).length != 1 || !scene[key]['color2'].hasOwnProperty('val') || typeof scene[key]['color2']['val'] != 'string' || !colorRe.test(scene[key]['color2']['val'])){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + } else if (key.includes("circularDotarray")){ + let attributes = Object.keys(scene[key]); + let circularDotArrayRe = /^circularDotarray[0-9]+$/; + if(attributes.length != 11 || !circularDotArrayRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('circles') || typeof scene[key]['circles'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('dots') || typeof scene[key]['dots'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('circleSize') || typeof scene[key]['circleSize'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('toggleCenterDot') || Object.keys(scene[key]['toggleCenterDot']).length != 1 || !scene[key]['toggleCenterDot'].hasOwnProperty('val') || typeof scene[key]['toggleCenterDot']['val'] != 'boolean'){ + return false + } + + if(!scene[key].hasOwnProperty('arraySpacing') || Object.keys(scene[key]['arraySpacing']).length != 1 || !scene[key]['arraySpacing'].hasOwnProperty('val') || typeof scene[key]['arraySpacing']['val'] != 'number'){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + + } else if (key.includes("dotarray")){ + let attributes = Object.keys(scene[key]); + let dotArrayRe = /^dotarray[0-9]+$/; + if(attributes.length != 11 || !dotArrayRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('rows') || typeof scene[key]['rows'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('cols') || typeof scene[key]['cols'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('circleSize') || typeof scene[key]['circleSize'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('toggleCenterDot') || Object.keys(scene[key]['toggleCenterDot']).length != 1 || !scene[key]['toggleCenterDot'].hasOwnProperty('val') || typeof scene[key]['toggleCenterDot']['val'] != 'boolean'){ + return false + } + + if(!scene[key].hasOwnProperty('spacing') || Object.keys(scene[key]['spacing']).length != 1 || !scene[key]['spacing'].hasOwnProperty('val') || typeof scene[key]['spacing']['val'] != 'number'){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + } else if (key.includes("bullseye")){ + let attributes = Object.keys(scene[key]); + let bullseyeRe = /^bullseye[0-9]+$/; + if(attributes.length != 8 || !bullseyeRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('numRings') || typeof scene[key]['numRings'] != 'number'){ + return false + } + + if(!scene[key].hasOwnProperty('ringPitch') || typeof scene[key]['ringPitch'] != 'number'){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + } else if (key.includes("text")){ + + let attributes = Object.keys(scene[key]); + let textRe = /^text[0-9]+$/; + if(attributes.length != 6 || !textRe.test(key)){ + return false + } + + if(!scene[key].hasOwnProperty('text') || Object.keys(scene[key]['text']).length != 6 || !scene[key]['text'].hasOwnProperty('value') || !scene[key]['text'].hasOwnProperty('color') || !scene[key]['text'].hasOwnProperty('width') || !scene[key]['text'].hasOwnProperty('height') || !scene[key]['text'].hasOwnProperty('align') || !scene[key]['text'].hasOwnProperty('wrapCount') + || typeof scene[key]['text']['value'] != 'string' || !colorRe.test(scene[key]['text']['color']) || typeof scene[key]['text']['width'] != 'number' || typeof scene[key]['text']['height'] != 'number' || scene[key]['text']['align'] != 'center' || typeof scene[key]['text']['wrapCount'] != 'number' + ){ + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + } else if (key.includes("timer")){ + timerEntCount++; + if(timerEntCount > 1){ + return false + } + + + // "timer0": { + // "advanced": {"val": false}, + // "angle": {"x": 49.326992963674456, "z": -250}, + // "text": {"value": "00:00.00 ", "color": "#FFFFFF", "width": 62.5, "height": 31.25, "align": "center", "wrapCount": 9, + // "alphaTest": 0.5, "anchor": "center", "baseline": "center", "font": "roboto", "fontImage": "", + // "letterSpacing": 0, "lineHeight": 0, "negate": true, "opacity": 1, "shader": "sdf", "side": "front", "tabSize": 4, + // "transparent": true, "whiteSpace": "normal", "wrapPixels": 0, "xOffset": 0, "yOffset": 0, "zOffset": 0.001}, + // "position": {"x": -189.6103665257861, "y": -9.42625287910497, "z": -162.93529054798734}, + // "rotation": {"x": 0, "y": 49.326992963674456, "z": 0}, + // "movement": {"startPoints": [], "endPoints": [], "initialVelocities": [], "accelerations": [], "types": [], "origin": {"x": -189.6103665257861, "y": -9.42625287910497, "z": -162.93529054798734}, "rotationOrigin": {"x": 0, "y": 49.326992963674456, "z": 0}, "status": -1, "index": 0, "currentVelocity": 0, "timeElapsed": 0}} + + + let attributes = Object.keys(scene[key]); + let timerRe = /^timer[0-9]+$/; + if(attributes.length != 6 || !timerRe.test(key)){ + console.log('test1') + return false + } + + if(!scene[key].hasOwnProperty('text') || Object.keys(scene[key]['text']).length != 24 + || !scene[key]['text'].hasOwnProperty('value') || !scene[key]['text'].hasOwnProperty('color') || !scene[key]['text'].hasOwnProperty('width') || !scene[key]['text'].hasOwnProperty('height') || !scene[key]['text'].hasOwnProperty('align') || !scene[key]['text'].hasOwnProperty('wrapCount') + || !scene[key]['text'].hasOwnProperty('alphaTest') || !scene[key]['text'].hasOwnProperty('anchor') || !scene[key]['text'].hasOwnProperty('baseline') || !scene[key]['text'].hasOwnProperty('font') || !scene[key]['text'].hasOwnProperty('fontImage') || !scene[key]['text'].hasOwnProperty('letterSpacing') + || !scene[key]['text'].hasOwnProperty('lineHeight') || !scene[key]['text'].hasOwnProperty('negate') || !scene[key]['text'].hasOwnProperty('opacity') || !scene[key]['text'].hasOwnProperty('shader') || !scene[key]['text'].hasOwnProperty('side') || !scene[key]['text'].hasOwnProperty('tabSize') + || typeof scene[key]['text']['value'] != 'string' || !colorRe.test(scene[key]['text']['color']) || typeof scene[key]['text']['width'] != 'number' || typeof scene[key]['text']['height'] != 'number' || scene[key]['text']['align'] != 'center' || typeof scene[key]['text']['wrapCount'] != 'number' + || scene[key]['text']['alphaTest'] != 0.5 || scene[key]['text']['anchor'] != 'center' || scene[key]['text']['baseline'] != 'center' || scene[key]['text']['font'] != 'roboto' || scene[key]['text']['fontImage'] != '' || scene[key]['text']['letterSpacing'] != 0 + || scene[key]['text']['lineHeight'] != 0 || scene[key]['text']['negate'] != true || scene[key]['text']['opacity'] != 1 || scene[key]['text']['shader'] != 'sdf' || scene[key]['text']['side'] != 'front' || scene[key]['text']['tabSize'] != 4 + || scene[key]['text']['transparent'] != true || scene[key]['text']['whiteSpace'] != 'normal' || scene[key]['text']['wrapPixels'] != 0 || scene[key]['text']['xOffset'] != 0 || scene[key]['text']['yOffset'] != 0 || scene[key]['text']['zOffset'] != 0.001 + ){ + console.log('test2') + return false + } + + if(!validateUniversal(scene, key, attributes)){ + return false + } + + + + } else { + return false; + } + } + + + + + + return true; +} + + + + +function validateUniversal(scene, key, attributes, skipMat){ + + let validationDict = {"advanced": false, "angle": false, "geometry": false, "fill": false, "position": false, "material": false, "rotation": false, "movement": false} + let colorRe = /^\#[a-fA-F0-9]{6}$/ + for(let j = 0; j < attributes.length; j++) { + let attr = attributes[j]; + + if(attr == "advanced"){ + let advanced = Object.keys(scene[key][attr]) + if(advanced.length != 1 || !scene[key][attr].hasOwnProperty('val') || typeof scene[key][attr]['val'] != 'boolean'){ + console.log('test1') + return false + } + } else if(attr == "angle"){ + let angle = Object.keys(scene[key][attr]) + if(angle.length != 2 || !scene[key][attr].hasOwnProperty('x') || !scene[key][attr].hasOwnProperty('z') || typeof scene[key][attr]['x'] != 'number' || typeof scene[key][attr]['z'] != 'number'){ + console.log('test2') + return false + } + } else if(attr == "position"){ + let pos = Object.keys(scene[key][attr]) + if(pos.length != 3 || !scene[key][attr].hasOwnProperty('x') || !scene[key][attr].hasOwnProperty('y') || !scene[key][attr].hasOwnProperty('z') || typeof scene[key][attr]['x'] != 'number' || typeof scene[key][attr]['y'] != 'number' || typeof scene[key][attr]['z'] != 'number'){ + console.log('test4') + return false + } + + } else if(attr == "material"){ + if(skipMat){ + continue; + } + let mat = Object.keys(scene[key][attr]) + if(mat.length != 2 || !scene[key][attr].hasOwnProperty('shader') || !scene[key][attr].hasOwnProperty('color') || scene[key][attr]['shader'] != 'flat' || !colorRe.test(scene[key][attr]['color'])){ + console.log(scene[key]) + console.log('test5') + return false + } + } else if(attr == "rotation"){ + let rot = Object.keys(scene[key][attr]) + if(rot.length != 3 || !scene[key][attr].hasOwnProperty('x') || !scene[key][attr].hasOwnProperty('y') || !scene[key][attr].hasOwnProperty('z') || typeof scene[key][attr]['x'] != 'number' || typeof scene[key][attr]['y'] != 'number' || typeof scene[key][attr]['z'] != 'number'){ + console.log('test6') + return false + } + } else if(attr == "movement"){ + let mov = Object.keys(scene[key][attr]) + if(mov.length != 11 || !scene[key][attr].hasOwnProperty('startPoints') || !scene[key][attr].hasOwnProperty('endPoints') || !scene[key][attr].hasOwnProperty('initialVelocities') || !scene[key][attr].hasOwnProperty('accelerations') || !scene[key][attr].hasOwnProperty('types') || !scene[key][attr].hasOwnProperty('origin') || !scene[key][attr].hasOwnProperty('rotationOrigin') || !scene[key][attr].hasOwnProperty('status') || !scene[key][attr].hasOwnProperty('index') || !scene[key][attr].hasOwnProperty('currentVelocity') || !scene[key][attr].hasOwnProperty('timeElapsed') + || !(scene[key][attr]['startPoints'].length == scene[key][attr]['endPoints'].length && scene[key][attr]['initialVelocities'].length == scene[key][attr]['accelerations'].length && scene[key][attr]['types'].length == scene[key][attr]['startPoints'].length && scene[key][attr]['startPoints'].length == scene[key][attr]['accelerations'].length + || typeof scene[key][attr]['status'] != 'number' || scene[key][attr]['status'] != -1 + || typeof scene[key][attr]['origin'] != 'object' + || typeof scene[key][attr]['rotationOrigin'] != 'object' + || typeof scene[key][attr]['index'] != 'number' || scene[key][attr]['index'] != 0 + || typeof scene[key][attr]['currentVelocity'] != 'number' || scene[key][attr]['currentVelocity'] != 0 + || typeof scene[key][attr]['timeElapsed'] != 'number' || scene[key][attr]['timeElapsed'] != 0 + )){ + console.log(scene[key]) + + + + + console.log('test7') + return false; + + } else { + // need to validate each object stored in movement + + for(let k = 0; k < scene[key][attr]['startPoints'].length; k++){ + if(scene[key][attr]['startPoints'][k].hasOwnProperty('x') && scene[key][attr]['startPoints'][k].hasOwnProperty('y') && scene[key][attr]['startPoints'][k].hasOwnProperty('z')){ + if(typeof scene[key][attr]['startPoints'][k].x != 'number' && typeof scene[key][attr]['startPoints'][k].y != 'number' && typeof scene[key][attr]['startPoints'][k].z != 'number'){ + console.log('test8') + return false; + } + } else if(scene[key][attr]['startPoints'][k].hasOwnProperty('r') && scene[key][attr]['startPoints'][k].hasOwnProperty('y') && scene[key][attr]['startPoints'][k].hasOwnProperty('theta')){ + if(typeof scene[key][attr]['startPoints'][k].r != 'number' && typeof scene[key][attr]['startPoints'][k].theta != 'number' && typeof scene[key][attr]['startPoints'][k].y != 'number'){ + console.log('test9') + return false + } + } else { + console.log('test10') + return false; + } + } + + + for(let k = 0; k < scene[key][attr]['endPoints'].length; k++){ + if(scene[key][attr]['endPoints'][k].hasOwnProperty('x') && scene[key][attr]['endPoints'][k].hasOwnProperty('y') && scene[key][attr]['endPoints'][k].hasOwnProperty('z')){ + if(typeof scene[key][attr]['endPoints'][k].x != 'number' && typeof scene[key][attr]['endPoints'][k].y != 'number' && typeof scene[key][attr]['endPoints'][k].z != 'number'){ + console.log('test11') + return false; + } + } else if(scene[key][attr]['endPoints'][k].hasOwnProperty('r') && scene[key][attr]['endPoints'][k].hasOwnProperty('y') && scene[key][attr]['endPoints'][k].hasOwnProperty('theta')){ + if(typeof scene[key][attr]['endPoints'][k].r != 'number' && typeof scene[key][attr]['endPoints'][k].theta != 'number' && typeof scene[key][attr]['endPoints'][k].y != 'number'){ + console.log('test12') + return false + } + } else { + console.log('test13') + return false; + } + } + + + for(let k = 0; k < scene[key][attr]['initialVelocities'].length; k++){ + if(typeof scene[key][attr]['initialVelocities'][k] != 'number'){ + console.log('test14') + return false + } + } + + for(let k = 0; k < scene[key][attr]['accelerations'].length; k++){ + if(typeof scene[key][attr]['accelerations'][k] != 'number'){ + console.log('test15') + return false + } + } + + for(let k = 0; k < scene[key][attr]['types'].length; k++){ + if(typeof scene[key][attr]['types'][k] != 'string' || (scene[key][attr]['types'][k] != 'Discontinous' && scene[key][attr]['types'][k] != 'Pause' && scene[key][attr]['types'][k] != 'Start' && scene[key][attr]['types'][k] != 'Rubberband' && scene[key][attr]['types'][k] != 'Rebound')){ + console.log('test16') + return false + } + } + + } + } else if(attr == 'geometry' || attr == 'widthReal' || attr == 'fill' || attr == 'childGeometry' ||attr == 'numBars' || attr == 'color2' || attr == 'rows' || attr == 'cols' || attr == 'tileSize' || attr == 'circles' || attr == 'dots' || attr == 'circleSize' || attr == 'arraySpacing' || attr == 'toggleCenterDot' || attr == 'spacing' || attr == 'numRings' || attr == 'ringPitch' || attr == 'text') { + continue; + } else { + console.log(attr) + console.log('test17') + return false; + } + + } + return true; +}