Skip to content

Commit

Permalink
Merge pull request #965 from 3DStreet/load-managed-street-from-json
Browse files Browse the repository at this point in the history
load from managed street object
  • Loading branch information
kfarr authored Dec 24, 2024
2 parents 4cde5ab + cee039a commit a358304
Show file tree
Hide file tree
Showing 8 changed files with 480 additions and 38 deletions.
5 changes: 5 additions & 0 deletions src/DEV-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

These is a place to save random notes like code snippets, links to assets, and other references. This doc might not be useful to anyone else :)

### Example managed street load from hash
```
localhost:3333#managed-street-json:{"id":"aaaaaaaa-0123-4678-9000-000000000000","name":"Kieran's Awesome Street","width":40,"length":100,"justifyWidth":"center","justifyLength":"start","segments":[{"id":"aaaaaaaa-0123-4678-9000-000000000001","name":"Sidewalk for walking","type":"sidewalk","surface":"sidewalk","color":"#ffffff","level":1,"width":3,"direction":"none","generated":{"pedestrians":[{"density":"normal"}]}},{"id":"aaaaaaaa-0123-4678-9000-000000000002","name":"Sidewalk for trees and stuff","type":"sidewalk","surface":"sidewalk","color":"#ffffff","level":1,"width":1,"direction":"none","generated":{"clones":[{"mode":"fixed","model":"tree3","spacing":15}]}},{"id":"aaaaaaaa-0123-4678-9000-000000000003","name":"Parking for cars","type":"parking-lane","surface":"concrete","color":"#dddddd","level":0,"width":3,"direction":"inbound","generated":{"clones":[{"mode":"random","modelsArray":"sedan-rig, self-driving-waymo-car, suv-rig","spacing":6,"count":6}],"stencil":[{"model":"parking-t","cycleOffset":1,"spacing":6}]}},{"id":"aaaaaaaa-0123-4678-9000-000000000004","name":"Drive Lane for cars and stuff","type":"drive-lane","color":"#ffffff","surface":"asphalt","level":0,"width":3,"direction":"inbound","generated":{"clones":[{"mode":"random","modelsArray":"sedan-rig, box-truck-rig, self-driving-waymo-car, suv-rig, motorbike","spacing":7.3,"count":4}]}},{"id":"aaaaaaaa-0123-4678-9000-000000000005","name":"A beautiful median","type":"divider","surface":"sidewalk","color":"#ffffff","level":1,"width":0.5}]}
```

### Audio Notes
```
var entity = document.querySelector('.playme');
Expand Down
12 changes: 12 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,17 @@ I learned a few things:
* This UUID is not shown in the UI. It can be found by going to this URL and supplying the nameSpacedId and creatorId, such as: https://streetmix.net/api/v1/streets?namespacedId=3&creatorId=kfarr . This will redirect to the UUID API endpoint
* I wrote a quick JS helper function that takes a user facing URL on Streetmix (such as https://streetmix.net/kfarr/3/a-frame-city-builder-street-only) and transforms it into the API Redirect to find the UUID endpoint. You can find the [helper function docs here](https://github.com/kfarr/3dstreet/tree/master/src#streetmix-utilsjs).

# Possibly Accepted URL Input hash schemes

3DStreet can import third-party street data in a variety of formats. The following URL input hash schemes are experimental and not guaranteed to be supported in future versions:

| Scheme | Description | Usage Example |
| --------- | -- |-- |
| `streetmix-url` | Streetmix User-Facing Street URL | `https://3dstreet.app/#https://streetmix.net/kfarr/3/3dstreet-demo-street` |
| `streetplan-url` | StreetPlan API URL | `https://3dstreet.app/#https://streetplan.net/3dstreet/89241` |
| `managed-street-json` | Managed Street JSON Blob | `https://3dstreet.app/#managed-street-json:{"data":"value"}` |
| `cloud-uuid-legacy` | 3DStreet Scene JSON Format from Cloud UUID with .json Extension | `https://3dstreet.app/#scenes/bc72ab26-891d-417b-a50f-0cf84621a54c.json` |
| `cloud-uuid` | 3DStreet Scene JSON Format from Cloud UUID | `https://3dstreet.app/#scenes/bc72ab26-891d-417b-a50f-0cf84621a54c` |

### More Notes
See [DEV-NOTES](DEV-NOTES.md) for additional notes on future features and work in progress.
60 changes: 51 additions & 9 deletions src/components/managed-street.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ const { segmentVariants } = require('../segments-variants.js');
const streetmixUtils = require('../tested/streetmix-utils');
const streetmixParsersTested = require('../tested/aframe-streetmix-parsers-tested');

// invoking from js console
/*
userLayersEl = document.getElementById('street-container');
newStreetEl = document.createElement('a-entity');
newStreetEl.setAttribute('managed-street', 'sourceType: streetmix-url; sourceValue: https://streetmix.net/kfarr/3/; synchronize: true');
userLayersEl.append(newStreetEl);
*/

AFRAME.registerComponent('managed-street', {
schema: {
width: {
Expand Down Expand Up @@ -98,9 +90,18 @@ AFRAME.registerComponent('managed-street', {
if (data.sourceType === 'streetmix-url') {
this.loadAndParseStreetmixURL(data.sourceValue);
} else if (data.sourceType === 'streetplan-url') {
// this function is not yet implemented
this.refreshFromStreetplanURL(data.sourceValue);
} else if (data.sourceType === 'json-blob') {
this.refreshFromJSONBlob(data.sourceValue);
// if data.sourceValue is a string convert string to object for parsing but keep string for saving
if (typeof data.sourceValue === 'string') {
const streetObjectFromBlob = JSON.parse(data.sourceValue);
this.parseStreetObject(streetObjectFromBlob);
} else {
console.log(
'[managed-street]: ERROR parsing json-blob, sourceValue must be a string'
);
}
}
},
applyLength: function () {
Expand Down Expand Up @@ -174,6 +175,8 @@ AFRAME.registerComponent('managed-street', {
this.justifiedDirtBox = dirtBox;
dirtBox.setAttribute('material', `color: ${window.STREET.colors.brown};`);
dirtBox.setAttribute('data-layer-name', 'Underground');
dirtBox.setAttribute('data-no-transform', '');
dirtBox.setAttribute('data-ignore-raycaster', '');
}
this.justifiedDirtBox.setAttribute('height', 2); // height is 2 meters from y of -0.1 to -y of 2.1
this.justifiedDirtBox.setAttribute('width', streetWidth);
Expand Down Expand Up @@ -202,6 +205,42 @@ AFRAME.registerComponent('managed-street', {
`${xPosition} -1 ${zPosition}`
);
},
parseStreetObject: function (streetObject) {
// reset and delete all existing entities
this.remove();

// given an object streetObject, create child entities with 'street-segment' component
this.el.setAttribute(
'data-layer-name',
'Managed Street • ' + streetObject.name
);
this.el.setAttribute('managed-street', 'width', streetObject.width);
this.el.setAttribute('managed-street', 'length', streetObject.length);

for (let i = 0; i < streetObject.segments.length; i++) {
const segment = streetObject.segments[i];
const segmentEl = document.createElement('a-entity');
this.el.appendChild(segmentEl);

segmentEl.setAttribute('street-segment', {
type: segment.type, // this is the base type, it won't load its defaults since we are changing more than just the type value
width: segment.width,
length: streetObject.length,
level: segment.level,
direction: segment.direction,
color: segment.color || window.STREET.types[segment.type]?.color,
surface: segment.surface || window.STREET.types[segment.type]?.surface // no error handling for segmentPreset not found
});
segmentEl.setAttribute('data-layer-name', segment.name);
// wait for street-segment to be loaded, then generate components from segment object
segmentEl.addEventListener('loaded', () => {
segmentEl.components[
'street-segment'
].generateComponentsFromSegmentObject(segment);
this.applyJustification();
});
}
},
loadAndParseStreetmixURL: async function (streetmixURL) {
const data = this.data;
const streetmixAPIURL = streetmixUtils.streetmixUserToAPI(streetmixURL);
Expand Down Expand Up @@ -265,6 +304,7 @@ AFRAME.registerComponent('managed-street', {

// When all entities are loaded, do something with them
this.allLoadedPromise.then(() => {
this.refreshManagedEntities();
this.applyJustification();
this.createOrUpdateJustifiedDirtBox();
AFRAME.INSPECTOR.selectEntity(this.el);
Expand Down Expand Up @@ -293,6 +333,8 @@ AFRAME.registerComponent('managed-street', {
}
});

// Helper functions for Streetmix to A-Frame conversion

function getSeparatorMixinId(previousSegment, currentSegment) {
if (previousSegment === undefined || currentSegment === undefined) {
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { loadScript, roundCoord } from '../../../../../src/utils.js';
import { createUniqueId } from '../../../lib/entity.js';
import * as defaultStreetObjects from './defaultStreets.js';

export function createSvgExtrudedEntity(position) {
// This component accepts a svgString and creates a new entity with geometry extruded
Expand Down Expand Up @@ -50,7 +51,7 @@ export function createMapbox() {
});
}

export function createManagedStreet(position) {
export function createManagedStreetFromStreetmixURLPrompt(position) {
// This creates a new Managed Street
let streetmixURL = prompt(
'Please enter a Streetmix URL',
Expand All @@ -76,7 +77,29 @@ export function createManagedStreet(position) {
}
}

export function createManagedStreetFromStreetObject(position, streetObject) {
// This creates a new Managed Street
if (streetObject && streetObject !== '') {
const definition = {
id: createUniqueId(),
components: {
position: position ?? '0 0 0',
'managed-street': {
sourceType: 'json-blob',
sourceValue: JSON.stringify(streetObject),
showVehicles: true,
showStriping: true,
synchronize: true
}
}
};

AFRAME.INSPECTOR.execute('entitycreate', definition);
}
}

export function createStreetmixStreet(position, streetmixURL, hideBuildings) {
// legacy
// This code snippet allows the creation of an additional Streetmix street
// in your 3DStreet scene without replacing any existing streets.
if (streetmixURL === undefined) {
Expand Down Expand Up @@ -116,6 +139,18 @@ export function create60ftRightOfWay(position) {
true
);
}

export function create60ftRightOfWayManagedStreet(position) {
console.log(
'create60ftRightOfWayManagedStreet',
defaultStreetObjects.stroad60ftROW
);
createManagedStreetFromStreetObject(
position,
defaultStreetObjects.stroad60ftROW
);
}

export function create80ftRightOfWay(position) {
createStreetmixStreet(
position,
Expand Down
Loading

0 comments on commit a358304

Please sign in to comment.