diff --git a/index.html b/index.html index da6d15622..e5f54abed 100644 --- a/index.html +++ b/index.html @@ -88,7 +88,7 @@ - + @@ -137,7 +137,7 @@ sceneEl.components.inspector.openInspector(); document.querySelector('.viewer-header-wrapper').style.display = 'none'; } - + AFRAME.registerComponent('timed-inspector', { init: function() { setTimeout( function () { diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index 39ab67d69..36d7423e0 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -196,6 +196,7 @@ function getZPositions (start, end, step) { function createSidewalkClonedVariants (segmentWidthInMeters, density, elevationPosY = 0, streetLength, direction = 'random', animated = false) { const xValueRange = [-(0.37 * segmentWidthInMeters), (0.37 * segmentWidthInMeters)]; const zValueRange = getZPositions((-0.5 * streetLength), (0.5 * streetLength), 1.5); + const densityFactors = { empty: 0, sparse: 0.03, @@ -207,7 +208,7 @@ function createSidewalkClonedVariants (segmentWidthInMeters, density, elevationP dividerParentEl.setAttribute('position', {y: elevationPosY}); // Randomly generate avatars for (let i = 0; i < totalPedestrianNumber; i++) { - const variantName = (animated === true) ? 'a_char' + String(getRandomIntInclusive(1, 8)) : 'char' + String(getRandomIntInclusive(1, 16)); + const variantName = 'a_char' + String(getRandomIntInclusive(1, 8)); const xVal = getRandomArbitrary(xValueRange[0], xValueRange[1]); const zVal = zValueRange.pop(); const yVal = 0; @@ -215,6 +216,7 @@ function createSidewalkClonedVariants (segmentWidthInMeters, density, elevationP const placedObjectEl = document.createElement('a-entity'); let animationDirection = 'inbound'; placedObjectEl.setAttribute('mixin', variantName); + placedObjectEl.setAttribute('position', { x: xVal, y: yVal, z: zVal }); // Roughly 50% of traffic will be incoming if (Math.random() < 0.5 && direction === 'random') { placedObjectEl.setAttribute('rotation', '0 180 0'); @@ -223,8 +225,14 @@ function createSidewalkClonedVariants (segmentWidthInMeters, density, elevationP placedObjectEl.setAttribute('rotation', '0 0 0'); } - if (animated) { - addLinearStreetAnimation(placedObjectEl, 1.4, streetLength, xVal, yVal, zVal, animationDirection); + if (animated) { + placedObjectEl.setAttribute('automation-element', { + zPos: zVal, + direction: animationDirection, + speed: 1.4, + streetLength: streetLength, + mixer: true + }); } dividerParentEl.append(placedObjectEl); } @@ -314,37 +322,6 @@ function createBusElement (variantList, length, showVehicles) { return busParentEl; } -function addLinearStreetAnimation (reusableObjectEl, speed, streetLength, xPos, yVal = 0, zPos, direction) { - const totalStreetDuration = (streetLength / speed) * 1000; // time in milliseconds - const halfStreet = (direction === 'outbound') - ? -streetLength / 2 - : streetLength / 2; - const startingDistanceToTravel = Math.abs(halfStreet - zPos); - const startingDuration = (startingDistanceToTravel / speed) * 1000; - - const animationAttrs_1 = { - property: 'position', - easing: 'linear', - loop: 'false', - from: { x: xPos, y: yVal, z: zPos }, - to: { z: halfStreet }, - dur: startingDuration - }; - const animationAttrs_2 = { - property: 'position', - easing: 'linear', - loop: 'true', - from: { x: xPos, y: yVal, z: -halfStreet }, - to: { x: xPos, y: yVal, z: halfStreet }, - delay: startingDuration, - dur: totalStreetDuration - }; - reusableObjectEl.setAttribute('animation__1', animationAttrs_1); - reusableObjectEl.setAttribute('animation__2', animationAttrs_2); - - return reusableObjectEl; -} - function createDriveLaneElement (variantList, segmentWidthInMeters, streetLength, animated = false, showVehicles = true, count = 1, carStep = undefined) { if (!showVehicles) { return; @@ -374,11 +351,7 @@ function createDriveLaneElement (variantList, segmentWidthInMeters, streetLength } else { rotationY = rotationVariants[lineVariant]; } -/* - if (carType === 'pedestrian') { - return createSidewalkClonedVariants(segmentWidthInMeters, 'normal', streetLength, lineVariant, animated); - } -*/ + const driveLaneParentEl = document.createElement('a-entity'); if (variantList.length == 1) { @@ -431,7 +404,12 @@ function createDriveLaneElement (variantList, segmentWidthInMeters, streetLength reusableObjectEl.setAttribute('wheel', { speed: speed, wheelDiameter: params['wheelDiameter'] } ); - addLinearStreetAnimation(reusableObjectEl, speed, streetLength, 0, 0, positionZ, direction); + reusableObjectEl.setAttribute('automation-element', { + zPos: positionZ, + direction: direction, + speed: speed, + streetLength: streetLength + }); } driveLaneParentEl.append(reusableObjectEl); return reusableObjectEl; diff --git a/src/components/automation.js b/src/components/automation.js new file mode 100644 index 000000000..ad1e1dfd4 --- /dev/null +++ b/src/components/automation.js @@ -0,0 +1,79 @@ +/* global AFRAME */ + +/* +The animation-element component controls all animation of the elements +*/ +AFRAME.registerComponent('automation-element', { + schema: { + // initial z position of element + zPos: { type: 'number', default: 0 }, + direction: { type: 'string', default: 'outbound', oneOf: ['outbound', 'inbound'] }, + enabled: { type: 'boolean', default: true }, + speed: { type: 'number', default: 1000 }, + streetLength: { type: 'number', default: 60 } + }, + init: function () { + const el = this.el; + this.addLinearAnimation(); + }, + addLinearAnimation: function () { + const el = this.el; + const streetLength = this.data.streetLength; + const speed = this.data.speed; + const direction = this.data.direction; + const zPos = el.object3D.position.z; + + const totalStreetDuration = (streetLength / speed) * 1000; // time in milliseconds + + if (direction === 'outbound') { + halfStreet = -streetLength / 2; + el.setAttribute('rotation', {y: 180}); + } else { + halfStreet = streetLength / 2; + el.setAttribute('rotation', {y: 0}); + } + const startingDistanceToTravel = Math.abs(halfStreet - zPos); + const startingDuration = (startingDistanceToTravel / speed) * 1000; + + // animation params to move an object from its current position to the end of street + // in a specified direction + const animationAttrs_1 = { + property: 'object3D.position.z', + easing: 'linear', + loop: 'false', + from: zPos, + to: halfStreet, + dur: startingDuration + }; + // Animation parameters for the next animation cycle. + // They can be changed when changing position of the object in the editor + const animationAttrs_2 = { + property: 'object3D.position.z', + autoplay: false, + easing: 'linear', + loop: 'true', + from: -halfStreet, + to: halfStreet, + dur: totalStreetDuration, + startEvents: 'animationcomplete__1' + //startEvents: 'startAnim2' + }; + el.setAttribute('animation__1', animationAttrs_1); + el.setAttribute('animation__2', animationAttrs_2); + }, + animationCompleteEvent: function (evt) { + const elem = evt.target; + //this.el.parentEl.emit('addInBuffer', {uuid: elem.uuid}); + }, + update: function (oldData) { + // If `oldData` is empty, then this means we're in the initialization process. + // No need to update. + if (Object.keys(oldData).length === 0) { return; } + + const changedData = AFRAME.utils.diff(this.data, oldData); + + if (Object.keys(changedData).length > 0) { + this.addLinearAnimation(); + } + } +}); diff --git a/src/index.js b/src/index.js index cabcee910..e270c02bd 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,7 @@ require('./assets.js'); require('./components/notify.js'); require('./components/create-from-json'); require('./components/screentock.js'); +require('./components/automation.js'); require('aframe-atlas-uvs-component'); AFRAME.registerComponent('street', {