From fa4d14868ee9875c0a8e5ebdec6283059e148c0b Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sat, 3 Jun 2023 12:30:41 +0530 Subject: [PATCH 01/12] update maps with the latest ethereal engine --- editor/MapNodeEditor.tsx | 9 ++-- editor/index.ts | 5 +- engine/MapFunctions.ts | 49 ++++++++++--------- engine/MapReceptor.ts | 25 +++++----- engine/MapUpdateSystem.ts | 24 +++++---- engine/functions/PhaseFunctions.ts | 2 +- engine/functions/createFeatureLabel.ts | 4 +- engine/functions/createGeometry.ts | 4 +- engine/functions/fetchUsingCache.ts | 4 +- engine/helpers/PolygonHelpers.ts | 4 +- .../phases/CreateFallbackLanduseMeshPhase.ts | 4 +- engine/phases/CreateGeometryPhase.ts | 6 +-- engine/phases/TransformFeaturePhase.ts | 7 ++- engine/workers/geometryWorker.ts | 3 +- package.json | 6 +-- worldInjection.ts | 11 ++--- xrengine.config.ts | 2 +- 17 files changed, 83 insertions(+), 86 deletions(-) diff --git a/editor/MapNodeEditor.tsx b/editor/MapNodeEditor.tsx index 901ddce..354407f 100755 --- a/editor/MapNodeEditor.tsx +++ b/editor/MapNodeEditor.tsx @@ -10,8 +10,7 @@ import { getComponent } from '@etherealengine/engine/src/ecs/functions/Component export const MapNodeEditor: EditorComponentType = (props) => { const { t } = useTranslation() - - const mapComponent = getComponent(props.node.entity, MapComponent) + const mapComponent = getComponent(props.entity, MapComponent) console.log('MapNodeEditor') return ( @@ -25,7 +24,7 @@ export const MapNodeEditor: EditorComponentType = (props) => { label={t('editor:properties.map.lbl-useDeviceGeolocation')} info={t('editor:properties.map.info-useDeviceGeolocation')} > - + @@ -38,14 +37,14 @@ export const MapNodeEditor: EditorComponentType = (props) => { label={t('editor:properties.map.lbl-showRasterTiles')} info={t('editor:properties.map.info-showRasterTiles')} > - + - + ) diff --git a/editor/index.ts b/editor/index.ts index c3481b4..3bb386b 100644 --- a/editor/index.ts +++ b/editor/index.ts @@ -3,12 +3,11 @@ import { EntityNodeEditor, prefabIcons } from '@etherealengine/editor/src/functi import { MapNodeEditor } from './MapNodeEditor' import MapIcon from '@mui/icons-material/Map' import { map } from '../worldInjection' -import { World } from '@etherealengine/engine/src/ecs/classes/World' import MapUpdateSystem from '../engine/MapUpdateSystem' EntityNodeEditor[map] = MapNodeEditor prefabIcons[map] = MapIcon -export default async (world: World) => { - return await MapUpdateSystem(world) +export default async () => { + return await MapUpdateSystem() } \ No newline at end of file diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index 7cd979c..622b5f0 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -1,38 +1,43 @@ -import { getStartCoords } from './getStartCoords' -import { MapComponentType } from './MapComponent' -import { addComponent, getComponent, hasComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { ComponentJson } from '@etherealengine/common/src/interfaces/SceneInterface' +import { LoadGLTF } from '@etherealengine/engine/src/assets/functions/LoadGLTF' +import { defaultAvatarHalfHeight } from '@etherealengine/engine/src/avatar/functions/spawnAvatarReceptor' import { DebugNavMeshComponent } from '@etherealengine/engine/src/debug/DebugNavMeshComponent' -import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' -import { Object3D, Group, Mesh } from 'three' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' +import { EngineState } from '@etherealengine/engine/src/ecs/classes/EngineState' +import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' +import { addComponent, getAllComponents, getComponent, hasComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' import { NavMeshComponent } from '@etherealengine/engine/src/navigation/component/NavMeshComponent' -import { MapAction, mapReducer } from './MapReceptor' -import { MapComponent } from './MapComponent' -import { getPhases, startPhases } from './functions/PhaseFunctions' -import { LoadGLTF } from '@etherealengine/engine/src/assets/functions/LoadGLTF' -import { avatarHalfHeight } from '@etherealengine/engine/src/avatar/functions/createAvatar' -import { Text } from 'troika-three-text' import { Object3DComponent } from '@etherealengine/engine/src/scene/components/Object3DComponent' -import { ComponentJson } from '@etherealengine/common/src/interfaces/SceneInterface' -import { isClient } from '@etherealengine/engine/src/common/functions/isClient' import { registerSceneLoadPromise } from '@etherealengine/engine/src/scene/functions/SceneLoading' -import { EntityNodeComponent } from '@etherealengine/engine/src/scene/components/EntityNodeComponent' -import { addChildFast, setPosition } from './util' +import { getState } from '@etherealengine/hyperflux' + import { debounce } from 'lodash' +import { Group, Mesh, Object3D } from 'three' +import { Text } from 'troika-three-text' + +import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' +import { MapComponent, MapComponentType } from './MapComponent' +import { MapAction, mapReducer } from './MapReceptor' +import { getPhases, startPhases } from './functions/PhaseFunctions' +import { getStartCoords } from './getStartCoords' +import { addChildFast, setPosition } from './util' export const SCENE_COMPONENT_MAP = 'map' export const SCENE_COMPONENT_MAP_DEFAULT_VALUES = {} export const deserializeMap = (entity: Entity, json: ComponentJson) => { if (isClient) { - registerSceneLoadPromise(createMap(entity, json.props)) - if (Engine.isEditor) getComponent(entity, EntityNodeComponent)?.components.push(SCENE_COMPONENT_MAP) + registerSceneLoadPromise(createMap(entity, json.props as MapComponentType)) + if (getState(EngineState).isEditor) { + const components = getAllComponents(entity) + components.push(SCENE_COMPONENT_MAP) + } } } export const createMap = async (entity: Entity, args: MapComponentType) => { - if(Engine.isEditor && hasComponent(entity, MapComponent)) { - _updateMap(entity, args) + if(getState(EngineState).isEditor && hasComponent(entity, MapComponent)) { + _updateMap(entity, args) return } // TODO: handle "navigator.geolocation.getCurrentPosition" rejection? @@ -55,9 +60,9 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { const state = mapReducer(null, MapAction.initialize(center, args.scale?.x)) // TODO fix hardcoded URL - const spinnerGLTF = await LoadGLTF(Engine.publicPath + '/projects/XREngine-Project-Maps/EarthLowPoly.glb') + const spinnerGLTF = await LoadGLTF(getState(EngineState).publicPath + '/projects/XREngine-Project-Maps/EarthLowPoly.glb') const spinner = spinnerGLTF.scene as Mesh - spinner.position.y = avatarHalfHeight * 2 + spinner.position.y = defaultAvatarHalfHeight * 2 spinner.position.z = -150 state.updateSpinner = spinner @@ -81,7 +86,7 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { await startPhases(state, await getPhases({ exclude: ['navigation'] })) navigationRaycastTarget.scale.setScalar(state.scale) - Engine.scene.add(navigationRaycastTarget) + Engine.instance.scene.add(navigationRaycastTarget) addComponent(entity, NavMeshComponent, { /* diff --git a/engine/MapReceptor.ts b/engine/MapReceptor.ts index 10cd2ee..79cf0f5 100644 --- a/engine/MapReceptor.ts +++ b/engine/MapReceptor.ts @@ -20,7 +20,7 @@ import { MultiPolygon } from 'polygon-clipping' import MutableNavMesh from './classes/MutableNavMesh' import { LongLat } from './functions/UnitConversionFunctions' import HashSet from './classes/HashSet' -import { isClient } from '@etherealengine/engine/src/common/functions/isClient' +import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' import { Mesh } from 'three' const state = createState({ @@ -86,25 +86,22 @@ export const mapReducer = (_, action: MapActionType) => { } export const mapReceptor = (action: MapActionType) => { - state.batch((s) => { - switch (action.type) { - case 'map.INITIALIZE': - return s.merge({ - center: action.centerPoint, + switch(action.type) { + case 'map.INITIALIZE': return state.merge({ + center: action.centerPoint, originalCenter: action.centerPoint, triggerRefreshRadius: action.triggerRefreshRadius, minimumSceneRadius: action.minimumSceneRadius, labelRadius: action.minimumSceneRadius * 0.5, navMeshRadius: action.minimumSceneRadius * 0.5, scale: action.scale - }) - case 'map.SET_CENTER_POINT': - return s.merge({ - center: action.centerPoint, - originalCenter: action.centerPoint - }) - } - }) + }) + case 'map.SET_CENTER_POINT': + return state.merge({ + center: action.centerPoint, + originalCenter: action.centerPoint + }) + } } export const accessMapState = () => state diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index 414a5a4..0a6d6f3 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -1,4 +1,3 @@ -import { System } from '@etherealengine/engine/src/ecs/classes/System' import { MapComponent } from './MapComponent' import { TransformComponent } from '@etherealengine/engine/src/transform/components/TransformComponent' import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctions' @@ -7,7 +6,6 @@ import { Vector3 } from 'three' import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' import { Object3DComponent } from '@etherealengine/engine/src/scene/components/Object3DComponent' import { getComponent, defineQuery, addComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' -import { World } from '@etherealengine/engine/src/ecs/classes/World' import isIntersectCircleCircle from './functions/isIntersectCircleCircle' import { AvatarComponent } from '@etherealengine/engine/src/avatar/components/AvatarComponent' import { NavMeshComponent } from '@etherealengine/engine/src/navigation/component/NavMeshComponent' @@ -15,6 +13,7 @@ import { accessMapState } from './MapReceptor' import { Downgraded } from '@hookstate/core' import { getPhases, startPhases, resetPhases } from './functions/PhaseFunctions' import { TargetCameraRotationComponent } from '@etherealengine/engine/src/camera/components/TargetCameraRotationComponent' +import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' const PI2 = Math.PI * 2 const $vector3 = new Vector3() @@ -24,7 +23,7 @@ const $normalScaleViewerPositionDelta = new Array(2) as [number, number] const $previousViewerPosition = new Vector3() const $previousMapCenterPoint: LongLat = Array(2) -export default async function MapUpdateSystem(world: World): Promise { +export default async function MapUpdateSystem(): Promise { const mapsQuery = defineQuery([MapComponent]) const viewerQuery = defineQuery([AvatarComponent]) const navMeshQuery = defineQuery([NavMeshComponent]) @@ -33,12 +32,12 @@ export default async function MapUpdateSystem(world: World): Promise { let spinnerAngle = 0 return () => { - const viewerEntity = viewerQuery(world)[0] - const mapEntities = mapsQuery(world) + const viewerEntity = viewerQuery()[0] + const mapEntities = mapsQuery() const mapEntity = mapEntities[0] - const navPlaneEntity = navMeshQuery(world)[0] + const navPlaneEntity = navMeshQuery()[0] // Sanity checks - if (!mapEntity || !viewerEntity) return world + if (!mapEntity || !viewerEntity) return if (mapEntities.length > 1) console.warn('Not supported: More than one map!') const mapState = accessMapState().attach(Downgraded).get() const mapScale = mapState.scale @@ -95,12 +94,12 @@ export default async function MapUpdateSystem(world: World): Promise { spinnerAngle = (spinnerAngle + 0.01) % PI2 object3dComponent.value.children.length = 0 - navigationRaycastTarget.children.length = 0 + // navigationRaycastTarget.children.length = 0 object3dComponent.value.children[0] = spinner object3dComponent.value.children[1] = mapState.updateTextContainer! - avatar.modelContainer.visible = false + avatar.model!.visible = false addComponent(viewerEntity, TargetCameraRotationComponent, { time: 0, phi: 0, @@ -109,7 +108,7 @@ export default async function MapUpdateSystem(world: World): Promise { thetaVelocity: { value: Math.PI } }) } else if (mapState.activePhase === 'UpdateScene') { - avatar.modelContainer.visible = true + avatar.model!.visible = true object3dComponent.value.children.length = 0 for (const key of mapState.completeObjects.keys()) { const object = mapState.completeObjects.get(key) @@ -147,7 +146,7 @@ export default async function MapUpdateSystem(world: World): Promise { } } } - navigationRaycastTarget.children.length = 0 + // navigationRaycastTarget.children.length = 0 for (const key of mapState.completeObjects.keys()) { const layerName = key[0] if (layerName === 'landuse_fallback') { @@ -168,7 +167,7 @@ export default async function MapUpdateSystem(world: World): Promise { } // Update labels - if (Math.round(world.fixedElapsedTime / world.fixedDelta) % 20 === 0) { + if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) { for (const label of mapState.labelCache.values()) { if (label.mesh) { if ( @@ -185,6 +184,5 @@ export default async function MapUpdateSystem(world: World): Promise { } } previousViewerEntity = viewerEntity - return world } } diff --git a/engine/functions/PhaseFunctions.ts b/engine/functions/PhaseFunctions.ts index c9e8838..83abfbe 100644 --- a/engine/functions/PhaseFunctions.ts +++ b/engine/functions/PhaseFunctions.ts @@ -1,6 +1,6 @@ +import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' import { TaskStatus } from '../types' import { ICachingPhase, IPhase, ISyncPhase, MapStateUnwrapped } from '../types' -import { isClient } from '@etherealengine/engine/src/common/functions/isClient' // Random Thought: Monads like https://github.com/monet/monet.js/blob/master/docs/FREE.md could be useful here. type FeatureId = 'navigation' diff --git a/engine/functions/createFeatureLabel.ts b/engine/functions/createFeatureLabel.ts index 2596d8d..807ae3b 100644 --- a/engine/functions/createFeatureLabel.ts +++ b/engine/functions/createFeatureLabel.ts @@ -37,7 +37,7 @@ function createText(textString: string): Text3D { const $cameraDirection = new Vector3() function createUpdateClosure(mesh: Text3D, middleSlice: Position[]) { return function updateFeatureLabel() { - const camera = Engine.camera + const camera = Engine.instance.camera const [[x1, y1]] = middleSlice const [x2, y2] = middleSlice[middleSlice.length - 1] @@ -53,7 +53,7 @@ function createUpdateClosure(mesh: Text3D, middleSlice: Position[]) { ) mesh.rotateX(-Math.PI / 2) - mesh.fontSize = Math.min(Math.max(Engine.camera.position.y / 4, MINIMUM_FONT_SIZE), MAXIMUM_FONT_SIZE) + mesh.fontSize = Math.min(Math.max(Engine.instance.camera.position.y / 4, MINIMUM_FONT_SIZE), MAXIMUM_FONT_SIZE) mesh.sync() } diff --git a/engine/functions/createGeometry.ts b/engine/functions/createGeometry.ts index 7216d13..2e11df4 100644 --- a/engine/functions/createGeometry.ts +++ b/engine/functions/createGeometry.ts @@ -22,13 +22,13 @@ function getBuildingColor(feature: SupportedFeature) { } function colorVertices(geometry: BufferGeometry, baseColor: Color, light: Color, shadow: Color) { - const normals = geometry.attributes.normal + const normals = geometry.attributes.normal as BufferAttribute const topColor = baseColor.clone().multiply(light) const bottomColor = baseColor.clone().multiply(shadow) geometry.setAttribute('color', new BufferAttribute(new Float32Array(normals.count * 3), 3)) - const colors = geometry.attributes.color + const colors = geometry.attributes.color as BufferAttribute geometry.computeVertexNormals() geometry.computeBoundingBox() diff --git a/engine/functions/fetchUsingCache.ts b/engine/functions/fetchUsingCache.ts index 7f7e411..7e5709f 100644 --- a/engine/functions/fetchUsingCache.ts +++ b/engine/functions/fetchUsingCache.ts @@ -3,7 +3,7 @@ import { ITuple, MapStateUnwrapped } from '../types' import createUsingGetSet from './createUsingGetSet' export default function fetchUsingCache( - fetch: (state: MapStateUnwrapped, key: CacheKey, ...args: any[]) => Promise + fetch: (state: MapStateUnwrapped, key: CacheKey, ...args: any[]) => Value ) { const _fetchUsingCache = createUsingGetSet(fetch) return async ( @@ -14,7 +14,7 @@ export default function fetchUsingCache( ) => { return await _fetchUsingCache( cache.get.bind(cache), - async function set(key: CacheKey, value: Promise) { + async function set(key: CacheKey, value: Value) { const resolvedValue = await value cache.set(key, resolvedValue) }, diff --git a/engine/helpers/PolygonHelpers.ts b/engine/helpers/PolygonHelpers.ts index ea61000..3fe031b 100644 --- a/engine/helpers/PolygonHelpers.ts +++ b/engine/helpers/PolygonHelpers.ts @@ -6,7 +6,7 @@ import { MeshBasicMaterial, Mesh, Shape, - ShapeBufferGeometry, + ShapeGeometry, Path } from 'three' @@ -34,7 +34,7 @@ export function createPolygonHelper(polygon: Polygon): Mesh { shape.holes[innerRingIndex - 1] = path } - const geometry = new ShapeBufferGeometry(shape) + const geometry = new ShapeGeometry(shape) const material = new MeshBasicMaterial({ color }) geometry.rotateX(-Math.PI / 2) diff --git a/engine/phases/CreateFallbackLanduseMeshPhase.ts b/engine/phases/CreateFallbackLanduseMeshPhase.ts index 8efd3cd..2a0c25d 100644 --- a/engine/phases/CreateFallbackLanduseMeshPhase.ts +++ b/engine/phases/CreateFallbackLanduseMeshPhase.ts @@ -1,7 +1,7 @@ import { TileKey, MapStateUnwrapped } from '../types' import { DEFAULT_FEATURE_STYLES, getFeatureStyles, MAX_Z_INDEX } from '../styles' import getCachedMaterial from '../functions/getCachedMaterial' -import { Mesh, MeshLambertMaterial, PlaneBufferGeometry } from 'three' +import { Mesh, MeshLambertMaterial, PlaneGeometry } from 'three' import computeTileBoundingBox from '../functions/computeTileBoundingBox' import FeatureKey from '../classes/FeatureKey' @@ -33,7 +33,7 @@ export function execTask(state: MapStateUnwrapped, key: TileKey) { const material = getCachedMaterial(MeshLambertMaterial, { color, depthTest: false }) - const geometry = new PlaneBufferGeometry(tileWidth, tileHeight) + const geometry = new PlaneGeometry(tileWidth, tileHeight) geometry.rotateX(-Math.PI / 2) const mesh = new Mesh(geometry, material) diff --git a/engine/phases/CreateGeometryPhase.ts b/engine/phases/CreateGeometryPhase.ts index ed70c5a..c0a8a06 100644 --- a/engine/phases/CreateGeometryPhase.ts +++ b/engine/phases/CreateGeometryPhase.ts @@ -4,7 +4,7 @@ import isIntersectCircleCircle from '../functions/isIntersectCircleCircle' import { FeatureKey, TaskStatus, MapStateUnwrapped } from '../types' import { multiplyArray } from '../util' // @ts-ignore -import createGeometryWorker from '../workers/geometryWorker.ts?worker' +import createGeometryWorker from '../workers/geometryWorker.ts' import { WorkerApi } from '../workers/geometryWorker' import { DEFAULT_FEATURE_STYLES, getFeatureStyles } from '../styles' import { BufferGeometryLoader } from 'three' @@ -12,7 +12,7 @@ import { getHumanFriendlyFeatureKey } from '../helpers/KeyHelpers' const $array2 = Array(2) -const createGeometry = createWorkerFunction(createGeometryWorker()) +const createGeometry = createWorkerFunction(createGeometryWorker) const geometryLoader = new BufferGeometryLoader() @@ -63,7 +63,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status: } export function startTask(state: MapStateUnwrapped, key: FeatureKey) { - return createGeometryUsingCache(state.geometryCache, state, key) + return createGeometryUsingCache(state.geometryCache as any, state, key) } export function cleanup(state: MapStateUnwrapped) { diff --git a/engine/phases/TransformFeaturePhase.ts b/engine/phases/TransformFeaturePhase.ts index 87fe992..86141f0 100644 --- a/engine/phases/TransformFeaturePhase.ts +++ b/engine/phases/TransformFeaturePhase.ts @@ -1,11 +1,10 @@ import { MapStateUnwrapped, FeatureKey, TaskStatus } from '../types' import fetchUsingCache from '../functions/fetchUsingCache' -// @ts-ignore -import createWorker from '../workers/transformFeatureWorker.ts?worker' import { WorkerApi } from '../workers/transformFeatureWorker' import createWorkerFunction from '../functions/createWorkerFunction' +import { createWorkerFromCrossOriginURL } from '@etherealengine/common/src/utils/createWorkerFromCrossOriginURL' -const transformFeature = createWorkerFunction(createWorker()) +const transformFeature = createWorkerFunction(createWorkerFromCrossOriginURL('../workers/transformFeatureWorker.ts', true, {name: 'Transform Feature Worker'})) export const name = 'TransformFeature' export const isAsyncPhase = true @@ -34,7 +33,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status: } export function startTask(state: MapStateUnwrapped, key: FeatureKey) { - return transformFeatureUsingCache(state.transformedFeatureCache, state, key) + return transformFeatureUsingCache(state.transformedFeatureCache as any, state, key) } export function cleanup(state: MapStateUnwrapped) { diff --git a/engine/workers/geometryWorker.ts b/engine/workers/geometryWorker.ts index fa03098..c44ab23 100644 --- a/engine/workers/geometryWorker.ts +++ b/engine/workers/geometryWorker.ts @@ -1,4 +1,5 @@ import * as Comlink from 'comlink' +import { BufferAttribute } from 'three' import createGeometry from '../functions/createGeometry' import { IStyles } from '../styles' import { SupportedFeature } from '../types' @@ -26,7 +27,7 @@ function createGeometryInWorker(feature: SupportedFeature, style: IStyles) { const attributes = {} for (let attributeName of Object.keys(geometry.attributes)) { - const attribute = geometry.getAttribute(attributeName) + const attribute = geometry.getAttribute(attributeName) as BufferAttribute const array = attribute.array as Float32Array Comlink.transfer(array, [array.buffer]) attributes[attributeName] = { diff --git a/package.json b/package.json index 2fad23e..f934042 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "scripts": { "test": "exit 0" }, - "peerDependencies": {}, "dependencies": { "@mapbox/vector-tile": "^1.3.1", "@turf/turf": "^6.5.0", @@ -18,10 +17,11 @@ "troika-three-text": "^0.44.0" }, "devDependencies": { - "mocha": "9.1.3", - "earcut": "^2.2.3", "@types/earcut": "2.1.1", "@types/geojson": "7946.0.8", + "@types/yuka": "^0.7.1", + "earcut": "^2.2.3", + "mocha": "9.1.3", "trace-unhandled": "2.0.1" }, "license": "ISC" diff --git a/worldInjection.ts b/worldInjection.ts index f7b9228..96024d9 100644 --- a/worldInjection.ts +++ b/worldInjection.ts @@ -1,23 +1,22 @@ - -import { World } from '@etherealengine/engine/src/ecs/classes/World' import { deserializeMap, SCENE_COMPONENT_MAP, SCENE_COMPONENT_MAP_DEFAULT_VALUES, serializeMap, updateMap } from './engine/MapFunctions' import { defaultSpatialComponents } from '@etherealengine/engine/src/scene/functions/registerPrefabs' import { isNode } from '@etherealengine/engine/src/common/functions/getEnvironment' +import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' export const map = 'Geo Map' as const -export default async (world: World) => { +export default async () => { if(!isNode) { - (await import('./editor/index')).default(world) + (await import('./editor/index')).default() } - world.scenePrefabRegistry.set(map, [ + Engine.instance.scenePrefabRegistry.set(map, [ ...defaultSpatialComponents, { name: SCENE_COMPONENT_MAP, props: SCENE_COMPONENT_MAP_DEFAULT_VALUES } ]) - world.sceneLoadingRegistry.set(SCENE_COMPONENT_MAP, { + Engine.instance.sceneLoadingRegistry.set(SCENE_COMPONENT_MAP, { deserialize: deserializeMap, serialize: serializeMap, update: updateMap diff --git a/xrengine.config.ts b/xrengine.config.ts index 85bc433..a07d59c 100644 --- a/xrengine.config.ts +++ b/xrengine.config.ts @@ -3,7 +3,7 @@ import type { ProjectConfigInterface } from '@etherealengine/projects/ProjectCon const config: ProjectConfigInterface = { onEvent: undefined, thumbnail: '/static/etherealengine_thumbnail.jpg', - worldInjection: () => import('./worldInjection'), + // worldInjection: () => import('./worldInjection'), routes: {}, services: undefined, databaseSeed: undefined From 4ad3fd051e81ee473e9b5d16455c80570765fda1 Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sat, 3 Jun 2023 12:53:55 +0530 Subject: [PATCH 02/12] fix: remove incorrect committed lines --- engine/MapFunctions.ts | 2 +- engine/MapUpdateSystem.ts | 2 +- engine/functions/findSplitFeatures.ts | 2 +- engine/phases/CreateGeometryPhase.ts | 5 ++--- engine/phases/FetchTilesPhase.ts | 2 +- xrengine.config.ts | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index 622b5f0..cf823fa 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -37,7 +37,7 @@ export const deserializeMap = (entity: Entity, json: ComponentJson { if(getState(EngineState).isEditor && hasComponent(entity, MapComponent)) { - _updateMap(entity, args) + _updateMap(entity, args) return } // TODO: handle "navigator.geolocation.getCurrentPosition" rejection? diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index 0a6d6f3..cadb164 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -94,7 +94,7 @@ export default async function MapUpdateSystem(): Promise { spinnerAngle = (spinnerAngle + 0.01) % PI2 object3dComponent.value.children.length = 0 - // navigationRaycastTarget.children.length = 0 + navigationRaycastTarget.children.length = 0 object3dComponent.value.children[0] = spinner object3dComponent.value.children[1] = mapState.updateTextContainer! diff --git a/engine/functions/findSplitFeatures.ts b/engine/functions/findSplitFeatures.ts index dbb2e3f..c2c7d81 100644 --- a/engine/functions/findSplitFeatures.ts +++ b/engine/functions/findSplitFeatures.ts @@ -12,7 +12,7 @@ export default function* findSplitFeatures(keys: Iterator, features: const groups = new Map() const addToGroup = updateKeyVal( groups.get.bind(groups), - groups.set.bind(groups), + groups.set.bind(groups), // help needed! (group: Group, newKey: FeatureKey, newFeature: Feature) => { return [...group, [newKey, newFeature]] }, diff --git a/engine/phases/CreateGeometryPhase.ts b/engine/phases/CreateGeometryPhase.ts index c0a8a06..2799cf0 100644 --- a/engine/phases/CreateGeometryPhase.ts +++ b/engine/phases/CreateGeometryPhase.ts @@ -3,16 +3,15 @@ import fetchUsingCache from '../functions/fetchUsingCache' import isIntersectCircleCircle from '../functions/isIntersectCircleCircle' import { FeatureKey, TaskStatus, MapStateUnwrapped } from '../types' import { multiplyArray } from '../util' -// @ts-ignore -import createGeometryWorker from '../workers/geometryWorker.ts' import { WorkerApi } from '../workers/geometryWorker' import { DEFAULT_FEATURE_STYLES, getFeatureStyles } from '../styles' import { BufferGeometryLoader } from 'three' import { getHumanFriendlyFeatureKey } from '../helpers/KeyHelpers' +import { createWorkerFromCrossOriginURL } from '@etherealengine/common/src/utils/createWorkerFromCrossOriginURL' const $array2 = Array(2) -const createGeometry = createWorkerFunction(createGeometryWorker) +const createGeometry = createWorkerFunction(createWorkerFromCrossOriginURL('../workers/geometryWorker.ts', true, {name: "Geometry Worker"})) const geometryLoader = new BufferGeometryLoader() diff --git a/engine/phases/FetchTilesPhase.ts b/engine/phases/FetchTilesPhase.ts index a6469e3..6852265 100644 --- a/engine/phases/FetchTilesPhase.ts +++ b/engine/phases/FetchTilesPhase.ts @@ -5,7 +5,7 @@ import { TILE_ZOOM } from '../constants' import fetchUsingCache from '../functions/fetchUsingCache' import fetchVectorTile from '../functions/fetchVectorTile' -const fetchVectorTileUsingCache = fetchUsingCache(fetchVectorTile) +const fetchVectorTileUsingCache = fetchUsingCache(fetchVectorTile) // help needed! export const name = 'FetchTiles' export const isAsyncPhase = true diff --git a/xrengine.config.ts b/xrengine.config.ts index a07d59c..85bc433 100644 --- a/xrengine.config.ts +++ b/xrengine.config.ts @@ -3,7 +3,7 @@ import type { ProjectConfigInterface } from '@etherealengine/projects/ProjectCon const config: ProjectConfigInterface = { onEvent: undefined, thumbnail: '/static/etherealengine_thumbnail.jpg', - // worldInjection: () => import('./worldInjection'), + worldInjection: () => import('./worldInjection'), routes: {}, services: undefined, databaseSeed: undefined From d0300e666feb4b8a5704beac8567e201c18dc02a Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sat, 3 Jun 2023 23:47:20 +0530 Subject: [PATCH 03/12] fix: incorporate corrections from reviews --- editor/MapNodeEditor.tsx | 16 ++++++++-------- engine/MapFunctions.ts | 2 +- engine/phases/CreateGeometryPhase.ts | 2 +- engine/phases/TransformFeaturePhase.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/editor/MapNodeEditor.tsx b/editor/MapNodeEditor.tsx index 354407f..93c9be0 100755 --- a/editor/MapNodeEditor.tsx +++ b/editor/MapNodeEditor.tsx @@ -6,45 +6,45 @@ import StringInput from '@etherealengine/editor/src/components/inputs/StringInpu import NodeEditor from '@etherealengine/editor/src/components/properties/NodeEditor' import { MapComponent } from '../engine/MapComponent' import { EditorComponentType, updateProperty } from '@etherealengine/editor/src/components/properties/Util' -import { getComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { useComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' export const MapNodeEditor: EditorComponentType = (props) => { const { t } = useTranslation() - const mapComponent = getComponent(props.entity, MapComponent) + const mapComponent = useComponent(props.entity, MapComponent) console.log('MapNodeEditor') return ( - + - + - + - + - + - + ) diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index cf823fa..b29a557 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -60,7 +60,7 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { const state = mapReducer(null, MapAction.initialize(center, args.scale?.x)) // TODO fix hardcoded URL - const spinnerGLTF = await LoadGLTF(getState(EngineState).publicPath + '/projects/XREngine-Project-Maps/EarthLowPoly.glb') + const spinnerGLTF = await LoadGLTF(getState(EngineState).publicPath + '/projects/ee-maps/EarthLowPoly.glb') const spinner = spinnerGLTF.scene as Mesh spinner.position.y = defaultAvatarHalfHeight * 2 spinner.position.z = -150 diff --git a/engine/phases/CreateGeometryPhase.ts b/engine/phases/CreateGeometryPhase.ts index 2799cf0..b4f468a 100644 --- a/engine/phases/CreateGeometryPhase.ts +++ b/engine/phases/CreateGeometryPhase.ts @@ -11,7 +11,7 @@ import { createWorkerFromCrossOriginURL } from '@etherealengine/common/src/utils const $array2 = Array(2) -const createGeometry = createWorkerFunction(createWorkerFromCrossOriginURL('../workers/geometryWorker.ts', true, {name: "Geometry Worker"})) +const createGeometry = createWorkerFunction(createWorkerFromCrossOriginURL(new URL('../workers/geometryWorker.ts', import.meta.url).href, true, {name: "Geometry Worker"})) const geometryLoader = new BufferGeometryLoader() diff --git a/engine/phases/TransformFeaturePhase.ts b/engine/phases/TransformFeaturePhase.ts index 86141f0..80b8253 100644 --- a/engine/phases/TransformFeaturePhase.ts +++ b/engine/phases/TransformFeaturePhase.ts @@ -4,7 +4,7 @@ import { WorkerApi } from '../workers/transformFeatureWorker' import createWorkerFunction from '../functions/createWorkerFunction' import { createWorkerFromCrossOriginURL } from '@etherealengine/common/src/utils/createWorkerFromCrossOriginURL' -const transformFeature = createWorkerFunction(createWorkerFromCrossOriginURL('../workers/transformFeatureWorker.ts', true, {name: 'Transform Feature Worker'})) +const transformFeature = createWorkerFunction(createWorkerFromCrossOriginURL(new URL('../workers/transformFeatureWorker.ts', import.meta.url).href, true, {name: 'Transform Feature Worker'})) export const name = 'TransformFeature' export const isAsyncPhase = true diff --git a/tsconfig.json b/tsconfig.json index b621634..dd1aaa3 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "noEmit": true, - "module": "CommonJS", + "module": "ES2020", "strict": false, "strictNullChecks": true, "strictBindCallApply": true, From 2d04752ef575bcf9ce0f0c0e02fe2e076d73d4ce Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sun, 4 Jun 2023 11:41:36 +0530 Subject: [PATCH 04/12] fix: .value after property --- editor/MapNodeEditor.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/MapNodeEditor.tsx b/editor/MapNodeEditor.tsx index 93c9be0..c08c828 100755 --- a/editor/MapNodeEditor.tsx +++ b/editor/MapNodeEditor.tsx @@ -17,34 +17,34 @@ export const MapNodeEditor: EditorComponentType = (props) => { - + - + - + - + - + - + ) From 7e1381b1ecc02f3eeabe3f61f5e138fe75dfc963 Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Thu, 8 Jun 2023 21:33:45 +0530 Subject: [PATCH 05/12] fix: mapfunctions and mapupdatesystems --- engine/MapFunctions.ts | 43 +++++++++++++++--------------- engine/MapUpdateSystem.ts | 20 +++++++------- engine/helpers/NavMeshComponent.ts | 11 ++++++++ worldInjection.ts | 25 ++++++++++------- 4 files changed, 58 insertions(+), 41 deletions(-) create mode 100644 engine/helpers/NavMeshComponent.ts diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index b29a557..e8aea1a 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -1,14 +1,10 @@ import { ComponentJson } from '@etherealengine/common/src/interfaces/SceneInterface' -import { LoadGLTF } from '@etherealengine/engine/src/assets/functions/LoadGLTF' import { defaultAvatarHalfHeight } from '@etherealengine/engine/src/avatar/functions/spawnAvatarReceptor' -import { DebugNavMeshComponent } from '@etherealengine/engine/src/debug/DebugNavMeshComponent' +// import { DebugNavMeshComponent } from '@etherealengine/engine/src/debug/DebugNavMeshComponent' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' import { EngineState } from '@etherealengine/engine/src/ecs/classes/EngineState' import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' -import { addComponent, getAllComponents, getComponent, hasComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' -import { NavMeshComponent } from '@etherealengine/engine/src/navigation/component/NavMeshComponent' -import { Object3DComponent } from '@etherealengine/engine/src/scene/components/Object3DComponent' -import { registerSceneLoadPromise } from '@etherealengine/engine/src/scene/functions/SceneLoading' +import { addComponent, defineQuery, getAllComponents, getComponent, hasComponent, setComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' import { getState } from '@etherealengine/hyperflux' import { debounce } from 'lodash' @@ -21,17 +17,24 @@ import { MapAction, mapReducer } from './MapReceptor' import { getPhases, startPhases } from './functions/PhaseFunctions' import { getStartCoords } from './getStartCoords' import { addChildFast, setPosition } from './util' +import { NavMeshComponent } from './helpers/NavMeshComponent' +import { GroupComponent, Object3DWithEntity } from '@etherealengine/engine/src/scene/components/GroupComponent' +import { SceneAssetPendingTagComponent } from '@etherealengine/engine/src/scene/components/SceneAssetPendingTagComponent' export const SCENE_COMPONENT_MAP = 'map' export const SCENE_COMPONENT_MAP_DEFAULT_VALUES = {} export const deserializeMap = (entity: Entity, json: ComponentJson) => { + const sceneAssetPendingTagQuery = defineQuery([SceneAssetPendingTagComponent]) if (isClient) { - registerSceneLoadPromise(createMap(entity, json.props as MapComponentType)) - if (getState(EngineState).isEditor) { - const components = getAllComponents(entity) - components.push(SCENE_COMPONENT_MAP) + if(sceneAssetPendingTagQuery.length > 0) { + createMap(entity, json.props as MapComponentType) } + + // if (getState(EngineState).isEditor) { + // const components = getAllComponents(entity) + // components.push(SCENE_COMPONENT_MAP) + // } } } @@ -45,26 +48,24 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { addComponent(entity, MapComponent, args) const center = await getStartCoords(args) - const mapObject3D = new Group() + const mapObject3D = new Object3D() as Object3DWithEntity const navigationRaycastTarget = new Group() mapObject3D.name = '(Geographic) Map' - addComponent(entity, Object3DComponent, { - value: mapObject3D - }) + addComponent(entity, GroupComponent, [mapObject3D]) + if (args.enableDebug) { - addComponent(entity, DebugNavMeshComponent, { object3d: new Group() }) + // addComponent(entity, DebugNavMeshComponent, { object3d: new Group() }) } const state = mapReducer(null, MapAction.initialize(center, args.scale?.x)) - // TODO fix hardcoded URL - const spinnerGLTF = await LoadGLTF(getState(EngineState).publicPath + '/projects/ee-maps/EarthLowPoly.glb') - const spinner = spinnerGLTF.scene as Mesh - spinner.position.y = defaultAvatarHalfHeight * 2 - spinner.position.z = -150 - state.updateSpinner = spinner + // const spinnerGLTF = getState(EngineState).publicPath + '/projects/ee-maps/EarthLowPoly.glb' + // const spinner = spinnerGLTF as Mesh + // spinner.position.y = defaultAvatarHalfHeight * 2 + // spinner.position.z = -150 + // state.updateSpinner = spinner const updateTextContainer = new Text() diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index cadb164..5f6f41e 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -4,16 +4,16 @@ import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctio import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util' import { Vector3 } from 'three' import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' -import { Object3DComponent } from '@etherealengine/engine/src/scene/components/Object3DComponent' import { getComponent, defineQuery, addComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' import isIntersectCircleCircle from './functions/isIntersectCircleCircle' import { AvatarComponent } from '@etherealengine/engine/src/avatar/components/AvatarComponent' -import { NavMeshComponent } from '@etherealengine/engine/src/navigation/component/NavMeshComponent' import { accessMapState } from './MapReceptor' import { Downgraded } from '@hookstate/core' import { getPhases, startPhases, resetPhases } from './functions/PhaseFunctions' import { TargetCameraRotationComponent } from '@etherealengine/engine/src/camera/components/TargetCameraRotationComponent' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' +import { GroupComponent } from '@etherealengine/engine/src/scene/components/GroupComponent' +import { NavMeshComponent } from './helpers/NavMeshComponent' const PI2 = Math.PI * 2 const $vector3 = new Vector3() @@ -41,7 +41,7 @@ export default async function MapUpdateSystem(): Promise { if (mapEntities.length > 1) console.warn('Not supported: More than one map!') const mapState = accessMapState().attach(Downgraded).get() const mapScale = mapState.scale - const object3dComponent = getComponent(mapEntity, Object3DComponent) + const object3dComponent = getComponent(mapEntity, GroupComponent) const viewerTransform = getComponent(viewerEntity, TransformComponent) const viewerPosition = vectorToArray(viewerTransform.position) const viewerPositionScaled = multiplyArray(viewerPosition, 1 / mapScale) @@ -93,11 +93,11 @@ export default async function MapUpdateSystem(): Promise { spinner.rotation.y = spinnerAngle spinnerAngle = (spinnerAngle + 0.01) % PI2 - object3dComponent.value.children.length = 0 + object3dComponent[0].children.length = 0 navigationRaycastTarget.children.length = 0 - object3dComponent.value.children[0] = spinner + object3dComponent[0].children[0] = spinner - object3dComponent.value.children[1] = mapState.updateTextContainer! + object3dComponent[0].children[1] = mapState.updateTextContainer! avatar.model!.visible = false addComponent(viewerEntity, TargetCameraRotationComponent, { @@ -109,7 +109,7 @@ export default async function MapUpdateSystem(): Promise { }) } else if (mapState.activePhase === 'UpdateScene') { avatar.model!.visible = true - object3dComponent.value.children.length = 0 + object3dComponent[0].children.length = 0 for (const key of mapState.completeObjects.keys()) { const object = mapState.completeObjects.get(key) if (object.mesh) { @@ -123,7 +123,7 @@ export default async function MapUpdateSystem(): Promise { key[0] !== 'landuse_fallback' ) { setPosition(object.mesh, object.centerPoint) - addChildFast(object3dComponent.value, object.mesh) + addChildFast(object3dComponent[0], object.mesh) } else { object.mesh.parent = null } @@ -140,7 +140,7 @@ export default async function MapUpdateSystem(): Promise { ) ) { setPosition(label.mesh, label.centerPoint) - addChildFast(object3dComponent.value, label.mesh) + addChildFast(object3dComponent[0], label.mesh) } else { label.mesh.parent = null } @@ -158,7 +158,7 @@ export default async function MapUpdateSystem(): Promise { } for (const helpers of mapState.helpersCache.values()) { if (helpers.tileNavMesh) { - addChildFast(object3dComponent.value, helpers.tileNavMesh) + addChildFast(object3dComponent[0], helpers.tileNavMesh) } } diff --git a/engine/helpers/NavMeshComponent.ts b/engine/helpers/NavMeshComponent.ts new file mode 100644 index 0000000..a38829c --- /dev/null +++ b/engine/helpers/NavMeshComponent.ts @@ -0,0 +1,11 @@ +import { Object3D } from 'three' +import { NavMesh } from 'yuka' + +import { createMappedComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' + +export type NavMeshComponentType = { + yukaNavMesh?: NavMesh + navTarget: Object3D +} + +export const NavMeshComponent = createMappedComponent('NavMeshComponent') \ No newline at end of file diff --git a/worldInjection.ts b/worldInjection.ts index 96024d9..6bee02a 100644 --- a/worldInjection.ts +++ b/worldInjection.ts @@ -1,24 +1,29 @@ import { deserializeMap, SCENE_COMPONENT_MAP, SCENE_COMPONENT_MAP_DEFAULT_VALUES, serializeMap, updateMap } from './engine/MapFunctions' -import { defaultSpatialComponents } from '@etherealengine/engine/src/scene/functions/registerPrefabs' -import { isNode } from '@etherealengine/engine/src/common/functions/getEnvironment' +import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' +import { defineQuery, setComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { SceneAssetPendingTagComponent } from '@etherealengine/engine/src/scene/components/SceneAssetPendingTagComponent' +import { defaultSpatialComponents } from '@etherealengine/engine/src/scene/systems/SceneObjectUpdateSystem' -export const map = 'Geo Map' as const +export const GEO_MAP = 'Geo Map' as const export default async () => { - if(!isNode) { + if(isClient) { (await import('./editor/index')).default() } - Engine.instance.scenePrefabRegistry.set(map, [ + Engine.instance.scenePrefabRegistry.set(GEO_MAP, [ ...defaultSpatialComponents, { name: SCENE_COMPONENT_MAP, props: SCENE_COMPONENT_MAP_DEFAULT_VALUES } ]) - Engine.instance.sceneLoadingRegistry.set(SCENE_COMPONENT_MAP, { - deserialize: deserializeMap, - serialize: serializeMap, - update: updateMap - }) + const sceneAssetPendingTagQuery = defineQuery([SceneAssetPendingTagComponent]) + if(sceneAssetPendingTagQuery.length > 0) { + Engine.instance.sceneLoadingRegistry.set(SCENE_COMPONENT_MAP, { + deserialize: deserializeMap, + serialize: serializeMap, + update: updateMap + }) + } } From 667ba30f3388fa3e4ac3148347df4ebe2ba55e5e Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sun, 11 Jun 2023 15:11:33 +0530 Subject: [PATCH 06/12] fix: errors in engine functions and phases --- editor/index.ts | 6 +++--- engine/functions/fetchUsingCache.ts | 18 ++++++++++++++++++ engine/functions/findSplitFeatures.ts | 6 +++++- engine/phases/FetchTilesPhase.ts | 10 +++++----- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/editor/index.ts b/editor/index.ts index 3bb386b..116bd50 100644 --- a/editor/index.ts +++ b/editor/index.ts @@ -2,11 +2,11 @@ import { EntityNodeEditor, prefabIcons } from '@etherealengine/editor/src/functions/PrefabEditors' import { MapNodeEditor } from './MapNodeEditor' import MapIcon from '@mui/icons-material/Map' -import { map } from '../worldInjection' +import { GEO_MAP } from '../worldInjection' import MapUpdateSystem from '../engine/MapUpdateSystem' -EntityNodeEditor[map] = MapNodeEditor -prefabIcons[map] = MapIcon +EntityNodeEditor[GEO_MAP] = MapNodeEditor +prefabIcons[GEO_MAP] = MapIcon export default async () => { return await MapUpdateSystem() diff --git a/engine/functions/fetchUsingCache.ts b/engine/functions/fetchUsingCache.ts index 7e5709f..8120d35 100644 --- a/engine/functions/fetchUsingCache.ts +++ b/engine/functions/fetchUsingCache.ts @@ -24,3 +24,21 @@ export default function fetchUsingCache( ) } } + +export function fetchUsingCacheAsync( + fetch: (state: MapStateUnwrapped, key: CacheKey, ...args: any[]) => Promise +) { + return async ( + cache: ParametricCache, + state: MapStateUnwrapped, + key: CacheKey, + ...extraArgs: any[] + ) => { + let value = cache.get(key) + if (!value) { + value = await fetch(state, key, ...extraArgs) + cache.set(key, value) + } + return value + } +} diff --git a/engine/functions/findSplitFeatures.ts b/engine/functions/findSplitFeatures.ts index c2c7d81..eb8ba48 100644 --- a/engine/functions/findSplitFeatures.ts +++ b/engine/functions/findSplitFeatures.ts @@ -10,9 +10,13 @@ type Group = [FeatureKey, Feature][] export default function* findSplitFeatures(keys: Iterator, features: Iterator): Generator { const zipped = zipIterators<[FeatureKey, Feature]>(keys, features) const groups = new Map() + const groupSetFunction = (groupKey: GroupKey, groupValue: Group) => { + groups.set(groupKey, groupValue) + return groupValue + } const addToGroup = updateKeyVal( groups.get.bind(groups), - groups.set.bind(groups), // help needed! + groupSetFunction, (group: Group, newKey: FeatureKey, newFeature: Feature) => { return [...group, [newKey, newFeature]] }, diff --git a/engine/phases/FetchTilesPhase.ts b/engine/phases/FetchTilesPhase.ts index 6852265..50c9f7f 100644 --- a/engine/phases/FetchTilesPhase.ts +++ b/engine/phases/FetchTilesPhase.ts @@ -1,11 +1,11 @@ -import { MapStateUnwrapped, TaskStatus, TileKey } from '../types' -import { VectorTile } from '../types' -import createSurroundingTileIterator from '../functions/createSurroundingTileIterator' import { TILE_ZOOM } from '../constants' -import fetchUsingCache from '../functions/fetchUsingCache' +import createSurroundingTileIterator from '../functions/createSurroundingTileIterator' +import { fetchUsingCacheAsync } from '../functions/fetchUsingCache' import fetchVectorTile from '../functions/fetchVectorTile' +import { MapStateUnwrapped, TaskStatus, TileKey } from '../types' +import { VectorTile } from '../types' -const fetchVectorTileUsingCache = fetchUsingCache(fetchVectorTile) // help needed! +const fetchVectorTileUsingCache = fetchUsingCacheAsync(fetchVectorTile) export const name = 'FetchTiles' export const isAsyncPhase = true From cac2c481a257b3d4cd347316f5bcd1fa5f1a476d Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sat, 17 Jun 2023 12:44:37 +0530 Subject: [PATCH 07/12] feat: defineComponent --- engine/MapComponent.ts | 7 +++- engine/MapFunctions.ts | 81 +++++++++++++++++++++++------------------- worldInjection.ts | 74 ++++++++++++++++++++++++++++++-------- 3 files changed, 111 insertions(+), 51 deletions(-) diff --git a/engine/MapComponent.ts b/engine/MapComponent.ts index 8f12a26..2bfe916 100644 --- a/engine/MapComponent.ts +++ b/engine/MapComponent.ts @@ -1,6 +1,11 @@ -import { createMappedComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import {useEffect} from 'react' import { Vector3 } from 'three' +import { createMappedComponent, defineComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { SCENE_COMPONENT_MAP, _updateMap, serializeMap } from './MapFunctions' +import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' +import { useEntityContext } from '@etherealengine/engine/src/ecs/functions/EntityFunctions' + export type MapComponentType = { apiKey: string name?: string diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index e8aea1a..ed83c27 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -1,36 +1,43 @@ +import { debounce } from 'lodash' +import { Group, Mesh, Object3D } from 'three' +import { Text } from 'troika-three-text' + import { ComponentJson } from '@etherealengine/common/src/interfaces/SceneInterface' import { defaultAvatarHalfHeight } from '@etherealengine/engine/src/avatar/functions/spawnAvatarReceptor' +import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' // import { DebugNavMeshComponent } from '@etherealengine/engine/src/debug/DebugNavMeshComponent' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' import { EngineState } from '@etherealengine/engine/src/ecs/classes/EngineState' import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' -import { addComponent, defineQuery, getAllComponents, getComponent, hasComponent, setComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { + addComponent, + defineQuery, + getAllComponents, + getComponent, + hasComponent, + setComponent +} from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { GroupComponent, Object3DWithEntity } from '@etherealengine/engine/src/scene/components/GroupComponent' +import { SceneAssetPendingTagComponent } from '@etherealengine/engine/src/scene/components/SceneAssetPendingTagComponent' import { getState } from '@etherealengine/hyperflux' -import { debounce } from 'lodash' -import { Group, Mesh, Object3D } from 'three' -import { Text } from 'troika-three-text' - -import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' -import { MapComponent, MapComponentType } from './MapComponent' -import { MapAction, mapReducer } from './MapReceptor' import { getPhases, startPhases } from './functions/PhaseFunctions' import { getStartCoords } from './getStartCoords' -import { addChildFast, setPosition } from './util' import { NavMeshComponent } from './helpers/NavMeshComponent' -import { GroupComponent, Object3DWithEntity } from '@etherealengine/engine/src/scene/components/GroupComponent' -import { SceneAssetPendingTagComponent } from '@etherealengine/engine/src/scene/components/SceneAssetPendingTagComponent' +import { MapComponent, MapComponentType } from './MapComponent' +import { MapAction, mapReducer } from './MapReceptor' +import { addChildFast, setPosition } from './util' export const SCENE_COMPONENT_MAP = 'map' export const SCENE_COMPONENT_MAP_DEFAULT_VALUES = {} -export const deserializeMap = (entity: Entity, json: ComponentJson) => { +export const deserializeMap = (entity: Entity, json: ComponentJson) => { const sceneAssetPendingTagQuery = defineQuery([SceneAssetPendingTagComponent]) if (isClient) { - if(sceneAssetPendingTagQuery.length > 0) { + if (sceneAssetPendingTagQuery.length > 0) { createMap(entity, json.props as MapComponentType) } - + // if (getState(EngineState).isEditor) { // const components = getAllComponents(entity) // components.push(SCENE_COMPONENT_MAP) @@ -39,7 +46,7 @@ export const deserializeMap = (entity: Entity, json: ComponentJson { - if(getState(EngineState).isEditor && hasComponent(entity, MapComponent)) { + if (getState(EngineState).isEditor && hasComponent(entity, MapComponent)) { _updateMap(entity, args) return } @@ -99,13 +106,15 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { } export const _updateMap = async (entity: Entity, props: any) => { - // only update on some property changes - if(!( - Object.keys(props).includes('startLatitude') - || Object.keys(props).includes('startLongitude') - || Object.keys(props).includes('useDeviceGeolocation')) - ) return + if ( + !( + Object.keys(props).includes('startLatitude') || + Object.keys(props).includes('startLongitude') || + Object.keys(props).includes('useDeviceGeolocation') + ) + ) + return const args = getComponent(entity, MapComponent) const center = await getStartCoords(args) @@ -131,23 +140,23 @@ export const _updateMap = async (entity: Entity, props: any) => { } subScene.children = subSceneChildren } -export const updateMap = debounce((entity, args) => _updateMap(entity, args), 500) as any as (entity: Entity, props: any) => void +export const updateMap = debounce((entity, args) => _updateMap(entity, args), 500) as any as ( + entity: Entity, + props: any +) => void export const serializeMap = (entity: Entity) => { const mapComponent = getComponent(entity, MapComponent) return { - name: SCENE_COMPONENT_MAP, - props: { - apiKey: mapComponent.apiKey, - name: mapComponent.name, - scale: mapComponent.scale, - useTimeOfDay: mapComponent.useTimeOfDay, - useDirectionalShadows: mapComponent.useDirectionalShadows, - useDeviceGeolocation: mapComponent.useDeviceGeolocation, - startLatitude: mapComponent.startLatitude, - startLongitude: mapComponent.startLongitude, - showRasterTiles: mapComponent.showRasterTiles, - enableDebug: mapComponent.enableDebug - } + apiKey: mapComponent.apiKey, + name: mapComponent.name, + scale: mapComponent.scale, + useTimeOfDay: mapComponent.useTimeOfDay, + useDirectionalShadows: mapComponent.useDirectionalShadows, + useDeviceGeolocation: mapComponent.useDeviceGeolocation, + startLatitude: mapComponent.startLatitude, + startLongitude: mapComponent.startLongitude, + showRasterTiles: mapComponent.showRasterTiles, + enableDebug: mapComponent.enableDebug } -} \ No newline at end of file +} diff --git a/worldInjection.ts b/worldInjection.ts index 6bee02a..c019abf 100644 --- a/worldInjection.ts +++ b/worldInjection.ts @@ -1,16 +1,26 @@ -import { deserializeMap, SCENE_COMPONENT_MAP, SCENE_COMPONENT_MAP_DEFAULT_VALUES, serializeMap, updateMap } from './engine/MapFunctions' +import { useEffect } from 'react' +import { Vector3 } from 'three' + import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' -import { defineQuery, setComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' -import { SceneAssetPendingTagComponent } from '@etherealengine/engine/src/scene/components/SceneAssetPendingTagComponent' +import { + defineComponent, +} from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { useEntityContext } from '@etherealengine/engine/src/ecs/functions/EntityFunctions' import { defaultSpatialComponents } from '@etherealengine/engine/src/scene/systems/SceneObjectUpdateSystem' +import { + _updateMap, + SCENE_COMPONENT_MAP, + SCENE_COMPONENT_MAP_DEFAULT_VALUES, + serializeMap, +} from './engine/MapFunctions' + export const GEO_MAP = 'Geo Map' as const export default async () => { - - if(isClient) { - (await import('./editor/index')).default() + if (isClient) { + ;(await import('./editor/index')).default() } Engine.instance.scenePrefabRegistry.set(GEO_MAP, [ @@ -18,12 +28,48 @@ export default async () => { { name: SCENE_COMPONENT_MAP, props: SCENE_COMPONENT_MAP_DEFAULT_VALUES } ]) - const sceneAssetPendingTagQuery = defineQuery([SceneAssetPendingTagComponent]) - if(sceneAssetPendingTagQuery.length > 0) { - Engine.instance.sceneLoadingRegistry.set(SCENE_COMPONENT_MAP, { - deserialize: deserializeMap, - serialize: serializeMap, - update: updateMap - }) - } + defineComponent({ + name: 'EE_maps_scene_component', + jsonID: SCENE_COMPONENT_MAP, + onInit: () => ({ + apiKey: '', + name: '', + scale: new Vector3(), + style: {}, + useTimeOfDay: 0, + useDirectionalShadows: false, + useDeviceGeolocation: false, + startLatitude: '', + startLongitude: '', + showRasterTiles: false, + enableDebug: false + }), + onSet: (entity, component, json) => { + if (!json) return + // if(typeof json.apiKey === 'string' && json.apiKey !== component.apiKey.value) component.apiKey.set(json.apiKey) + // if(typeof json.name === 'string' && json.name !== component.) + component.apiKey.set(json.apiKey!) + component.name.set(json.name!) + component.scale.set(json.scale!) + component.style.set(json.style!) + component.useTimeOfDay.set(json.useTimeOfDay!) + component.useDirectionalShadows.set(json.useDirectionalShadows!) + component.useDeviceGeolocation.set(json.useDeviceGeolocation!) + component.startLatitude.set(json.startLatitude!) + component.startLongitude.set(json.startLongitude!) + component.showRasterTiles.set(json.showRasterTiles!) + component.enableDebug.set(json.enableDebug!) + }, + toJSON: (entity) => serializeMap(entity), + reactor: () => { + if (!isClient) return null + const entity = useEntityContext() + + useEffect(() => { + _updateMap(entity, {}) + }, [entity]) + + return null + } + }) } From b5d6a3624f22ba852bbe1553cb2979257b4b8f42 Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Sun, 18 Jun 2023 00:28:14 +0530 Subject: [PATCH 08/12] defineSystem and MapUpdateSystem --- editor/index.ts | 16 +- engine/MapComponent.ts | 80 +++++++-- engine/MapFunctions.ts | 51 +++--- engine/MapUpdateSystem.ts | 333 ++++++++++++++++++++------------------ worldInjection.ts | 72 ++------- 5 files changed, 284 insertions(+), 268 deletions(-) diff --git a/editor/index.ts b/editor/index.ts index 116bd50..8afbba1 100644 --- a/editor/index.ts +++ b/editor/index.ts @@ -1,13 +1,13 @@ +import { prefabIcons } from '@etherealengine/editor/src/functions/PrefabEditors' +import { startSystem } from '@etherealengine/engine/src/ecs/functions/SystemFunctions' -import { EntityNodeEditor, prefabIcons } from '@etherealengine/editor/src/functions/PrefabEditors' -import { MapNodeEditor } from './MapNodeEditor' import MapIcon from '@mui/icons-material/Map' -import { GEO_MAP } from '../worldInjection' -import MapUpdateSystem from '../engine/MapUpdateSystem' -EntityNodeEditor[GEO_MAP] = MapNodeEditor -prefabIcons[GEO_MAP] = MapIcon +import MapUpdateSystem from '../engine/MapUpdateSystem' +import { GEO_MAP } from '../worldInjection' export default async () => { - return await MapUpdateSystem() -} \ No newline at end of file + prefabIcons[GEO_MAP] = MapIcon + + startSystem(MapUpdateSystem, {}) +} diff --git a/engine/MapComponent.ts b/engine/MapComponent.ts index 2bfe916..e0eea33 100644 --- a/engine/MapComponent.ts +++ b/engine/MapComponent.ts @@ -1,23 +1,69 @@ -import {useEffect} from 'react' +import { useEffect } from 'react' import { Vector3 } from 'three' -import { createMappedComponent, defineComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' -import { SCENE_COMPONENT_MAP, _updateMap, serializeMap } from './MapFunctions' import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' +import { ComponentType, defineComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' import { useEntityContext } from '@etherealengine/engine/src/ecs/functions/EntityFunctions' -export type MapComponentType = { - apiKey: string - name?: string - scale?: Vector3 - style?: any - useTimeOfDay?: number - useDirectionalShadows?: boolean - useDeviceGeolocation?: boolean - startLatitude?: string - startLongitude?: string - showRasterTiles?: boolean - enableDebug?: boolean -} +import { _updateMap, deserializeMap, SCENE_COMPONENT_MAP } from './MapFunctions' -export const MapComponent = createMappedComponent('MapComponent') +export const MapComponent = defineComponent({ + name: 'EE_maps_scene_component', + jsonID: SCENE_COMPONENT_MAP, + onInit: (entity) => { + return { + apiKey: '', + name: '', + scale: new Vector3(), + style: {}, + useTimeOfDay: 0, + useDirectionalShadows: false, + useDeviceGeolocation: false, + startLatitude: '', + startLongitude: '', + showRasterTiles: false, + enableDebug: false + } + }, + onSet: (entity, component, json) => { + if (!json) return + component.apiKey.set(json.apiKey!) + component.name.set(json.name!) + component.scale.set(json.scale!) + component.style.set(json.style!) + component.useTimeOfDay.set(json.useTimeOfDay!) + component.useDirectionalShadows.set(json.useDirectionalShadows!) + component.useDeviceGeolocation.set(json.useDeviceGeolocation!) + component.startLatitude.set(json.startLatitude!) + component.startLongitude.set(json.startLongitude!) + component.showRasterTiles.set(json.showRasterTiles!) + component.enableDebug.set(json.enableDebug!) + deserializeMap(entity, component.value) + }, + toJSON: (entity, component) => { + return { + apiKey: component.apiKey, + name: component.name, + scale: component.scale, + useTimeOfDay: component.useTimeOfDay, + useDirectionalShadows: component.useDirectionalShadows, + useDeviceGeolocation: component.useDeviceGeolocation, + startLatitude: component.startLatitude, + startLongitude: component.startLongitude, + showRasterTiles: component.showRasterTiles, + enableDebug: component.enableDebug + } + }, + reactor: () => { + if (!isClient) return null + const entity = useEntityContext() + + useEffect(() => { + _updateMap(entity, {}) + }, [entity]) + + return null + } +}) + +export type MapComponentType = ComponentType diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index ed83c27..9fc9f16 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -11,6 +11,7 @@ import { EngineState } from '@etherealengine/engine/src/ecs/classes/EngineState' import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' import { addComponent, + ComponentType, defineQuery, getAllComponents, getComponent, @@ -32,11 +33,13 @@ export const SCENE_COMPONENT_MAP = 'map' export const SCENE_COMPONENT_MAP_DEFAULT_VALUES = {} export const deserializeMap = (entity: Entity, json: ComponentJson) => { + console.log('deserialize_map') const sceneAssetPendingTagQuery = defineQuery([SceneAssetPendingTagComponent]) + console.log('sceneassetpending', sceneAssetPendingTagQuery.length) if (isClient) { - if (sceneAssetPendingTagQuery.length > 0) { - createMap(entity, json.props as MapComponentType) - } + // if (sceneAssetPendingTagQuery.length > 0) { + createMap(entity, json.props as MapComponentType) + // } // if (getState(EngineState).isEditor) { // const components = getAllComponents(entity) @@ -46,12 +49,12 @@ export const deserializeMap = (entity: Entity, json: ComponentJson { + console.log('create_map_1') if (getState(EngineState).isEditor && hasComponent(entity, MapComponent)) { _updateMap(entity, args) return } // TODO: handle "navigator.geolocation.getCurrentPosition" rejection? - addComponent(entity, MapComponent, args) const center = await getStartCoords(args) @@ -66,6 +69,8 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { // addComponent(entity, DebugNavMeshComponent, { object3d: new Group() }) } + console.log('map_functions_create_map') + const state = mapReducer(null, MapAction.initialize(center, args.scale?.x)) // const spinnerGLTF = getState(EngineState).publicPath + '/projects/ee-maps/EarthLowPoly.glb' @@ -107,17 +112,22 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { export const _updateMap = async (entity: Entity, props: any) => { // only update on some property changes - if ( - !( - Object.keys(props).includes('startLatitude') || - Object.keys(props).includes('startLongitude') || - Object.keys(props).includes('useDeviceGeolocation') - ) - ) - return + console.log('props_update_map', Object.keys(props)) + + // if ( + // !( + // Object.keys(props).includes('startLatitude') || + // Object.keys(props).includes('startLongitude') || + // Object.keys(props).includes('useDeviceGeolocation') + // ) + // ) + // return + + console.log('_updatemap') const args = getComponent(entity, MapComponent) const center = await getStartCoords(args) + console.log('center->', center) const subSceneChildren = [] const subScene = this as unknown as Object3D @@ -140,23 +150,8 @@ export const _updateMap = async (entity: Entity, props: any) => { } subScene.children = subSceneChildren } + export const updateMap = debounce((entity, args) => _updateMap(entity, args), 500) as any as ( entity: Entity, props: any ) => void - -export const serializeMap = (entity: Entity) => { - const mapComponent = getComponent(entity, MapComponent) - return { - apiKey: mapComponent.apiKey, - name: mapComponent.name, - scale: mapComponent.scale, - useTimeOfDay: mapComponent.useTimeOfDay, - useDirectionalShadows: mapComponent.useDirectionalShadows, - useDeviceGeolocation: mapComponent.useDeviceGeolocation, - startLatitude: mapComponent.startLatitude, - startLongitude: mapComponent.startLongitude, - showRasterTiles: mapComponent.showRasterTiles, - enableDebug: mapComponent.enableDebug - } -} diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index 5f6f41e..945331c 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -1,19 +1,24 @@ -import { MapComponent } from './MapComponent' -import { TransformComponent } from '@etherealengine/engine/src/transform/components/TransformComponent' -import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctions' -import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util' +import { Downgraded } from '@hookstate/core' +import { useEffect } from 'react' import { Vector3 } from 'three' -import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' -import { getComponent, defineQuery, addComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' -import isIntersectCircleCircle from './functions/isIntersectCircleCircle' + import { AvatarComponent } from '@etherealengine/engine/src/avatar/components/AvatarComponent' -import { accessMapState } from './MapReceptor' -import { Downgraded } from '@hookstate/core' -import { getPhases, startPhases, resetPhases } from './functions/PhaseFunctions' import { TargetCameraRotationComponent } from '@etherealengine/engine/src/camera/components/TargetCameraRotationComponent' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' +import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity' +import { addComponent, defineQuery, getComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' +import { defineSystem } from '@etherealengine/engine/src/ecs/functions/SystemFunctions' import { GroupComponent } from '@etherealengine/engine/src/scene/components/GroupComponent' +import { TransformComponent } from '@etherealengine/engine/src/transform/components/TransformComponent' +import { getState } from '@etherealengine/hyperflux' + +import isIntersectCircleCircle from './functions/isIntersectCircleCircle' +import { getPhases, resetPhases, startPhases } from './functions/PhaseFunctions' +import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctions' import { NavMeshComponent } from './helpers/NavMeshComponent' +import { MapComponent } from './MapComponent' +import { accessMapState } from './MapReceptor' +import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util' const PI2 = Math.PI * 2 const $vector3 = new Vector3() @@ -23,166 +28,182 @@ const $normalScaleViewerPositionDelta = new Array(2) as [number, number] const $previousViewerPosition = new Vector3() const $previousMapCenterPoint: LongLat = Array(2) -export default async function MapUpdateSystem(): Promise { - const mapsQuery = defineQuery([MapComponent]) - const viewerQuery = defineQuery([AvatarComponent]) - const navMeshQuery = defineQuery([NavMeshComponent]) - const phases = await getPhases({ exclude: ['navigation'] }) - let previousViewerEntity: Entity - let spinnerAngle = 0 - - return () => { - const viewerEntity = viewerQuery()[0] - const mapEntities = mapsQuery() - const mapEntity = mapEntities[0] - const navPlaneEntity = navMeshQuery()[0] - // Sanity checks - if (!mapEntity || !viewerEntity) return - if (mapEntities.length > 1) console.warn('Not supported: More than one map!') - const mapState = accessMapState().attach(Downgraded).get() - const mapScale = mapState.scale - const object3dComponent = getComponent(mapEntity, GroupComponent) - const viewerTransform = getComponent(viewerEntity, TransformComponent) - const viewerPosition = vectorToArray(viewerTransform.position) - const viewerPositionScaled = multiplyArray(viewerPosition, 1 / mapScale) - const navigationRaycastTarget = getComponent(navPlaneEntity, NavMeshComponent).navTarget - const avatar = getComponent(viewerEntity, AvatarComponent) - - // Initialize on first pass or whenever the viewer changes - if (viewerEntity !== previousViewerEntity) { - $previousViewerPosition.copy(viewerTransform.position) - } +const reactor = () => { + useEffect(() => { + const run = async () => { + const phases = await getPhases({ exclude: ['navigation'] }) + const mapsQuery = defineQuery([MapComponent]) + const viewerQuery = defineQuery([AvatarComponent]) + const navMeshQuery = defineQuery([NavMeshComponent]) + + let previousViewerEntity: Entity | null = null + let spinnerAngle = 0 + + const viewerEntity = viewerQuery()[0] + const mapEntities = mapsQuery() + const mapEntity = mapEntities[0] + const navPlaneEntity = navMeshQuery()[0] + + // Sanity checks + if (!mapEntity || !viewerEntity) return + if (mapEntities.length > 1) console.warn('Not supported: More than one map!') + + console.log('reachere') + + const mapState = accessMapState().attach(Downgraded).get() + const mapScale = mapState.scale + const object3dComponent = getComponent(mapEntity, GroupComponent) + const viewerTransform = getComponent(viewerEntity, TransformComponent) + const viewerPosition = vectorToArray(viewerTransform.position) + const viewerPositionScaled = multiplyArray(viewerPosition, 1 / mapScale) + const navigationRaycastTarget = getComponent(navPlaneEntity, NavMeshComponent).navTarget + const avatar = getComponent(viewerEntity, AvatarComponent) + + // Initialize on first pass or whenever the viewer changes + if (viewerEntity !== previousViewerEntity) { + $previousViewerPosition.copy(viewerTransform.position) + } - // Find how far the viewer has travelled since last update, in real-world scale (scale=1) - // TODO only compare x, z components of positions - $vector3.subVectors(viewerTransform.position, $previousViewerPosition).divideScalar(mapScale) - vectorToArray($vector3, $normalScaleViewerPositionDelta) - const viewerDistanceFromCenterSquared = - $normalScaleViewerPositionDelta[0] * $normalScaleViewerPositionDelta[0] + - $normalScaleViewerPositionDelta[1] * $normalScaleViewerPositionDelta[1] - - const wasRefreshTriggered = - viewerDistanceFromCenterSquared >= mapState.triggerRefreshRadius * mapState.triggerRefreshRadius - const wasMapCenterUpdated = - typeof $previousMapCenterPoint[0] !== 'undefined' && - typeof $previousMapCenterPoint[1] !== 'undefined' && - ($previousMapCenterPoint[0] !== mapState.center[0] || $previousMapCenterPoint[1] !== mapState.center[1]) - - if (wasMapCenterUpdated) { - mapState.viewerPosition[0] = $previousViewerPosition[0] = 0 - mapState.viewerPosition[1] = $previousViewerPosition[1] = 0 - viewerTransform.position.set(0, 0, 0) - resetPhases(mapState, phases) - } + // Find how far the viewer has travelled since last update, in real-world scale (scale=1) + // TODO only compare x, z components of positions + $vector3.subVectors(viewerTransform.position, $previousViewerPosition).divideScalar(mapScale) + vectorToArray($vector3, $normalScaleViewerPositionDelta) + const viewerDistanceFromCenterSquared = + $normalScaleViewerPositionDelta[0] * $normalScaleViewerPositionDelta[0] + + $normalScaleViewerPositionDelta[1] * $normalScaleViewerPositionDelta[1] + + const wasRefreshTriggered = + viewerDistanceFromCenterSquared >= mapState.triggerRefreshRadius * mapState.triggerRefreshRadius + const wasMapCenterUpdated = + typeof $previousMapCenterPoint[0] !== 'undefined' && + typeof $previousMapCenterPoint[1] !== 'undefined' && + ($previousMapCenterPoint[0] !== mapState.center[0] || $previousMapCenterPoint[1] !== mapState.center[1]) + + if (wasMapCenterUpdated) { + mapState.viewerPosition[0] = $previousViewerPosition[0] = 0 + mapState.viewerPosition[1] = $previousViewerPosition[1] = 0 + viewerTransform.position.set(0, 0, 0) + resetPhases(mapState, phases) + } - if (wasRefreshTriggered || wasMapCenterUpdated) { - mapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, mapState.center) - mapState.viewerPosition = viewerPosition - startPhases(mapState, phases) + if (wasRefreshTriggered || wasMapCenterUpdated) { + mapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, mapState.center) + mapState.viewerPosition = viewerPosition + startPhases(mapState, phases) - $previousViewerPosition.copy(viewerTransform.position) - $previousViewerPosition.y = 0 - } + $previousViewerPosition.copy(viewerTransform.position) + $previousViewerPosition.y = 0 + } - $previousMapCenterPoint[0] = mapState.center[0] - $previousMapCenterPoint[1] = mapState.center[1] - - // Perf hack: Start with an empty array so that any children that have been purged or that do not meet the criteria for adding are implicitly removed. - if (mapState.updateSpinner && mapState.activePhase !== null && mapState.completeObjects.size === 0) { - const spinner = mapState.updateSpinner - spinner.rotation.y = spinnerAngle - spinnerAngle = (spinnerAngle + 0.01) % PI2 - - object3dComponent[0].children.length = 0 - navigationRaycastTarget.children.length = 0 - object3dComponent[0].children[0] = spinner - - object3dComponent[0].children[1] = mapState.updateTextContainer! - - avatar.model!.visible = false - addComponent(viewerEntity, TargetCameraRotationComponent, { - time: 0, - phi: 0, - theta: 0, - phiVelocity: { value: Math.PI }, - thetaVelocity: { value: Math.PI } - }) - } else if (mapState.activePhase === 'UpdateScene') { - avatar.model!.visible = true - object3dComponent[0].children.length = 0 - for (const key of mapState.completeObjects.keys()) { - const object = mapState.completeObjects.get(key) - if (object.mesh) { - if ( - isIntersectCircleCircle( - viewerPositionScaled, - mapState.minimumSceneRadius * mapState.scale, - object.centerPoint, - object.boundingCircleRadius - ) && - key[0] !== 'landuse_fallback' - ) { - setPosition(object.mesh, object.centerPoint) - addChildFast(object3dComponent[0], object.mesh) - } else { - object.mesh.parent = null + $previousMapCenterPoint[0] = mapState.center[0] + $previousMapCenterPoint[1] = mapState.center[1] + + // Perf hack: Start with an empty array so that any children that have been purged or that do not meet the criteria for adding are implicitly removed. + if (mapState.updateSpinner && mapState.activePhase !== null && mapState.completeObjects.size === 0) { + const spinner = mapState.updateSpinner + spinner.rotation.y = spinnerAngle + spinnerAngle = (spinnerAngle + 0.01) % PI2 + + object3dComponent[0].children.length = 0 + navigationRaycastTarget.children.length = 0 + object3dComponent[0].children[0] = spinner + + object3dComponent[0].children[1] = mapState.updateTextContainer! + + avatar.model!.visible = false + addComponent(viewerEntity, TargetCameraRotationComponent, { + time: 0, + phi: 0, + theta: 0, + phiVelocity: { value: Math.PI }, + thetaVelocity: { value: Math.PI } + }) + } else if (mapState.activePhase === 'UpdateScene') { + avatar.model!.visible = true + object3dComponent[0].children.length = 0 + for (const key of mapState.completeObjects.keys()) { + const object = mapState.completeObjects.get(key) + if (object.mesh) { + if ( + isIntersectCircleCircle( + viewerPositionScaled, + mapState.minimumSceneRadius * mapState.scale, + object.centerPoint, + object.boundingCircleRadius + ) && + key[0] !== 'landuse_fallback' + ) { + setPosition(object.mesh, object.centerPoint) + addChildFast(object3dComponent[0], object.mesh) + } else { + object.mesh.parent = null + } } } - } - for (const label of mapState.labelCache.values()) { - if (label.mesh) { - if ( - isIntersectCircleCircle( - viewerPositionScaled, - mapState.labelRadius * mapState.scale, - label.centerPoint, - label.boundingCircleRadius - ) - ) { - setPosition(label.mesh, label.centerPoint) - addChildFast(object3dComponent[0], label.mesh) - } else { - label.mesh.parent = null + for (const label of mapState.labelCache.values()) { + if (label.mesh) { + if ( + isIntersectCircleCircle( + viewerPositionScaled, + mapState.labelRadius * mapState.scale, + label.centerPoint, + label.boundingCircleRadius + ) + ) { + setPosition(label.mesh, label.centerPoint) + addChildFast(object3dComponent[0], label.mesh) + } else { + label.mesh.parent = null + } } } - } - // navigationRaycastTarget.children.length = 0 - for (const key of mapState.completeObjects.keys()) { - const layerName = key[0] - if (layerName === 'landuse_fallback') { - const { mesh, centerPoint } = mapState.completeObjects.get(key) - setPosition(mesh, centerPoint) - - addChildFast(navigationRaycastTarget, mesh) + // navigationRaycastTarget.children.length = 0 + for (const key of mapState.completeObjects.keys()) { + const layerName = key[0] + if (layerName === 'landuse_fallback') { + const { mesh, centerPoint } = mapState.completeObjects.get(key) + setPosition(mesh, centerPoint) + + addChildFast(navigationRaycastTarget, mesh) + } } - } - for (const helpers of mapState.helpersCache.values()) { - if (helpers.tileNavMesh) { - addChildFast(object3dComponent[0], helpers.tileNavMesh) + for (const helpers of mapState.helpersCache.values()) { + if (helpers.tileNavMesh) { + addChildFast(object3dComponent[0], helpers.tileNavMesh) + } } - } - // Update (sub)scene - mapState.activePhase = null - } + // Update (sub)scene + mapState.activePhase = null + } - // Update labels - if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) { - for (const label of mapState.labelCache.values()) { - if (label.mesh) { - if ( - isIntersectCircleCircle( - viewerPositionScaled, - mapState.labelRadius * mapState.scale, - label.centerPoint, - label.boundingCircleRadius - ) - ) { - label.mesh.update() + // Update labels + if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) { + for (const label of mapState.labelCache.values()) { + if (label.mesh) { + if ( + isIntersectCircleCircle( + viewerPositionScaled, + mapState.labelRadius * mapState.scale, + label.centerPoint, + label.boundingCircleRadius + ) + ) { + label.mesh.update() + } } } + previousViewerEntity = viewerEntity } } - previousViewerEntity = viewerEntity - } + run() + }, []) + return null } + +const MapUpdateSystem = defineSystem({ + uuid: 'ee.map.MapUpdateSystem', + reactor +}) + +export default MapUpdateSystem diff --git a/worldInjection.ts b/worldInjection.ts index c019abf..8eb6802 100644 --- a/worldInjection.ts +++ b/worldInjection.ts @@ -1,75 +1,29 @@ -import { useEffect } from 'react' -import { Vector3 } from 'three' - +import { prefabIcons } from '@etherealengine/editor/src/functions/PrefabEditors' +import { EntityNodeEditor } from '@etherealengine/editor/src/functions/PrefabEditors' import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine' -import { - defineComponent, -} from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' -import { useEntityContext } from '@etherealengine/engine/src/ecs/functions/EntityFunctions' +import { InputSystemGroup } from '@etherealengine/engine/src/ecs/functions/EngineFunctions' +import { startSystem } from '@etherealengine/engine/src/ecs/functions/SystemFunctions' import { defaultSpatialComponents } from '@etherealengine/engine/src/scene/systems/SceneObjectUpdateSystem' -import { - _updateMap, - SCENE_COMPONENT_MAP, - SCENE_COMPONENT_MAP_DEFAULT_VALUES, - serializeMap, -} from './engine/MapFunctions' +import MapIcon from '@mui/icons-material/Map' + +import { MapNodeEditor } from './editor/MapNodeEditor' +import { MapComponent } from './engine/MapComponent' +import { _updateMap, SCENE_COMPONENT_MAP, SCENE_COMPONENT_MAP_DEFAULT_VALUES } from './engine/MapFunctions' +import MapUpdateSystem from './engine/MapUpdateSystem' export const GEO_MAP = 'Geo Map' as const export default async () => { if (isClient) { - ;(await import('./editor/index')).default() + EntityNodeEditor.set(MapComponent, MapNodeEditor) + prefabIcons[GEO_MAP] = MapIcon + startSystem(MapUpdateSystem, { after: InputSystemGroup }) } Engine.instance.scenePrefabRegistry.set(GEO_MAP, [ ...defaultSpatialComponents, { name: SCENE_COMPONENT_MAP, props: SCENE_COMPONENT_MAP_DEFAULT_VALUES } ]) - - defineComponent({ - name: 'EE_maps_scene_component', - jsonID: SCENE_COMPONENT_MAP, - onInit: () => ({ - apiKey: '', - name: '', - scale: new Vector3(), - style: {}, - useTimeOfDay: 0, - useDirectionalShadows: false, - useDeviceGeolocation: false, - startLatitude: '', - startLongitude: '', - showRasterTiles: false, - enableDebug: false - }), - onSet: (entity, component, json) => { - if (!json) return - // if(typeof json.apiKey === 'string' && json.apiKey !== component.apiKey.value) component.apiKey.set(json.apiKey) - // if(typeof json.name === 'string' && json.name !== component.) - component.apiKey.set(json.apiKey!) - component.name.set(json.name!) - component.scale.set(json.scale!) - component.style.set(json.style!) - component.useTimeOfDay.set(json.useTimeOfDay!) - component.useDirectionalShadows.set(json.useDirectionalShadows!) - component.useDeviceGeolocation.set(json.useDeviceGeolocation!) - component.startLatitude.set(json.startLatitude!) - component.startLongitude.set(json.startLongitude!) - component.showRasterTiles.set(json.showRasterTiles!) - component.enableDebug.set(json.enableDebug!) - }, - toJSON: (entity) => serializeMap(entity), - reactor: () => { - if (!isClient) return null - const entity = useEntityContext() - - useEffect(() => { - _updateMap(entity, {}) - }, [entity]) - - return null - } - }) } From 8c96b4f8cb3e609b6334cc043fcc236ee5224500 Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:20:25 +0530 Subject: [PATCH 09/12] mapupdatesystem and phasesfunctions --- engine/MapUpdateSystem.ts | 327 ++++++++++++++--------------- engine/functions/PhaseFunctions.ts | 18 +- 2 files changed, 171 insertions(+), 174 deletions(-) diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index 945331c..6a415d2 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -1,5 +1,4 @@ import { Downgraded } from '@hookstate/core' -import { useEffect } from 'react' import { Vector3 } from 'three' import { AvatarComponent } from '@etherealengine/engine/src/avatar/components/AvatarComponent' @@ -10,7 +9,6 @@ import { addComponent, defineQuery, getComponent } from '@etherealengine/engine/ import { defineSystem } from '@etherealengine/engine/src/ecs/functions/SystemFunctions' import { GroupComponent } from '@etherealengine/engine/src/scene/components/GroupComponent' import { TransformComponent } from '@etherealengine/engine/src/transform/components/TransformComponent' -import { getState } from '@etherealengine/hyperflux' import isIntersectCircleCircle from './functions/isIntersectCircleCircle' import { getPhases, resetPhases, startPhases } from './functions/PhaseFunctions' @@ -18,6 +16,7 @@ import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctio import { NavMeshComponent } from './helpers/NavMeshComponent' import { MapComponent } from './MapComponent' import { accessMapState } from './MapReceptor' +import { IPhase } from './types' import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util' const PI2 = Math.PI * 2 @@ -28,182 +27,178 @@ const $normalScaleViewerPositionDelta = new Array(2) as [number, number] const $previousViewerPosition = new Vector3() const $previousMapCenterPoint: LongLat = Array(2) -const reactor = () => { - useEffect(() => { - const run = async () => { - const phases = await getPhases({ exclude: ['navigation'] }) - const mapsQuery = defineQuery([MapComponent]) - const viewerQuery = defineQuery([AvatarComponent]) - const navMeshQuery = defineQuery([NavMeshComponent]) - - let previousViewerEntity: Entity | null = null - let spinnerAngle = 0 - - const viewerEntity = viewerQuery()[0] - const mapEntities = mapsQuery() - const mapEntity = mapEntities[0] - const navPlaneEntity = navMeshQuery()[0] - - // Sanity checks - if (!mapEntity || !viewerEntity) return - if (mapEntities.length > 1) console.warn('Not supported: More than one map!') - - console.log('reachere') - - const mapState = accessMapState().attach(Downgraded).get() - const mapScale = mapState.scale - const object3dComponent = getComponent(mapEntity, GroupComponent) - const viewerTransform = getComponent(viewerEntity, TransformComponent) - const viewerPosition = vectorToArray(viewerTransform.position) - const viewerPositionScaled = multiplyArray(viewerPosition, 1 / mapScale) - const navigationRaycastTarget = getComponent(navPlaneEntity, NavMeshComponent).navTarget - const avatar = getComponent(viewerEntity, AvatarComponent) - - // Initialize on first pass or whenever the viewer changes - if (viewerEntity !== previousViewerEntity) { - $previousViewerPosition.copy(viewerTransform.position) +const mapsQuery = defineQuery([MapComponent]) +const viewerQuery = defineQuery([AvatarComponent]) +const navMeshQuery = defineQuery([NavMeshComponent]) + +let previousViewerEntity: Entity | null = null +let spinnerAngle = 0 + +let phases: readonly IPhase[] +getPhases({ exclude: ['navigation'] }).then((phases_) => (phases = phases_)) + +const execute = () => { + if (!phases) return + + const viewerEntity = viewerQuery()[0] + const mapEntities = mapsQuery() + const mapEntity = mapEntities[0] + const navPlaneEntity = navMeshQuery()[0] + + // Sanity checks + if (!mapEntity || !viewerEntity) return + if (mapEntities.length > 1) console.warn('Not supported: More than one map!') + + const mapState = accessMapState().attach(Downgraded).get() + const mapScale = mapState.scale + const object3dComponent = getComponent(mapEntity, GroupComponent) + const viewerTransform = getComponent(viewerEntity, TransformComponent) + const viewerPosition = vectorToArray(viewerTransform.position) + const viewerPositionScaled = multiplyArray(viewerPosition, 1 / mapScale) + const navigationRaycastTarget = getComponent(navPlaneEntity, NavMeshComponent).navTarget + const avatar = getComponent(viewerEntity, AvatarComponent) + + // Initialize on first pass or whenever the viewer changes + if (viewerEntity !== previousViewerEntity) { + $previousViewerPosition.copy(viewerTransform.position) + } + + // Find how far the viewer has travelled since last update, in real-world scale (scale=1) + // TODO only compare x, z components of positions + $vector3.subVectors(viewerTransform.position, $previousViewerPosition).divideScalar(mapScale) + vectorToArray($vector3, $normalScaleViewerPositionDelta) + const viewerDistanceFromCenterSquared = + $normalScaleViewerPositionDelta[0] * $normalScaleViewerPositionDelta[0] + + $normalScaleViewerPositionDelta[1] * $normalScaleViewerPositionDelta[1] + + const wasRefreshTriggered = + viewerDistanceFromCenterSquared >= mapState.triggerRefreshRadius * mapState.triggerRefreshRadius + const wasMapCenterUpdated = + typeof $previousMapCenterPoint[0] !== 'undefined' && + typeof $previousMapCenterPoint[1] !== 'undefined' && + ($previousMapCenterPoint[0] !== mapState.center[0] || $previousMapCenterPoint[1] !== mapState.center[1]) + + if (wasMapCenterUpdated) { + mapState.viewerPosition[0] = $previousViewerPosition[0] = 0 + mapState.viewerPosition[1] = $previousViewerPosition[1] = 0 + viewerTransform.position.set(0, 0, 0) + resetPhases(mapState, phases) + } + + if (wasRefreshTriggered || wasMapCenterUpdated) { + mapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, mapState.center) + mapState.viewerPosition = viewerPosition + startPhases(mapState, phases) + + $previousViewerPosition.copy(viewerTransform.position) + $previousViewerPosition.y = 0 + } + + $previousMapCenterPoint[0] = mapState.center[0] + $previousMapCenterPoint[1] = mapState.center[1] + + // Perf hack: Start with an empty array so that any children that have been purged or that do not meet the criteria for adding are implicitly removed. + if (mapState.updateSpinner && mapState.activePhase !== null && mapState.completeObjects.size === 0) { + const spinner = mapState.updateSpinner + spinner.rotation.y = spinnerAngle + spinnerAngle = (spinnerAngle + 0.01) % PI2 + + object3dComponent[0].children.length = 0 + navigationRaycastTarget.children.length = 0 + object3dComponent[0].children[0] = spinner + + object3dComponent[0].children[1] = mapState.updateTextContainer! + + avatar.model!.visible = false + addComponent(viewerEntity, TargetCameraRotationComponent, { + time: 0, + phi: 0, + theta: 0, + phiVelocity: { value: Math.PI }, + thetaVelocity: { value: Math.PI } + }) + } else if (mapState.activePhase === 'UpdateScene') { + avatar.model!.visible = true + object3dComponent[0].children.length = 0 + for (const key of mapState.completeObjects.keys()) { + const object = mapState.completeObjects.get(key) + if (object.mesh) { + if ( + isIntersectCircleCircle( + viewerPositionScaled, + mapState.minimumSceneRadius * mapState.scale, + object.centerPoint, + object.boundingCircleRadius + ) && + key[0] !== 'landuse_fallback' + ) { + setPosition(object.mesh, object.centerPoint) + addChildFast(object3dComponent[0], object.mesh) + } else { + object.mesh.parent = null + } } - - // Find how far the viewer has travelled since last update, in real-world scale (scale=1) - // TODO only compare x, z components of positions - $vector3.subVectors(viewerTransform.position, $previousViewerPosition).divideScalar(mapScale) - vectorToArray($vector3, $normalScaleViewerPositionDelta) - const viewerDistanceFromCenterSquared = - $normalScaleViewerPositionDelta[0] * $normalScaleViewerPositionDelta[0] + - $normalScaleViewerPositionDelta[1] * $normalScaleViewerPositionDelta[1] - - const wasRefreshTriggered = - viewerDistanceFromCenterSquared >= mapState.triggerRefreshRadius * mapState.triggerRefreshRadius - const wasMapCenterUpdated = - typeof $previousMapCenterPoint[0] !== 'undefined' && - typeof $previousMapCenterPoint[1] !== 'undefined' && - ($previousMapCenterPoint[0] !== mapState.center[0] || $previousMapCenterPoint[1] !== mapState.center[1]) - - if (wasMapCenterUpdated) { - mapState.viewerPosition[0] = $previousViewerPosition[0] = 0 - mapState.viewerPosition[1] = $previousViewerPosition[1] = 0 - viewerTransform.position.set(0, 0, 0) - resetPhases(mapState, phases) + } + for (const label of mapState.labelCache.values()) { + if (label.mesh) { + if ( + isIntersectCircleCircle( + viewerPositionScaled, + mapState.labelRadius * mapState.scale, + label.centerPoint, + label.boundingCircleRadius + ) + ) { + setPosition(label.mesh, label.centerPoint) + addChildFast(object3dComponent[0], label.mesh) + } else { + label.mesh.parent = null + } } - - if (wasRefreshTriggered || wasMapCenterUpdated) { - mapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, mapState.center) - mapState.viewerPosition = viewerPosition - startPhases(mapState, phases) - - $previousViewerPosition.copy(viewerTransform.position) - $previousViewerPosition.y = 0 + } + // navigationRaycastTarget.children.length = 0 + for (const key of mapState.completeObjects.keys()) { + const layerName = key[0] + if (layerName === 'landuse_fallback') { + const { mesh, centerPoint } = mapState.completeObjects.get(key) + setPosition(mesh, centerPoint) + + addChildFast(navigationRaycastTarget, mesh) } - - $previousMapCenterPoint[0] = mapState.center[0] - $previousMapCenterPoint[1] = mapState.center[1] - - // Perf hack: Start with an empty array so that any children that have been purged or that do not meet the criteria for adding are implicitly removed. - if (mapState.updateSpinner && mapState.activePhase !== null && mapState.completeObjects.size === 0) { - const spinner = mapState.updateSpinner - spinner.rotation.y = spinnerAngle - spinnerAngle = (spinnerAngle + 0.01) % PI2 - - object3dComponent[0].children.length = 0 - navigationRaycastTarget.children.length = 0 - object3dComponent[0].children[0] = spinner - - object3dComponent[0].children[1] = mapState.updateTextContainer! - - avatar.model!.visible = false - addComponent(viewerEntity, TargetCameraRotationComponent, { - time: 0, - phi: 0, - theta: 0, - phiVelocity: { value: Math.PI }, - thetaVelocity: { value: Math.PI } - }) - } else if (mapState.activePhase === 'UpdateScene') { - avatar.model!.visible = true - object3dComponent[0].children.length = 0 - for (const key of mapState.completeObjects.keys()) { - const object = mapState.completeObjects.get(key) - if (object.mesh) { - if ( - isIntersectCircleCircle( - viewerPositionScaled, - mapState.minimumSceneRadius * mapState.scale, - object.centerPoint, - object.boundingCircleRadius - ) && - key[0] !== 'landuse_fallback' - ) { - setPosition(object.mesh, object.centerPoint) - addChildFast(object3dComponent[0], object.mesh) - } else { - object.mesh.parent = null - } - } - } - for (const label of mapState.labelCache.values()) { - if (label.mesh) { - if ( - isIntersectCircleCircle( - viewerPositionScaled, - mapState.labelRadius * mapState.scale, - label.centerPoint, - label.boundingCircleRadius - ) - ) { - setPosition(label.mesh, label.centerPoint) - addChildFast(object3dComponent[0], label.mesh) - } else { - label.mesh.parent = null - } - } - } - // navigationRaycastTarget.children.length = 0 - for (const key of mapState.completeObjects.keys()) { - const layerName = key[0] - if (layerName === 'landuse_fallback') { - const { mesh, centerPoint } = mapState.completeObjects.get(key) - setPosition(mesh, centerPoint) - - addChildFast(navigationRaycastTarget, mesh) - } - } - for (const helpers of mapState.helpersCache.values()) { - if (helpers.tileNavMesh) { - addChildFast(object3dComponent[0], helpers.tileNavMesh) - } - } - - // Update (sub)scene - mapState.activePhase = null + } + for (const helpers of mapState.helpersCache.values()) { + if (helpers.tileNavMesh) { + addChildFast(object3dComponent[0], helpers.tileNavMesh) } + } - // Update labels - if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) { - for (const label of mapState.labelCache.values()) { - if (label.mesh) { - if ( - isIntersectCircleCircle( - viewerPositionScaled, - mapState.labelRadius * mapState.scale, - label.centerPoint, - label.boundingCircleRadius - ) - ) { - label.mesh.update() - } - } + // Update (sub)scene + mapState.activePhase = null + } + + // Update labels + if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) { + for (const label of mapState.labelCache.values()) { + if (label.mesh) { + if ( + isIntersectCircleCircle( + viewerPositionScaled, + mapState.labelRadius * mapState.scale, + label.centerPoint, + label.boundingCircleRadius + ) + ) { + label.mesh.update() } - previousViewerEntity = viewerEntity } } - run() - }, []) - return null + previousViewerEntity = viewerEntity + } } const MapUpdateSystem = defineSystem({ uuid: 'ee.map.MapUpdateSystem', - reactor + execute }) export default MapUpdateSystem diff --git a/engine/functions/PhaseFunctions.ts b/engine/functions/PhaseFunctions.ts index 83abfbe..ab2ccb5 100644 --- a/engine/functions/PhaseFunctions.ts +++ b/engine/functions/PhaseFunctions.ts @@ -1,4 +1,5 @@ import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' + import { TaskStatus } from '../types' import { ICachingPhase, IPhase, ISyncPhase, MapStateUnwrapped } from '../types' @@ -69,28 +70,29 @@ export async function startPhases(state: MapStateUnwrapped, phases: readonly IPh // TODO remove const results = [] as any[] let result: any + const newState = { ...state } for (const phase of phases) { // console.log("starting phase", phase.name) const keys = phase.getTaskKeys(state) if (phase.isCachingPhase || phase.isAsyncPhase) { - state.activePhase = phase.name + newState.activePhase = phase.name // TODO remove const promises = [] as Promise[] let promise: Promise for (const key of keys) { - const taskStatus = phase.getTaskStatus(state, key) + const taskStatus = phase.getTaskStatus(newState, key) // console.log(`task key: ${key} status: ${taskStatus === TaskStatus.STARTED ? 'started' : 'not started'}`) if (taskStatus === TaskStatus.NOT_STARTED) { // console.log("starting task for", phase.name) if (phase.isAsyncPhase) { - promise = phase.startTask(state, key) + promise = phase.startTask(newState, key) promises.push(promise) } else { - result = (phase as ICachingPhase).execTask(state, key) + result = (phase as ICachingPhase).execTask(newState, key) results.push(result) } - ;(phase as ICachingPhase).setTaskStatus(state, key, TaskStatus.STARTED) + ;(phase as ICachingPhase).setTaskStatus(newState, key, TaskStatus.STARTED) } } results.push(...(await Promise.all(promises))) @@ -98,12 +100,12 @@ export async function startPhases(state: MapStateUnwrapped, phases: readonly IPh for (const key of keys) { // console.log(`task key: ${key}`) // console.log("starting task", phase.name) - result = (phase as ISyncPhase).execTask(state, key) + result = (phase as ISyncPhase).execTask(newState, key) results.push(result) } } - phase.cleanup(state) + phase.cleanup(newState) } - state.activePhase = 'UpdateScene' + newState.activePhase = 'UpdateScene' return results } From a705e7522599fdacecd9bda621a74ae1f15d519a Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Mon, 26 Jun 2023 18:25:28 +0530 Subject: [PATCH 10/12] feat: update mapreceptor (as mapreceptor2) to use defineSystem --- engine/MapFunctions.ts | 25 ++++---- engine/MapReceptor2.ts | 130 ++++++++++++++++++++++++++++++++++++++ engine/MapUpdateSystem.ts | 65 ++++++++++--------- engine/types.ts | 8 ++- 4 files changed, 184 insertions(+), 44 deletions(-) create mode 100644 engine/MapReceptor2.ts diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index 9fc9f16..c924580 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -20,13 +20,13 @@ import { } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions' import { GroupComponent, Object3DWithEntity } from '@etherealengine/engine/src/scene/components/GroupComponent' import { SceneAssetPendingTagComponent } from '@etherealengine/engine/src/scene/components/SceneAssetPendingTagComponent' -import { getState } from '@etherealengine/hyperflux' +import { getMutableState, getState } from '@etherealengine/hyperflux' import { getPhases, startPhases } from './functions/PhaseFunctions' import { getStartCoords } from './getStartCoords' import { NavMeshComponent } from './helpers/NavMeshComponent' import { MapComponent, MapComponentType } from './MapComponent' -import { MapAction, mapReducer } from './MapReceptor' +import { MapState, MapStateService } from './MapReceptor2' import { addChildFast, setPosition } from './util' export const SCENE_COMPONENT_MAP = 'map' @@ -71,7 +71,9 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { console.log('map_functions_create_map') - const state = mapReducer(null, MapAction.initialize(center, args.scale?.x)) + MapStateService.initializeMap(center, args.scale?.x) + + const state = getMutableState(MapState) // const spinnerGLTF = getState(EngineState).publicPath + '/projects/ee-maps/EarthLowPoly.glb' // const spinner = spinnerGLTF as Mesh @@ -94,11 +96,10 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { updateTextContainer.sync() - state.updateTextContainer = updateTextContainer - - await startPhases(state, await getPhases({ exclude: ['navigation'] })) + const tempState = { ...state.value, updateTextContainer } + await startPhases(tempState, await getPhases({ exclude: ['navigation'] })) - navigationRaycastTarget.scale.setScalar(state.scale) + navigationRaycastTarget.scale.setScalar(state.scale.value) Engine.instance.scene.add(navigationRaycastTarget) addComponent(entity, NavMeshComponent, { @@ -112,7 +113,6 @@ export const createMap = async (entity: Entity, args: MapComponentType) => { export const _updateMap = async (entity: Entity, props: any) => { // only update on some property changes - console.log('props_update_map', Object.keys(props)) // if ( // !( @@ -131,17 +131,18 @@ export const _updateMap = async (entity: Entity, props: any) => { const subSceneChildren = [] const subScene = this as unknown as Object3D - const state = mapReducer(null, MapAction.initialize(center, args.scale?.x)) + MapStateService.initializeMap(center, args.scale?.x) + const state = getMutableState(MapState) - await startPhases(state, await getPhases({ exclude: ['navigation'] })) + await startPhases(state.value, await getPhases({ exclude: ['navigation'] })) - for (const object of state.completeObjects.values()) { + for (const object of state.completeObjects.value.values()) { if (object.mesh) { setPosition(object.mesh, object.centerPoint) addChildFast(subScene, object.mesh, subSceneChildren) } } - for (const object of state.labelCache.values()) { + for (const object of state.labelCache.value.values()) { if (object.mesh) { setPosition(object.mesh, object.centerPoint) addChildFast(subScene, object.mesh, subSceneChildren) diff --git a/engine/MapReceptor2.ts b/engine/MapReceptor2.ts new file mode 100644 index 0000000..a9507ff --- /dev/null +++ b/engine/MapReceptor2.ts @@ -0,0 +1,130 @@ +import { MultiPolygon } from 'polygon-clipping' +import { Mesh } from 'three' + +import { matches, Validator } from '@etherealengine/engine/src/common/functions/MatchesUtils' +import { defineAction, defineState, dispatchAction, getMutableState } from '@etherealengine/hyperflux' + +import FeatureCache from './classes/FeatureCache' +import HashMap from './classes/HashMap' +import HashSet from './classes/HashSet' +import MutableNavMesh from './classes/MutableNavMesh' +import TileCache from './classes/TileCache' +import { MAX_CACHED_FEATURES, MAX_CACHED_TILES } from './constants' +import { LongLat } from './functions/UnitConversionFunctions' +import { + FeatureKey, + MapDerivedFeatureComplete, + MapDerivedFeatureGeometry, + MapFeatureLabel, + MapHelpers, + MapTransformedFeature, + SupportedFeature, + TaskStatus, + Text3D, + TileKey, + VectorTile +} from './types' + +interface IMapInitializeAction { + centerPoint: LongLat + triggerRefreshRadius: number + minimumSceneRadius: number + scale: number +} + +export const MapState = defineState({ + name: 'EE_Map_State', + initial: () => ({ + center: [0, 0], + originalCenter: [0, 0], + viewerPosition: [0, 0], + triggerRefreshRadius: 160, + minimumSceneRadius: 800, + labelRadius: 400, + navMeshRadius: 400, + scale: 1, + fetchTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + tileCache: new TileCache(MAX_CACHED_TILES), + extractTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + featureCache: new FeatureCache(MAX_CACHED_FEATURES), + transformedFeatureTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + transformedFeatureCache: new FeatureCache(MAX_CACHED_FEATURES), + geometryTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + geometryCache: new FeatureCache(MAX_CACHED_FEATURES), + completeObjectsTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + completeObjects: new FeatureCache(MAX_CACHED_FEATURES), + labelTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + labelCache: new FeatureCache(MAX_CACHED_FEATURES), + tileNavMeshTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + tileNavMeshCache: new TileCache(MAX_CACHED_TILES), + helpersTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + helpersCache: new TileCache(MAX_CACHED_TILES), + tileMeta: new HashMap }>([], { + defaultValue: { cachedFeatureKeys: new HashSet() } + }), + featureMeta: new HashMap(), + navMesh: new MutableNavMesh(), + activePhase: null as null | string, + updateSpinner: null as null | Mesh, + updateTextContainer: null as null | Text3D + }) +}) + +// ACTIONS + +export class MapStateActions { + static initialize = defineAction({ + type: 'ee.maps.MapState.INITIALIZE' as const, + data: matches.object as Validator + }) + static setProperty = defineAction({ + type: 'ee.maps.MapState.SET_PROPERTY' as const, + data: matches.object as Validator> + }) +} + +// RECEPTORS + +const mapInitializeActionReceptor = (action: typeof MapStateActions.initialize.matches._TYPE) => { + const state = getMutableState(MapState) + return state.merge({ + center: action.data.centerPoint, + originalCenter: action.data.centerPoint, + triggerRefreshRadius: action.data.triggerRefreshRadius, + minimumSceneRadius: action.data.minimumSceneRadius, + labelRadius: action.data.minimumSceneRadius * 0.5, + navMeshRadius: action.data.minimumSceneRadius * 0.5, + scale: action.data.scale + }) +} + +const mapSetPropertyActionReceptor = (action: typeof MapStateActions.setProperty.matches._TYPE) => { + const state = getMutableState(MapState) + return state.merge(action.data) +} + +export const MapStateReceptor = { + mapInitializeActionReceptor, + mapSetPropertyActionReceptor +} + +// SERVICE + +export const MapStateService = { + initializeMap: (centerPoint: LongLat, scale = 1, triggerRefreshRadius = 40, minimumSceneRadius = 800) => + dispatchAction( + MapStateActions.initialize({ + data: { + centerPoint, + scale, + triggerRefreshRadius, + minimumSceneRadius + } + }) + ), + setProperty: (data: Partial) => { + dispatchAction(MapStateActions.setProperty({ data })) + } +} + +MapStateService.setProperty({}) diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index 6a415d2..c3b68c5 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -1,4 +1,3 @@ -import { Downgraded } from '@hookstate/core' import { Vector3 } from 'three' import { AvatarComponent } from '@etherealengine/engine/src/avatar/components/AvatarComponent' @@ -9,13 +8,14 @@ import { addComponent, defineQuery, getComponent } from '@etherealengine/engine/ import { defineSystem } from '@etherealengine/engine/src/ecs/functions/SystemFunctions' import { GroupComponent } from '@etherealengine/engine/src/scene/components/GroupComponent' import { TransformComponent } from '@etherealengine/engine/src/transform/components/TransformComponent' +import { defineActionQueue, getMutableState } from '@etherealengine/hyperflux' import isIntersectCircleCircle from './functions/isIntersectCircleCircle' import { getPhases, resetPhases, startPhases } from './functions/PhaseFunctions' import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctions' import { NavMeshComponent } from './helpers/NavMeshComponent' import { MapComponent } from './MapComponent' -import { accessMapState } from './MapReceptor' +import { MapState, MapStateActions, MapStateReceptor, MapStateService } from './MapReceptor2' import { IPhase } from './types' import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util' @@ -30,6 +30,8 @@ const $previousMapCenterPoint: LongLat = Array(2) const mapsQuery = defineQuery([MapComponent]) const viewerQuery = defineQuery([AvatarComponent]) const navMeshQuery = defineQuery([NavMeshComponent]) +const mapStateInitializeActionQueue = defineActionQueue(MapStateActions.initialize.matches) +const mapStateSetPropertyActionQueue = defineActionQueue(MapStateActions.setProperty.matches) let previousViewerEntity: Entity | null = null let spinnerAngle = 0 @@ -49,8 +51,12 @@ const execute = () => { if (!mapEntity || !viewerEntity) return if (mapEntities.length > 1) console.warn('Not supported: More than one map!') - const mapState = accessMapState().attach(Downgraded).get() - const mapScale = mapState.scale + // MAP STATE RECEPTORS + for (const action of mapStateInitializeActionQueue()) MapStateReceptor.mapInitializeActionReceptor(action) + for (const action of mapStateSetPropertyActionQueue()) MapStateReceptor.mapSetPropertyActionReceptor(action) + + const mapState = getMutableState(MapState) + const mapScale = mapState.scale.value const object3dComponent = getComponent(mapEntity, GroupComponent) const viewerTransform = getComponent(viewerEntity, TransformComponent) const viewerPosition = vectorToArray(viewerTransform.position) @@ -72,34 +78,35 @@ const execute = () => { $normalScaleViewerPositionDelta[1] * $normalScaleViewerPositionDelta[1] const wasRefreshTriggered = - viewerDistanceFromCenterSquared >= mapState.triggerRefreshRadius * mapState.triggerRefreshRadius + viewerDistanceFromCenterSquared >= mapState.triggerRefreshRadius.value * mapState.triggerRefreshRadius.value const wasMapCenterUpdated = typeof $previousMapCenterPoint[0] !== 'undefined' && typeof $previousMapCenterPoint[1] !== 'undefined' && - ($previousMapCenterPoint[0] !== mapState.center[0] || $previousMapCenterPoint[1] !== mapState.center[1]) + ($previousMapCenterPoint[0] !== mapState.center.value[0] || $previousMapCenterPoint[1] !== mapState.center.value[1]) if (wasMapCenterUpdated) { - mapState.viewerPosition[0] = $previousViewerPosition[0] = 0 - mapState.viewerPosition[1] = $previousViewerPosition[1] = 0 + mapState.viewerPosition.value[0] = $previousViewerPosition[0] = 0 + mapState.viewerPosition.value[1] = $previousViewerPosition[1] = 0 viewerTransform.position.set(0, 0, 0) - resetPhases(mapState, phases) + resetPhases(mapState.value, phases) } if (wasRefreshTriggered || wasMapCenterUpdated) { - mapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, mapState.center) - mapState.viewerPosition = viewerPosition - startPhases(mapState, phases) + const tempMapState = { ...mapState.value } + tempMapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, tempMapState.center) + tempMapState.viewerPosition = viewerPosition + startPhases(tempMapState, phases) $previousViewerPosition.copy(viewerTransform.position) $previousViewerPosition.y = 0 } - $previousMapCenterPoint[0] = mapState.center[0] - $previousMapCenterPoint[1] = mapState.center[1] + $previousMapCenterPoint[0] = mapState.center.value[0] + $previousMapCenterPoint[1] = mapState.center.value[1] // Perf hack: Start with an empty array so that any children that have been purged or that do not meet the criteria for adding are implicitly removed. - if (mapState.updateSpinner && mapState.activePhase !== null && mapState.completeObjects.size === 0) { - const spinner = mapState.updateSpinner + if (mapState.updateSpinner && mapState.activePhase !== null && mapState.completeObjects.value.size === 0) { + const spinner = mapState.updateSpinner.value! spinner.rotation.y = spinnerAngle spinnerAngle = (spinnerAngle + 0.01) % PI2 @@ -107,7 +114,7 @@ const execute = () => { navigationRaycastTarget.children.length = 0 object3dComponent[0].children[0] = spinner - object3dComponent[0].children[1] = mapState.updateTextContainer! + object3dComponent[0].children[1] = mapState.updateTextContainer.value! avatar.model!.visible = false addComponent(viewerEntity, TargetCameraRotationComponent, { @@ -117,16 +124,16 @@ const execute = () => { phiVelocity: { value: Math.PI }, thetaVelocity: { value: Math.PI } }) - } else if (mapState.activePhase === 'UpdateScene') { + } else if (mapState.activePhase.value === 'UpdateScene') { avatar.model!.visible = true object3dComponent[0].children.length = 0 - for (const key of mapState.completeObjects.keys()) { - const object = mapState.completeObjects.get(key) + for (const key of mapState.completeObjects.value.keys()) { + const object = mapState.completeObjects.value.get(key) if (object.mesh) { if ( isIntersectCircleCircle( viewerPositionScaled, - mapState.minimumSceneRadius * mapState.scale, + mapState.minimumSceneRadius.value * mapState.scale.value, object.centerPoint, object.boundingCircleRadius ) && @@ -139,12 +146,12 @@ const execute = () => { } } } - for (const label of mapState.labelCache.values()) { + for (const label of mapState.labelCache.value.values()) { if (label.mesh) { if ( isIntersectCircleCircle( viewerPositionScaled, - mapState.labelRadius * mapState.scale, + mapState.labelRadius.value * mapState.scale.value, label.centerPoint, label.boundingCircleRadius ) @@ -157,33 +164,33 @@ const execute = () => { } } // navigationRaycastTarget.children.length = 0 - for (const key of mapState.completeObjects.keys()) { + for (const key of mapState.completeObjects.value.keys()) { const layerName = key[0] if (layerName === 'landuse_fallback') { - const { mesh, centerPoint } = mapState.completeObjects.get(key) + const { mesh, centerPoint } = mapState.completeObjects.value.get(key) setPosition(mesh, centerPoint) addChildFast(navigationRaycastTarget, mesh) } } - for (const helpers of mapState.helpersCache.values()) { + for (const helpers of mapState.helpersCache.value.values()) { if (helpers.tileNavMesh) { addChildFast(object3dComponent[0], helpers.tileNavMesh) } } // Update (sub)scene - mapState.activePhase = null + MapStateService.setProperty({ activePhase: null }) } // Update labels if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) { - for (const label of mapState.labelCache.values()) { + for (const label of mapState.labelCache.value.values()) { if (label.mesh) { if ( isIntersectCircleCircle( viewerPositionScaled, - mapState.labelRadius * mapState.scale, + mapState.labelRadius.value * mapState.scale.value, label.centerPoint, label.boundingCircleRadius ) diff --git a/engine/types.ts b/engine/types.ts index 01898a2..c49478a 100644 --- a/engine/types.ts +++ b/engine/types.ts @@ -1,10 +1,12 @@ import { Feature, LineString, MultiLineString, MultiPolygon, Polygon } from 'geojson' import { BufferGeometry, InstancedBufferGeometry, Mesh } from 'three' -import { _MapStateUnwrapped } from './MapReceptor' +import type _FeatureKey from './classes/FeatureKey' import type _TileKey from './classes/TileKey' +import { MapState } from './MapReceptor2' + export type TileKey = _TileKey -import type _FeatureKey from './classes/FeatureKey' + export type FeatureKey = _FeatureKey export interface ITuple { @@ -33,7 +35,7 @@ export interface IParametricMap { size: number } -export type MapStateUnwrapped = _MapStateUnwrapped +export type MapStateUnwrapped = typeof MapState._TYPE /** * @fileoverview a place for all types that are shared by multiple modules but not conceptually owned by any From c62f898abe17d3e14c29c3b8bcf7b72c69a93015 Mon Sep 17 00:00:00 2001 From: aditya-mitra <55396651+aditya-mitra@users.noreply.github.com> Date: Mon, 26 Jun 2023 18:28:53 +0530 Subject: [PATCH 11/12] chore: rename mapreceptor2 to mapreceptor --- engine/MapFunctions.ts | 2 +- engine/MapReceptor.ts | 193 +++++++++++++++++++++----------------- engine/MapReceptor2.ts | 130 ------------------------- engine/MapUpdateSystem.ts | 2 +- engine/types.ts | 2 +- 5 files changed, 108 insertions(+), 221 deletions(-) delete mode 100644 engine/MapReceptor2.ts diff --git a/engine/MapFunctions.ts b/engine/MapFunctions.ts index c924580..3fc31a9 100755 --- a/engine/MapFunctions.ts +++ b/engine/MapFunctions.ts @@ -26,7 +26,7 @@ import { getPhases, startPhases } from './functions/PhaseFunctions' import { getStartCoords } from './getStartCoords' import { NavMeshComponent } from './helpers/NavMeshComponent' import { MapComponent, MapComponentType } from './MapComponent' -import { MapState, MapStateService } from './MapReceptor2' +import { MapState, MapStateService } from './MapReceptor' import { addChildFast, setPosition } from './util' export const SCENE_COMPONENT_MAP = 'map' diff --git a/engine/MapReceptor.ts b/engine/MapReceptor.ts index 79cf0f5..a9507ff 100644 --- a/engine/MapReceptor.ts +++ b/engine/MapReceptor.ts @@ -1,7 +1,18 @@ -import { createState, Downgraded } from '@hookstate/core' +import { MultiPolygon } from 'polygon-clipping' +import { Mesh } from 'three' + +import { matches, Validator } from '@etherealengine/engine/src/common/functions/MatchesUtils' +import { defineAction, defineState, dispatchAction, getMutableState } from '@etherealengine/hyperflux' + +import FeatureCache from './classes/FeatureCache' import HashMap from './classes/HashMap' +import HashSet from './classes/HashSet' +import MutableNavMesh from './classes/MutableNavMesh' import TileCache from './classes/TileCache' +import { MAX_CACHED_FEATURES, MAX_CACHED_TILES } from './constants' +import { LongLat } from './functions/UnitConversionFunctions' import { + FeatureKey, MapDerivedFeatureComplete, MapDerivedFeatureGeometry, MapFeatureLabel, @@ -9,105 +20,111 @@ import { MapTransformedFeature, SupportedFeature, TaskStatus, - VectorTile, + Text3D, TileKey, - FeatureKey, - Text3D + VectorTile } from './types' -import { MAX_CACHED_TILES, MAX_CACHED_FEATURES } from './constants' -import FeatureCache from './classes/FeatureCache' -import { MultiPolygon } from 'polygon-clipping' -import MutableNavMesh from './classes/MutableNavMesh' -import { LongLat } from './functions/UnitConversionFunctions' -import HashSet from './classes/HashSet' -import { isClient } from '@etherealengine/engine/src/common/functions/getEnvironment' -import { Mesh } from 'three' -const state = createState({ - center: [0, 0], - originalCenter: [0, 0], - viewerPosition: [0, 0], - triggerRefreshRadius: 160, - minimumSceneRadius: 800, - labelRadius: 400, - navMeshRadius: 400, - scale: 1, - fetchTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - tileCache: new TileCache(MAX_CACHED_TILES), - extractTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - featureCache: new FeatureCache(MAX_CACHED_FEATURES), - transformedFeatureTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - transformedFeatureCache: new FeatureCache(MAX_CACHED_FEATURES), - geometryTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - geometryCache: new FeatureCache(MAX_CACHED_FEATURES), - completeObjectsTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - completeObjects: new FeatureCache(MAX_CACHED_FEATURES), - labelTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - labelCache: new FeatureCache(MAX_CACHED_FEATURES), - tileNavMeshTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - tileNavMeshCache: new TileCache(MAX_CACHED_TILES), - helpersTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - helpersCache: new TileCache(MAX_CACHED_TILES), - tileMeta: new HashMap }>([], { - defaultValue: { cachedFeatureKeys: new HashSet() } - }), - featureMeta: new HashMap(), - navMesh: new MutableNavMesh(), - activePhase: null as null | string, - updateSpinner: null as null | Mesh, - updateTextContainer: null as null | Text3D +interface IMapInitializeAction { + centerPoint: LongLat + triggerRefreshRadius: number + minimumSceneRadius: number + scale: number +} + +export const MapState = defineState({ + name: 'EE_Map_State', + initial: () => ({ + center: [0, 0], + originalCenter: [0, 0], + viewerPosition: [0, 0], + triggerRefreshRadius: 160, + minimumSceneRadius: 800, + labelRadius: 400, + navMeshRadius: 400, + scale: 1, + fetchTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + tileCache: new TileCache(MAX_CACHED_TILES), + extractTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + featureCache: new FeatureCache(MAX_CACHED_FEATURES), + transformedFeatureTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + transformedFeatureCache: new FeatureCache(MAX_CACHED_FEATURES), + geometryTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + geometryCache: new FeatureCache(MAX_CACHED_FEATURES), + completeObjectsTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + completeObjects: new FeatureCache(MAX_CACHED_FEATURES), + labelTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + labelCache: new FeatureCache(MAX_CACHED_FEATURES), + tileNavMeshTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + tileNavMeshCache: new TileCache(MAX_CACHED_TILES), + helpersTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), + helpersCache: new TileCache(MAX_CACHED_TILES), + tileMeta: new HashMap }>([], { + defaultValue: { cachedFeatureKeys: new HashSet() } + }), + featureMeta: new HashMap(), + navMesh: new MutableNavMesh(), + activePhase: null as null | string, + updateSpinner: null as null | Mesh, + updateTextContainer: null as null | Text3D + }) }) -export type _MapStateUnwrapped = ReturnType +// ACTIONS -export const MapAction = { - initialize: (centerPoint: LongLat, scale = 1, triggerRefreshRadius = 40, minimumSceneRadius = 800) => { - return { - type: 'map.INITIALIZE' as const, - centerPoint, - triggerRefreshRadius, - minimumSceneRadius, - scale - } - }, - setCenterPoint: (centerPoint: LongLat) => { - return { - type: 'map.SET_CENTER_POINT' as const, - centerPoint - } - } +export class MapStateActions { + static initialize = defineAction({ + type: 'ee.maps.MapState.INITIALIZE' as const, + data: matches.object as Validator + }) + static setProperty = defineAction({ + type: 'ee.maps.MapState.SET_PROPERTY' as const, + data: matches.object as Validator> + }) } -export type MapActionType = ReturnType +// RECEPTORS -export const mapReducer = (_, action: MapActionType) => { - mapReceptor(action) - return state.attach(Downgraded).value +const mapInitializeActionReceptor = (action: typeof MapStateActions.initialize.matches._TYPE) => { + const state = getMutableState(MapState) + return state.merge({ + center: action.data.centerPoint, + originalCenter: action.data.centerPoint, + triggerRefreshRadius: action.data.triggerRefreshRadius, + minimumSceneRadius: action.data.minimumSceneRadius, + labelRadius: action.data.minimumSceneRadius * 0.5, + navMeshRadius: action.data.minimumSceneRadius * 0.5, + scale: action.data.scale + }) } -export const mapReceptor = (action: MapActionType) => { - switch(action.type) { - case 'map.INITIALIZE': return state.merge({ - center: action.centerPoint, - originalCenter: action.centerPoint, - triggerRefreshRadius: action.triggerRefreshRadius, - minimumSceneRadius: action.minimumSceneRadius, - labelRadius: action.minimumSceneRadius * 0.5, - navMeshRadius: action.minimumSceneRadius * 0.5, - scale: action.scale - }) - case 'map.SET_CENTER_POINT': - return state.merge({ - center: action.centerPoint, - originalCenter: action.centerPoint - }) - } +const mapSetPropertyActionReceptor = (action: typeof MapStateActions.setProperty.matches._TYPE) => { + const state = getMutableState(MapState) + return state.merge(action.data) +} + +export const MapStateReceptor = { + mapInitializeActionReceptor, + mapSetPropertyActionReceptor } -export const accessMapState = () => state +// SERVICE -if (process.env.APP_ENV === 'development' && isClient) { - ;(window as any).mapReceptor = mapReceptor - ;(window as any).MapAction = MapAction - ;(window as any).accessMapState = accessMapState +export const MapStateService = { + initializeMap: (centerPoint: LongLat, scale = 1, triggerRefreshRadius = 40, minimumSceneRadius = 800) => + dispatchAction( + MapStateActions.initialize({ + data: { + centerPoint, + scale, + triggerRefreshRadius, + minimumSceneRadius + } + }) + ), + setProperty: (data: Partial) => { + dispatchAction(MapStateActions.setProperty({ data })) + } } + +MapStateService.setProperty({}) diff --git a/engine/MapReceptor2.ts b/engine/MapReceptor2.ts deleted file mode 100644 index a9507ff..0000000 --- a/engine/MapReceptor2.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { MultiPolygon } from 'polygon-clipping' -import { Mesh } from 'three' - -import { matches, Validator } from '@etherealengine/engine/src/common/functions/MatchesUtils' -import { defineAction, defineState, dispatchAction, getMutableState } from '@etherealengine/hyperflux' - -import FeatureCache from './classes/FeatureCache' -import HashMap from './classes/HashMap' -import HashSet from './classes/HashSet' -import MutableNavMesh from './classes/MutableNavMesh' -import TileCache from './classes/TileCache' -import { MAX_CACHED_FEATURES, MAX_CACHED_TILES } from './constants' -import { LongLat } from './functions/UnitConversionFunctions' -import { - FeatureKey, - MapDerivedFeatureComplete, - MapDerivedFeatureGeometry, - MapFeatureLabel, - MapHelpers, - MapTransformedFeature, - SupportedFeature, - TaskStatus, - Text3D, - TileKey, - VectorTile -} from './types' - -interface IMapInitializeAction { - centerPoint: LongLat - triggerRefreshRadius: number - minimumSceneRadius: number - scale: number -} - -export const MapState = defineState({ - name: 'EE_Map_State', - initial: () => ({ - center: [0, 0], - originalCenter: [0, 0], - viewerPosition: [0, 0], - triggerRefreshRadius: 160, - minimumSceneRadius: 800, - labelRadius: 400, - navMeshRadius: 400, - scale: 1, - fetchTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - tileCache: new TileCache(MAX_CACHED_TILES), - extractTilesTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - featureCache: new FeatureCache(MAX_CACHED_FEATURES), - transformedFeatureTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - transformedFeatureCache: new FeatureCache(MAX_CACHED_FEATURES), - geometryTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - geometryCache: new FeatureCache(MAX_CACHED_FEATURES), - completeObjectsTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - completeObjects: new FeatureCache(MAX_CACHED_FEATURES), - labelTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - labelCache: new FeatureCache(MAX_CACHED_FEATURES), - tileNavMeshTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - tileNavMeshCache: new TileCache(MAX_CACHED_TILES), - helpersTasks: new HashMap([], { defaultValue: TaskStatus.NOT_STARTED }), - helpersCache: new TileCache(MAX_CACHED_TILES), - tileMeta: new HashMap }>([], { - defaultValue: { cachedFeatureKeys: new HashSet() } - }), - featureMeta: new HashMap(), - navMesh: new MutableNavMesh(), - activePhase: null as null | string, - updateSpinner: null as null | Mesh, - updateTextContainer: null as null | Text3D - }) -}) - -// ACTIONS - -export class MapStateActions { - static initialize = defineAction({ - type: 'ee.maps.MapState.INITIALIZE' as const, - data: matches.object as Validator - }) - static setProperty = defineAction({ - type: 'ee.maps.MapState.SET_PROPERTY' as const, - data: matches.object as Validator> - }) -} - -// RECEPTORS - -const mapInitializeActionReceptor = (action: typeof MapStateActions.initialize.matches._TYPE) => { - const state = getMutableState(MapState) - return state.merge({ - center: action.data.centerPoint, - originalCenter: action.data.centerPoint, - triggerRefreshRadius: action.data.triggerRefreshRadius, - minimumSceneRadius: action.data.minimumSceneRadius, - labelRadius: action.data.minimumSceneRadius * 0.5, - navMeshRadius: action.data.minimumSceneRadius * 0.5, - scale: action.data.scale - }) -} - -const mapSetPropertyActionReceptor = (action: typeof MapStateActions.setProperty.matches._TYPE) => { - const state = getMutableState(MapState) - return state.merge(action.data) -} - -export const MapStateReceptor = { - mapInitializeActionReceptor, - mapSetPropertyActionReceptor -} - -// SERVICE - -export const MapStateService = { - initializeMap: (centerPoint: LongLat, scale = 1, triggerRefreshRadius = 40, minimumSceneRadius = 800) => - dispatchAction( - MapStateActions.initialize({ - data: { - centerPoint, - scale, - triggerRefreshRadius, - minimumSceneRadius - } - }) - ), - setProperty: (data: Partial) => { - dispatchAction(MapStateActions.setProperty({ data })) - } -} - -MapStateService.setProperty({}) diff --git a/engine/MapUpdateSystem.ts b/engine/MapUpdateSystem.ts index c3b68c5..ec90f5a 100644 --- a/engine/MapUpdateSystem.ts +++ b/engine/MapUpdateSystem.ts @@ -15,7 +15,7 @@ import { getPhases, resetPhases, startPhases } from './functions/PhaseFunctions' import { fromMetersFromCenter, LongLat } from './functions/UnitConversionFunctions' import { NavMeshComponent } from './helpers/NavMeshComponent' import { MapComponent } from './MapComponent' -import { MapState, MapStateActions, MapStateReceptor, MapStateService } from './MapReceptor2' +import { MapState, MapStateActions, MapStateReceptor, MapStateService } from './MapReceptor' import { IPhase } from './types' import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util' diff --git a/engine/types.ts b/engine/types.ts index c49478a..b77541c 100644 --- a/engine/types.ts +++ b/engine/types.ts @@ -3,7 +3,7 @@ import { BufferGeometry, InstancedBufferGeometry, Mesh } from 'three' import type _FeatureKey from './classes/FeatureKey' import type _TileKey from './classes/TileKey' -import { MapState } from './MapReceptor2' +import { MapState } from './MapReceptor' export type TileKey = _TileKey From 7dc1709526d23d8022b1ef7fd219f9b339f5cdb7 Mon Sep 17 00:00:00 2001 From: Mrigesh Thakur Date: Tue, 27 Jun 2023 06:36:22 +0000 Subject: [PATCH 12/12] chore: added debug statements in functions and phases --- engine/functions/PhaseFunctions.ts | 3 +++ engine/functions/checkKey.ts | 1 + engine/functions/computePolygonDifference.ts | 1 + engine/functions/computeSquaredDistanceFromCircle.ts | 2 ++ engine/functions/computeTileBoundingBox.ts | 1 + engine/functions/createCompleteObject.ts | 1 + engine/functions/createFeatureLabel.ts | 1 + engine/functions/createGeometry.ts | 1 + engine/functions/createIntersectionTestTileCircle.ts | 2 ++ engine/functions/createSurroundingTileIterator.ts | 1 + engine/functions/createUsingCache.ts | 1 + engine/functions/createUsingGetSet.ts | 1 + engine/functions/createWorkerFunction.ts | 2 +- engine/functions/fetchUsingCache.ts | 1 + engine/functions/fetchVectorTile.ts | 2 +- engine/functions/findSplitFeatures.ts | 2 ++ engine/functions/getCachedMaterial.ts | 1 + engine/functions/getFeaturesFromVectorTileLayer.ts | 1 + engine/functions/getMapboxUrl.ts | 3 ++- engine/functions/isIntersectCircleCircle.ts | 1 + engine/functions/tesselatePolygon.ts | 1 + engine/functions/transformFeature.ts | 1 + engine/functions/transformGeometry.ts | 1 + engine/functions/unifyCachedFeatures.ts | 1 + engine/functions/unifyFeatures.ts | 1 + engine/phases/CreateCompleteNavMeshPhase.ts | 2 ++ engine/phases/CreateCompleteObjectPhase.ts | 4 ++++ engine/phases/CreateFallbackLanduseMeshPhase.ts | 2 ++ engine/phases/CreateGeometryPhase.ts | 3 +++ engine/phases/CreateHelpersPhase.ts | 3 +++ engine/phases/CreateLabelPhase.ts | 2 ++ engine/phases/CreateTileNavMeshPhase.ts | 2 ++ engine/phases/ExtractTileFeaturesPhase.ts | 2 ++ engine/phases/FetchTilesPhase.ts | 2 ++ engine/phases/TransformFeaturePhase.ts | 2 ++ engine/phases/UnifyFeaturesPhase.ts | 2 ++ 36 files changed, 57 insertions(+), 3 deletions(-) diff --git a/engine/functions/PhaseFunctions.ts b/engine/functions/PhaseFunctions.ts index ab2ccb5..18200e2 100644 --- a/engine/functions/PhaseFunctions.ts +++ b/engine/functions/PhaseFunctions.ts @@ -56,11 +56,13 @@ Object.freeze(defaultPhases) Object.freeze(phasesNoNavigation) export async function getPhases(options: { exclude?: FeatureId[] } = {}): Promise[]> { + console.log('GETPHASES-PHASES-CALLED--->') const exclude = options.exclude || [] return Promise.all(exclude.includes('navigation') ? phasesNoNavigation : defaultPhases) } export function resetPhases(state: MapStateUnwrapped, phases: readonly IPhase[]) { + console.log('RESET-PHASES-CALLED--->') for (const phase of phases) { phase.reset(state) } @@ -68,6 +70,7 @@ export function resetPhases(state: MapStateUnwrapped, phases: readonly IPhase[]) { // TODO remove + console.log('START-PHASES-CALLED--->') const results = [] as any[] let result: any const newState = { ...state } diff --git a/engine/functions/checkKey.ts b/engine/functions/checkKey.ts index 7a86a4f..9822889 100644 --- a/engine/functions/checkKey.ts +++ b/engine/functions/checkKey.ts @@ -1,6 +1,7 @@ import matches from 'ts-matches' import { FeatureKey, TileKey } from '../types' export default function checkKey(key: FeatureKey | TileKey) { + console.log("CHECKKEY__FN") matches(key) .when(matches.tuple(matches.number, matches.number), () => {}) .when(matches.tuple(matches.string, matches.number, matches.number, matches.string), () => {}) diff --git a/engine/functions/computePolygonDifference.ts b/engine/functions/computePolygonDifference.ts index c12d29d..39dee1c 100644 --- a/engine/functions/computePolygonDifference.ts +++ b/engine/functions/computePolygonDifference.ts @@ -14,6 +14,7 @@ function roundEach(array: any[]) { } export default function computePolygonDifference(subjectGeometry: Polygon, ...clippingGeometries: Polygon[]) { + console.log("COMPUTEPOLYGONDIFF__FN") // Quick and dirty fix for polygon-clipping's floating point woes roundEach(clippingGeometries) return pc.difference([subjectGeometry], ...clippingGeometries) diff --git a/engine/functions/computeSquaredDistanceFromCircle.ts b/engine/functions/computeSquaredDistanceFromCircle.ts index 525fef1..be37132 100644 --- a/engine/functions/computeSquaredDistanceFromCircle.ts +++ b/engine/functions/computeSquaredDistanceFromCircle.ts @@ -1,7 +1,9 @@ export default function computeDistanceFromCircle( + point: [number, number], circleCenter: [number, number], circleRadius: number ) { + console.log("COMPUTEPSQUAREDIST__FN"); return Math.hypot(point[0] - circleCenter[0], point[1] - circleCenter[1]) - circleRadius } diff --git a/engine/functions/computeTileBoundingBox.ts b/engine/functions/computeTileBoundingBox.ts index 2e8a698..9f8e0e1 100644 --- a/engine/functions/computeTileBoundingBox.ts +++ b/engine/functions/computeTileBoundingBox.ts @@ -10,6 +10,7 @@ export default function computeTileBoundingBox( center: LongLat, target: BBox = Array(4) as any ): BBox { + console.log("COMPUTETILEBOUNDING__FN"); toMetersFromCenter([tileXToLong(x, TILE_ZOOM), tileYToLat(y, TILE_ZOOM)], center, $array2) const [x1, y1] = $array2 diff --git a/engine/functions/createCompleteObject.ts b/engine/functions/createCompleteObject.ts index 168f0b2..3a43b38 100644 --- a/engine/functions/createCompleteObject.ts +++ b/engine/functions/createCompleteObject.ts @@ -8,6 +8,7 @@ export default function createCompleteObject( geometryPhaseResult: MapDerivedFeatureGeometry, feature: SupportedFeature ): MapDerivedFeatureComplete { + console.log("CREATECOMPLETEOBJECT__FN"); const { color, extrude, zIndex = 0 } = getFeatureStyles(DEFAULT_FEATURE_STYLES, layerName, feature.properties.class) const materialParams = { diff --git a/engine/functions/createFeatureLabel.ts b/engine/functions/createFeatureLabel.ts index 807ae3b..5aa2a3f 100644 --- a/engine/functions/createFeatureLabel.ts +++ b/engine/functions/createFeatureLabel.ts @@ -64,6 +64,7 @@ export default function createFeatureLabel( lineString: Feature, mapCenterPoint: LongLat ): MapFeatureLabel { + console.log("CREATEFEATURELABEL__FN"); const lineLen = turf.length(lineString) const middleSlice = turf.lineSliceAlong(lineString, lineLen * 0.48, lineLen * 0.52).geometry.coordinates diff --git a/engine/functions/createGeometry.ts b/engine/functions/createGeometry.ts index 2e11df4..f1c5721 100644 --- a/engine/functions/createGeometry.ts +++ b/engine/functions/createGeometry.ts @@ -43,6 +43,7 @@ function colorVertices(geometry: BufferGeometry, baseColor: Color, light: Color, } export default function createGeometry(feature: SupportedFeature, style: IStyles): BufferGeometry { + console.log("CREATEGEOMETRY__FN"); const shape = new Shape() let coords: LongLat[] diff --git a/engine/functions/createIntersectionTestTileCircle.ts b/engine/functions/createIntersectionTestTileCircle.ts index cc83038..88699a1 100644 --- a/engine/functions/createIntersectionTestTileCircle.ts +++ b/engine/functions/createIntersectionTestTileCircle.ts @@ -1,5 +1,7 @@ export default function createIntersectTestTileCircle(centerX: number, centerY: number, radius: number) { + console.log("CREATEINTERESECT__FN"); return function isIntersectTileCircle(cellX: number, cellY: number): boolean { + const testEdgeX = centerX < cellX ? cellX : centerX > cellX + 1 ? cellX + 1 : centerX const testEdgeY = centerY < cellY ? cellY : centerY > cellY + 1 ? cellY + 1 : centerY const distanceFromCenter = Math.hypot(testEdgeX - centerX, testEdgeY - centerY) diff --git a/engine/functions/createSurroundingTileIterator.ts b/engine/functions/createSurroundingTileIterator.ts index 4b87465..5e2693b 100644 --- a/engine/functions/createSurroundingTileIterator.ts +++ b/engine/functions/createSurroundingTileIterator.ts @@ -12,6 +12,7 @@ export default function* createSurroundingTileIterator( minimumSceneRadius: number, zoomLevel: number ): Generator { + console.log("CREATESURROUNDING__FN"); const [startLong, startLat] = fromMetersFromCenter([-minimumSceneRadius, -minimumSceneRadius], center) const [endLong, endLat] = fromMetersFromCenter([minimumSceneRadius, minimumSceneRadius], center) diff --git a/engine/functions/createUsingCache.ts b/engine/functions/createUsingCache.ts index 59c0ed2..2967b72 100644 --- a/engine/functions/createUsingCache.ts +++ b/engine/functions/createUsingCache.ts @@ -4,6 +4,7 @@ import createUsingGetSet from './createUsingGetSet' export default function createUsingCache( create: (state: MapStateUnwrapped, key: CacheKey, ...extraArgs: any[]) => Value ) { + console.log("CREATEUSINGCACHE__FN"); const _createUsingCache = createUsingGetSet(create) return (cache: IParametricMap, state: MapStateUnwrapped, key: CacheKey, ...extraArgs: any[]) => { return _createUsingCache(cache.get.bind(cache), cache.set.bind(cache), state, key, ...extraArgs) diff --git a/engine/functions/createUsingGetSet.ts b/engine/functions/createUsingGetSet.ts index 7f4fd28..9087420 100644 --- a/engine/functions/createUsingGetSet.ts +++ b/engine/functions/createUsingGetSet.ts @@ -3,6 +3,7 @@ import { ITuple, MapStateUnwrapped } from '../types' export default function createUsingGetSet( create: (state: MapStateUnwrapped, key: CacheKey, ...args: any[]) => Value ) { + console.log("CREATEUSINGGETSET__FN"); return ( get: (key: CacheKey) => Value, set: (key: CacheKey, value: Value) => any, diff --git a/engine/functions/createWorkerFunction.ts b/engine/functions/createWorkerFunction.ts index f5cf6fb..8cdf1d4 100644 --- a/engine/functions/createWorkerFunction.ts +++ b/engine/functions/createWorkerFunction.ts @@ -8,7 +8,7 @@ export default function createWorkerFunction< worker: Worker ): (...args: { [I in keyof HandlerArgs]: Comlink.UnproxyOrClone }) => Promise { const api = Comlink.wrap(worker) - + console.log("CREATEWORKER__FN"); return async function workerFunction(...args: { [I in keyof HandlerArgs]: Comlink.UnproxyOrClone }) { return (await api.handle(...args)) as Promise } diff --git a/engine/functions/fetchUsingCache.ts b/engine/functions/fetchUsingCache.ts index 8120d35..ca33424 100644 --- a/engine/functions/fetchUsingCache.ts +++ b/engine/functions/fetchUsingCache.ts @@ -5,6 +5,7 @@ import createUsingGetSet from './createUsingGetSet' export default function fetchUsingCache( fetch: (state: MapStateUnwrapped, key: CacheKey, ...args: any[]) => Value ) { + console.log("FETCHCACHE__FN"); const _fetchUsingCache = createUsingGetSet(fetch) return async ( cache: ParametricCache, diff --git a/engine/functions/fetchVectorTile.ts b/engine/functions/fetchVectorTile.ts index 587b0e8..2813512 100644 --- a/engine/functions/fetchVectorTile.ts +++ b/engine/functions/fetchVectorTile.ts @@ -4,7 +4,7 @@ import { VectorTile } from '../types' import { vectors } from '../vectors' import getMapboxUrl from './getMapboxUrl' -export default async function fetchVectorTile(_: any, key: TileKey): Promise { +export default async function fetchVectorTile(_: any, key: TileKey): Promise { console.log("GETCHVECTOR__FN"); const [x, y] = key const url = getMapboxUrl( 'mapbox.mapbox-streets-v8', diff --git a/engine/functions/findSplitFeatures.ts b/engine/functions/findSplitFeatures.ts index eb8ba48..a94d56f 100644 --- a/engine/functions/findSplitFeatures.ts +++ b/engine/functions/findSplitFeatures.ts @@ -7,7 +7,9 @@ type GroupKey = Feature['id'] type Group = [FeatureKey, Feature][] /** Useful for when a feature is split across multiple vector tiles */ + export default function* findSplitFeatures(keys: Iterator, features: Iterator): Generator { + console.log("FINDSPLIT__FN"); const zipped = zipIterators<[FeatureKey, Feature]>(keys, features) const groups = new Map() const groupSetFunction = (groupKey: GroupKey, groupValue: Group) => { diff --git a/engine/functions/getCachedMaterial.ts b/engine/functions/getCachedMaterial.ts index b9942f0..4f04f9e 100644 --- a/engine/functions/getCachedMaterial.ts +++ b/engine/functions/getCachedMaterial.ts @@ -6,6 +6,7 @@ const cache = new Map() // TODO re-implement using createUsingGetSet // TODO generalize this so it'll work even if params contain Textures export default function getCachedMaterial(Material: any, params: MeshLambertMaterialParameters): MeshLambertMaterial { + console.log("GETCACHED__FN"); const key = JSON.stringify(params) let material = cache.get(key) diff --git a/engine/functions/getFeaturesFromVectorTileLayer.ts b/engine/functions/getFeaturesFromVectorTileLayer.ts index 14272bf..1e89bcb 100644 --- a/engine/functions/getFeaturesFromVectorTileLayer.ts +++ b/engine/functions/getFeaturesFromVectorTileLayer.ts @@ -8,6 +8,7 @@ export default function* getFeaturesFromVectorTileLayer( y: number, zoom: number ): Generator { + console.log("GETFEATURES__FN"); const layer = tile.layers[layerName] for (let tileIndex = 0; tileIndex < layer.length; tileIndex++) { const feature = layer.feature(tileIndex).toGeoJSON(x, y, zoom) diff --git a/engine/functions/getMapboxUrl.ts b/engine/functions/getMapboxUrl.ts index c8209a4..191e1f3 100644 --- a/engine/functions/getMapboxUrl.ts +++ b/engine/functions/getMapboxUrl.ts @@ -7,9 +7,10 @@ export default function getMapboxUrl( tileY: number, tileZoom: number, format: string, - apiKey: string, + apiKey: "", highDpi = false ) { + console.log("GETMAPBOX__FN"); return `https://api.mapbox.com/v4/${layerId}/${tileZoom}/${tileX}/${tileY}${ highDpi ? '@2x' : '' }.${format}?access_token=${apiKey}` diff --git a/engine/functions/isIntersectCircleCircle.ts b/engine/functions/isIntersectCircleCircle.ts index d2d5523..d250104 100644 --- a/engine/functions/isIntersectCircleCircle.ts +++ b/engine/functions/isIntersectCircleCircle.ts @@ -6,6 +6,7 @@ export default function isIntersectCircleCircle( centerPointB: [number, number], radiusB: number ): boolean { + console.log("ISINTERSECT__FN"); const distanceSquared = computeSquared(centerPointA, centerPointB, radiusB) return distanceSquared < radiusA * radiusA } diff --git a/engine/functions/tesselatePolygon.ts b/engine/functions/tesselatePolygon.ts index 3d3bb94..2a031ea 100644 --- a/engine/functions/tesselatePolygon.ts +++ b/engine/functions/tesselatePolygon.ts @@ -19,6 +19,7 @@ export function indexedVerticesToGeoJSONTriangles(indexes: number[], vertices: n } export default function tesselatePolygon(polygon: Polygon) { + console.log("tesselatePolygon__FN"); const { vertices, holes } = earcut.flatten(polygon) const indexes = earcut(vertices, holes, 2) return indexedVerticesToGeoJSONTriangles(indexes, vertices) diff --git a/engine/functions/transformFeature.ts b/engine/functions/transformFeature.ts index d9f87af..ea0bc87 100644 --- a/engine/functions/transformFeature.ts +++ b/engine/functions/transformFeature.ts @@ -34,6 +34,7 @@ export default function transformFeature( feature: FeatureType, center: LongLat ): MapTransformedFeature { + console.log("transformFeature__FN"); const centerPointLongLat = turf.center(feature).geometry.coordinates const centerPoint = toMetersFromCenter(centerPointLongLat, center) as [number, number] let transformedFeature = feature diff --git a/engine/functions/transformGeometry.ts b/engine/functions/transformGeometry.ts index ad7ec34..e62d5f0 100644 --- a/engine/functions/transformGeometry.ts +++ b/engine/functions/transformGeometry.ts @@ -18,6 +18,7 @@ export default function transformGeometry) { + console.log("unifyCACHE__FN"); for (const splitFeature of findSplitFeatures(cache.keys(), cache.values())) { const firstKey = splitFeature[0][0] const features = splitFeature.map(([_, feature]) => feature) diff --git a/engine/functions/unifyFeatures.ts b/engine/functions/unifyFeatures.ts index a8184ef..28edddf 100644 --- a/engine/functions/unifyFeatures.ts +++ b/engine/functions/unifyFeatures.ts @@ -4,6 +4,7 @@ import { multiPolygon, polygon } from '@turf/turf' /** Useful for when a feature is split across multiple vector tiles */ export default function unifyFeatures(features: Feature[]): Feature { + console.log("unifyFeature__FN"); if (features.length > 1) { const allCoords = features.map(getCoords) diff --git a/engine/phases/CreateCompleteNavMeshPhase.ts b/engine/phases/CreateCompleteNavMeshPhase.ts index 83e9d0c..ea70a00 100644 --- a/engine/phases/CreateCompleteNavMeshPhase.ts +++ b/engine/phases/CreateCompleteNavMeshPhase.ts @@ -8,10 +8,12 @@ export const isCachingPhase = false const builder = new NavMeshBuilder() export function getTaskKeys(_: MapStateUnwrapped) { + console.log('CreateCompleteNavMesh-PHASE-CALLED--->') return [null] } export function execTask(state: MapStateUnwrapped, _: TileKey) { + console.log('CreateCompleteNavMesh-PHASE-CALLED_2--->') for (const value of state.tileNavMeshCache.values()) { builder.addGeometry({ type: 'MultiPolygon', coordinates: value }) } diff --git a/engine/phases/CreateCompleteObjectPhase.ts b/engine/phases/CreateCompleteObjectPhase.ts index e5708d1..8ecfa9c 100644 --- a/engine/phases/CreateCompleteObjectPhase.ts +++ b/engine/phases/CreateCompleteObjectPhase.ts @@ -7,6 +7,7 @@ export const isAsyncPhase = false export const isCachingPhase = true const createCompleteObjectUsingCache = createUsingCache((state: MapStateUnwrapped, key: FeatureKey) => { + console.log('CreateCompleteObjectPhase--->') const [layerName] = key const feature = state.featureCache.get(key) @@ -16,6 +17,7 @@ const createCompleteObjectUsingCache = createUsingCache((state: MapStateUnwrappe }) export function* getTaskKeys(state: MapStateUnwrapped) { + console.log('CreateCompleteObjectPhase_2--->') for (const key of state.featureCache.keys()) { const geometry = state.geometryCache.get(key) if (geometry) { @@ -25,6 +27,7 @@ export function* getTaskKeys(state: MapStateUnwrapped) { } export function getTaskStatus(state: MapStateUnwrapped, key: FeatureKey) { + console.log('CreateCompleteObjectPhase_3--->') return state.completeObjectsTasks.get(key) } export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status: TaskStatus) { @@ -32,6 +35,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status: } export function execTask(state: MapStateUnwrapped, key: FeatureKey) { + console.log('CreateCompleteObjectPhase--->') return createCompleteObjectUsingCache(state.completeObjects, state, key) } diff --git a/engine/phases/CreateFallbackLanduseMeshPhase.ts b/engine/phases/CreateFallbackLanduseMeshPhase.ts index 2a0c25d..a8da103 100644 --- a/engine/phases/CreateFallbackLanduseMeshPhase.ts +++ b/engine/phases/CreateFallbackLanduseMeshPhase.ts @@ -10,12 +10,14 @@ export const isAsyncPhase = false export const isCachingPhase = false export function getTaskKeys(state: MapStateUnwrapped) { + console.log('CreateFallbackLand--->') return state.tileCache.keys() } const $tileBBox = Array(4) export function execTask(state: MapStateUnwrapped, key: TileKey) { + console.log('CreateFallbackLand_1--->') const [x, y] = key const [tileLeft, tileTop, tileRight, tileBottom] = computeTileBoundingBox( diff --git a/engine/phases/CreateGeometryPhase.ts b/engine/phases/CreateGeometryPhase.ts index b4f468a..ab09f78 100644 --- a/engine/phases/CreateGeometryPhase.ts +++ b/engine/phases/CreateGeometryPhase.ts @@ -17,6 +17,7 @@ const geometryLoader = new BufferGeometryLoader() /** using fetchUsingCache since createGeometry returns a promise */ const createGeometryUsingCache = fetchUsingCache(async (state: MapStateUnwrapped, key: FeatureKey) => { + console.log('CreateGeometryPhase--->') const { feature, centerPoint, boundingCircleRadius } = state.transformedFeatureCache.get(key) const [layerName] = key const styles = getFeatureStyles(DEFAULT_FEATURE_STYLES, layerName, feature.properties.class) @@ -44,6 +45,7 @@ export const isAsyncPhase = true export const isCachingPhase = true export function* getTaskKeys(state: MapStateUnwrapped) { + console.log('CreateGeometryPhase_2--->') const viewerPositionScaled = multiplyArray(state.viewerPosition, 1 / state.scale, $array2) as [number, number] for (const key of state.transformedFeatureCache.keys()) { const { centerPoint, boundingCircleRadius } = state.transformedFeatureCache.get(key) @@ -62,6 +64,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status: } export function startTask(state: MapStateUnwrapped, key: FeatureKey) { + console.log('CreateGeometryPhase_3--->') return createGeometryUsingCache(state.geometryCache as any, state, key) } diff --git a/engine/phases/CreateHelpersPhase.ts b/engine/phases/CreateHelpersPhase.ts index 6d34d24..742225b 100644 --- a/engine/phases/CreateHelpersPhase.ts +++ b/engine/phases/CreateHelpersPhase.ts @@ -7,6 +7,7 @@ export const isAsyncPhase = false export const isCachingPhase = true const createHelpersUsingCache = createUsingCache((state: MapStateUnwrapped, key: TileKey) => { + console.log('CreateHelpersUsingCache--->') const polygons = state.tileNavMeshCache.get(key) // const tileNavMesh = createPolygonHelper(polygons[0]) const tileNavMesh = createConvexMultiPolygonHelper(polygons) @@ -17,6 +18,7 @@ const createHelpersUsingCache = createUsingCache((state: MapStateUnwrapped, key: }) export function getTaskKeys(state: MapStateUnwrapped) { + console.log('CreateHelpersUsingCache_2--->') return state.tileNavMeshCache.keys() } @@ -28,6 +30,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: TileKey, status: Ta } export function execTask(state: MapStateUnwrapped, key: TileKey) { + console.log('CreateHelpersUsingCache_3--->') return createHelpersUsingCache(state.helpersCache, state, key) } diff --git a/engine/phases/CreateLabelPhase.ts b/engine/phases/CreateLabelPhase.ts index 8efc1b3..8715a0c 100644 --- a/engine/phases/CreateLabelPhase.ts +++ b/engine/phases/CreateLabelPhase.ts @@ -8,6 +8,7 @@ export const isAsyncPhase = false export const isCachingPhase = true export function* getTaskKeys(state: MapStateUnwrapped) { + console.log('CreateLabelPhase--->') for (const key of state.completeObjects.keys()) { const feature = state.featureCache.get(key) const transformed = state.transformedFeatureCache.get(key) @@ -38,6 +39,7 @@ const createLabelUsingCache = createUsingCache((state: MapStateUnwrapped, key: F }) export function execTask(state: MapStateUnwrapped, key: FeatureKey) { + console.log('CreateLabelPhase_2--->') return createLabelUsingCache(state.labelCache, state, key) } diff --git a/engine/phases/CreateTileNavMeshPhase.ts b/engine/phases/CreateTileNavMeshPhase.ts index 0217d62..9a08356 100644 --- a/engine/phases/CreateTileNavMeshPhase.ts +++ b/engine/phases/CreateTileNavMeshPhase.ts @@ -82,6 +82,7 @@ const createNavMeshUsingCache = createUsingCache((state: MapStateUnwrapped, key: }) export function getTaskKeys(state: MapStateUnwrapped) { + console.log('CreateNavMeshPhase--->') return createSurroundingTileIterator(state.center, state.navMeshRadius, TILE_ZOOM) } @@ -93,6 +94,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: TileKey, status: Ta } export function execTask(state: MapStateUnwrapped, key: TileKey) { + console.log('CreateNavMeshPhase_2--->') return createNavMeshUsingCache(state.tileNavMeshCache, state, key) } diff --git a/engine/phases/ExtractTileFeaturesPhase.ts b/engine/phases/ExtractTileFeaturesPhase.ts index c1aec5a..9d3f591 100644 --- a/engine/phases/ExtractTileFeaturesPhase.ts +++ b/engine/phases/ExtractTileFeaturesPhase.ts @@ -9,6 +9,7 @@ export const isAsyncPhase = false export const isCachingPhase = true export function getTaskKeys(state: MapStateUnwrapped) { + console.log('ExtractTileFeaturesPhase--->') console.log('tileCache size', state.tileCache.size) return state.tileCache.keys() } @@ -21,6 +22,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: TileKey, status: Ta } export function execTask(state: MapStateUnwrapped, tileKey: TileKey) { + console.log('ExtractTileFeaturesPhase_2--->') const vectorTile = state.tileCache.get(tileKey) const [x, y] = tileKey if (vectorTile) { diff --git a/engine/phases/FetchTilesPhase.ts b/engine/phases/FetchTilesPhase.ts index 50c9f7f..412b484 100644 --- a/engine/phases/FetchTilesPhase.ts +++ b/engine/phases/FetchTilesPhase.ts @@ -12,6 +12,7 @@ export const isAsyncPhase = true export const isCachingPhase = true export function getTaskKeys(state: MapStateUnwrapped) { + console.log('FetchVector--->') return createSurroundingTileIterator(state.center, state.minimumSceneRadius, TILE_ZOOM) } @@ -23,6 +24,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: TileKey, status: Ta } export function startTask(state: MapStateUnwrapped, key: TileKey) { + console.log('FetchVector_2--->') return fetchVectorTileUsingCache(state.tileCache, state, key) } diff --git a/engine/phases/TransformFeaturePhase.ts b/engine/phases/TransformFeaturePhase.ts index 80b8253..491d248 100644 --- a/engine/phases/TransformFeaturePhase.ts +++ b/engine/phases/TransformFeaturePhase.ts @@ -22,6 +22,7 @@ const transformFeatureUsingCache = fetchUsingCache((state: MapStateUnwrapped, ke }) export function getTaskKeys(state: MapStateUnwrapped) { + console.log('TransformPhase--->') return state.featureCache.keys() } @@ -33,6 +34,7 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status: } export function startTask(state: MapStateUnwrapped, key: FeatureKey) { + console.log('TransformPhase_2--->') return transformFeatureUsingCache(state.transformedFeatureCache as any, state, key) } diff --git a/engine/phases/UnifyFeaturesPhase.ts b/engine/phases/UnifyFeaturesPhase.ts index 4e7b008..882fa06 100644 --- a/engine/phases/UnifyFeaturesPhase.ts +++ b/engine/phases/UnifyFeaturesPhase.ts @@ -6,10 +6,12 @@ export const isAsyncPhase = false export const isCachingPhase = false export function* getTaskKeys() { + console.log('UnifyFeatures--->') yield null } export function execTask(state: MapStateUnwrapped) { + console.log('UnifyFeatures_2--->') unifyCachedFeatures(state.featureCache) }