diff --git a/editor/MapNodeEditor.tsx b/editor/MapNodeEditor.tsx
index 901ddce..c08c828 100755
--- a/editor/MapNodeEditor.tsx
+++ b/editor/MapNodeEditor.tsx
@@ -6,46 +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.node.entity, MapComponent)
+ const mapComponent = useComponent(props.entity, MapComponent)
console.log('MapNodeEditor')
return (
-
+
-
+
-
+
-
+
-
+
-
+
)
diff --git a/editor/index.ts b/editor/index.ts
index c3481b4..8afbba1 100644
--- a/editor/index.ts
+++ b/editor/index.ts
@@ -1,14 +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 { map } from '../worldInjection'
-import { World } from '@etherealengine/engine/src/ecs/classes/World'
+
import MapUpdateSystem from '../engine/MapUpdateSystem'
+import { GEO_MAP } from '../worldInjection'
-EntityNodeEditor[map] = MapNodeEditor
-prefabIcons[map] = MapIcon
+export default async () => {
+ prefabIcons[GEO_MAP] = MapIcon
-export default async (world: World) => {
- return await MapUpdateSystem(world)
-}
\ No newline at end of file
+ startSystem(MapUpdateSystem, {})
+}
diff --git a/engine/MapComponent.ts b/engine/MapComponent.ts
index 8f12a26..e0eea33 100644
--- a/engine/MapComponent.ts
+++ b/engine/MapComponent.ts
@@ -1,18 +1,69 @@
-import { createMappedComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
+import { useEffect } from 'react'
import { Vector3 } from 'three'
-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 { 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 const MapComponent = createMappedComponent('MapComponent')
+import { _updateMap, deserializeMap, SCENE_COMPONENT_MAP } from './MapFunctions'
+
+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 7cd979c..3fc31a9 100755
--- a/engine/MapFunctions.ts
+++ b/engine/MapFunctions.ts
@@ -1,65 +1,85 @@
-import { getStartCoords } from './getStartCoords'
-import { MapComponentType } from './MapComponent'
-import { addComponent, getComponent, hasComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
-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 { 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 { debounce } from 'lodash'
+import { Group, Mesh, Object3D } from 'three'
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 { 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,
+ ComponentType,
+ 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 { 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 { MapState, MapStateService } from './MapReceptor'
import { addChildFast, setPosition } from './util'
-import { debounce } from 'lodash'
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) => {
+ console.log('deserialize_map')
+ const sceneAssetPendingTagQuery = defineQuery([SceneAssetPendingTagComponent])
+ console.log('sceneassetpending', sceneAssetPendingTagQuery.length)
if (isClient) {
- registerSceneLoadPromise(createMap(entity, json.props))
- if (Engine.isEditor) getComponent(entity, EntityNodeComponent)?.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)
+ // }
}
}
export const createMap = async (entity: Entity, args: MapComponentType) => {
- if(Engine.isEditor && hasComponent(entity, MapComponent)) {
+ 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)
- 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))
+ console.log('map_functions_create_map')
- // TODO fix hardcoded URL
- const spinnerGLTF = await LoadGLTF(Engine.publicPath + '/projects/XREngine-Project-Maps/EarthLowPoly.glb')
- const spinner = spinnerGLTF.scene as Mesh
- spinner.position.y = avatarHalfHeight * 2
- spinner.position.z = -150
- state.updateSpinner = spinner
+ 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
+ // spinner.position.y = defaultAvatarHalfHeight * 2
+ // spinner.position.z = -150
+ // state.updateSpinner = spinner
const updateTextContainer = new Text()
@@ -76,12 +96,11 @@ 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)
- Engine.scene.add(navigationRaycastTarget)
+ navigationRaycastTarget.scale.setScalar(state.scale.value)
+ Engine.instance.scene.add(navigationRaycastTarget)
addComponent(entity, NavMeshComponent, {
/*
@@ -93,30 +112,37 @@ 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
+
+ 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
- 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)
@@ -125,23 +151,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 {
- 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
- }
- }
-}
\ No newline at end of file
+
+export const updateMap = debounce((entity, args) => _updateMap(entity, args), 500) as any as (
+ entity: Entity,
+ props: any
+) => void
diff --git a/engine/MapReceptor.ts b/engine/MapReceptor.ts
index 10cd2ee..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,108 +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/isClient'
-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) => {
- state.batch((s) => {
- switch (action.type) {
- case 'map.INITIALIZE':
- return s.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
- })
- }
- })
+const mapSetPropertyActionReceptor = (action: typeof MapStateActions.setProperty.matches._TYPE) => {
+ const state = getMutableState(MapState)
+ return state.merge(action.data)
}
-export const accessMapState = () => state
+export const MapStateReceptor = {
+ mapInitializeActionReceptor,
+ mapSetPropertyActionReceptor
+}
-if (process.env.APP_ENV === 'development' && isClient) {
- ;(window as any).mapReceptor = mapReceptor
- ;(window as any).MapAction = MapAction
- ;(window as any).accessMapState = accessMapState
+// 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 414a5a4..ec90f5a 100644
--- a/engine/MapUpdateSystem.ts
+++ b/engine/MapUpdateSystem.ts
@@ -1,20 +1,23 @@
-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'
-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 { 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'
-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 { 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 { MapState, MapStateActions, MapStateReceptor, MapStateService } from './MapReceptor'
+import { IPhase } from './types'
+import { addChildFast, multiplyArray, setPosition, vectorToArray } from './util'
const PI2 = Math.PI * 2
const $vector3 = new Vector3()
@@ -24,167 +27,185 @@ 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 {
- 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(world)[0]
- const mapEntities = mapsQuery(world)
- const mapEntity = mapEntities[0]
- const navPlaneEntity = navMeshQuery(world)[0]
- // Sanity checks
- if (!mapEntity || !viewerEntity) return world
- 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 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])
+const mapStateInitializeActionQueue = defineActionQueue(MapStateActions.initialize.matches)
+const mapStateSetPropertyActionQueue = defineActionQueue(MapStateActions.setProperty.matches)
+
+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!')
+
+ // 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)
+ 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.value * mapState.triggerRefreshRadius.value
+ const wasMapCenterUpdated =
+ typeof $previousMapCenterPoint[0] !== 'undefined' &&
+ typeof $previousMapCenterPoint[1] !== 'undefined' &&
+ ($previousMapCenterPoint[0] !== mapState.center.value[0] || $previousMapCenterPoint[1] !== mapState.center.value[1])
+
+ if (wasMapCenterUpdated) {
+ mapState.viewerPosition.value[0] = $previousViewerPosition[0] = 0
+ mapState.viewerPosition.value[1] = $previousViewerPosition[1] = 0
+ viewerTransform.position.set(0, 0, 0)
+ resetPhases(mapState.value, phases)
+ }
- if (wasRefreshTriggered || wasMapCenterUpdated) {
- mapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, mapState.center)
- mapState.viewerPosition = viewerPosition
- startPhases(mapState, phases)
+ if (wasRefreshTriggered || wasMapCenterUpdated) {
+ const tempMapState = { ...mapState.value }
+ tempMapState.center = fromMetersFromCenter($normalScaleViewerPositionDelta, tempMapState.center)
+ tempMapState.viewerPosition = viewerPosition
+ startPhases(tempMapState, 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.value.children.length = 0
- navigationRaycastTarget.children.length = 0
- object3dComponent.value.children[0] = spinner
-
- object3dComponent.value.children[1] = mapState.updateTextContainer!
-
- avatar.modelContainer.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.modelContainer.visible = true
- object3dComponent.value.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.value, object.mesh)
- } else {
- object.mesh.parent = null
- }
+ $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.value.size === 0) {
+ const spinner = mapState.updateSpinner.value!
+ 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.value!
+
+ 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.value === 'UpdateScene') {
+ avatar.model!.visible = true
+ object3dComponent[0].children.length = 0
+ for (const key of mapState.completeObjects.value.keys()) {
+ const object = mapState.completeObjects.value.get(key)
+ if (object.mesh) {
+ if (
+ isIntersectCircleCircle(
+ viewerPositionScaled,
+ mapState.minimumSceneRadius.value * mapState.scale.value,
+ 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.value, label.mesh)
- } else {
- label.mesh.parent = null
- }
+ }
+ for (const label of mapState.labelCache.value.values()) {
+ if (label.mesh) {
+ if (
+ isIntersectCircleCircle(
+ viewerPositionScaled,
+ mapState.labelRadius.value * mapState.scale.value,
+ 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.value.keys()) {
+ const layerName = key[0]
+ if (layerName === 'landuse_fallback') {
+ const { mesh, centerPoint } = mapState.completeObjects.value.get(key)
+ setPosition(mesh, centerPoint)
+
+ addChildFast(navigationRaycastTarget, mesh)
}
- for (const helpers of mapState.helpersCache.values()) {
- if (helpers.tileNavMesh) {
- addChildFast(object3dComponent.value, helpers.tileNavMesh)
- }
+ }
+ for (const helpers of mapState.helpersCache.value.values()) {
+ if (helpers.tileNavMesh) {
+ addChildFast(object3dComponent[0], helpers.tileNavMesh)
}
-
- // Update (sub)scene
- mapState.activePhase = null
}
- // Update labels
- if (Math.round(world.fixedElapsedTime / world.fixedDelta) % 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
+ MapStateService.setProperty({ activePhase: null })
+ }
+
+ // Update labels
+ if (Math.round(Engine.instance.elapsedSeconds / Engine.instance.fixedDeltaSeconds) % 20 === 0) {
+ for (const label of mapState.labelCache.value.values()) {
+ if (label.mesh) {
+ if (
+ isIntersectCircleCircle(
+ viewerPositionScaled,
+ mapState.labelRadius.value * mapState.scale.value,
+ label.centerPoint,
+ label.boundingCircleRadius
+ )
+ ) {
+ label.mesh.update()
}
}
}
previousViewerEntity = viewerEntity
- return world
}
}
+
+const MapUpdateSystem = defineSystem({
+ uuid: 'ee.map.MapUpdateSystem',
+ execute
+})
+
+export default MapUpdateSystem
diff --git a/engine/functions/PhaseFunctions.ts b/engine/functions/PhaseFunctions.ts
index c9e8838..18200e2 100644
--- a/engine/functions/PhaseFunctions.ts
+++ b/engine/functions/PhaseFunctions.ts
@@ -1,6 +1,7 @@
+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'
@@ -55,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)
}
@@ -67,30 +70,32 @@ 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 }
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 +103,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
}
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 2596d8d..5aa2a3f 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()
}
@@ -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 7216d13..f1c5721 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()
@@ -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 7f7e411..ca33424 100644
--- a/engine/functions/fetchUsingCache.ts
+++ b/engine/functions/fetchUsingCache.ts
@@ -3,8 +3,9 @@ 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
) {
+ console.log("FETCHCACHE__FN");
const _fetchUsingCache = createUsingGetSet(fetch)
return async (
cache: ParametricCache,
@@ -14,7 +15,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)
},
@@ -24,3 +25,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/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 dbb2e3f..a94d56f 100644
--- a/engine/functions/findSplitFeatures.ts
+++ b/engine/functions/findSplitFeatures.ts
@@ -7,12 +7,18 @@ 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) => {
+ groups.set(groupKey, groupValue)
+ return groupValue
+ }
const addToGroup = updateKeyVal(
groups.get.bind(groups),
- groups.set.bind(groups),
+ groupSetFunction,
(group: Group, newKey: FeatureKey, newFeature: Feature) => {
return [...group, [newKey, newFeature]]
},
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/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/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/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 8efd3cd..a8da103 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'
@@ -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(
@@ -33,7 +35,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..ab09f78 100644
--- a/engine/phases/CreateGeometryPhase.ts
+++ b/engine/phases/CreateGeometryPhase.ts
@@ -3,21 +3,21 @@ 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?worker'
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(new URL('../workers/geometryWorker.ts', import.meta.url).href, true, {name: "Geometry Worker"}))
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)
@@ -45,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)
@@ -63,7 +64,8 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status:
}
export function startTask(state: MapStateUnwrapped, key: FeatureKey) {
- return createGeometryUsingCache(state.geometryCache, state, key)
+ console.log('CreateGeometryPhase_3--->')
+ return createGeometryUsingCache(state.geometryCache as any, state, key)
}
export function cleanup(state: MapStateUnwrapped) {
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 a6469e3..412b484 100644
--- a/engine/phases/FetchTilesPhase.ts
+++ b/engine/phases/FetchTilesPhase.ts
@@ -1,17 +1,18 @@
-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)
+const fetchVectorTileUsingCache = fetchUsingCacheAsync(fetchVectorTile)
export const name = 'FetchTiles'
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 87fe992..491d248 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(new URL('../workers/transformFeatureWorker.ts', import.meta.url).href, true, {name: 'Transform Feature Worker'}))
export const name = 'TransformFeature'
export const isAsyncPhase = true
@@ -23,6 +22,7 @@ const transformFeatureUsingCache = fetchUsingCache((state: MapStateUnwrapped, ke
})
export function getTaskKeys(state: MapStateUnwrapped) {
+ console.log('TransformPhase--->')
return state.featureCache.keys()
}
@@ -34,7 +34,8 @@ export function setTaskStatus(state: MapStateUnwrapped, key: FeatureKey, status:
}
export function startTask(state: MapStateUnwrapped, key: FeatureKey) {
- return transformFeatureUsingCache(state.transformedFeatureCache, state, key)
+ console.log('TransformPhase_2--->')
+ return transformFeatureUsingCache(state.transformedFeatureCache as any, state, key)
}
export function cleanup(state: MapStateUnwrapped) {
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)
}
diff --git a/engine/types.ts b/engine/types.ts
index 01898a2..b77541c 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 './MapReceptor'
+
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
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/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,
diff --git a/worldInjection.ts b/worldInjection.ts
index f7b9228..8eb6802 100644
--- a/worldInjection.ts
+++ b/worldInjection.ts
@@ -1,25 +1,29 @@
+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 { 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 { 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 MapIcon from '@mui/icons-material/Map'
-export const map = 'Geo Map' as const
+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 default async (world: World) => {
+export const GEO_MAP = 'Geo Map' as const
- if(!isNode) {
- (await import('./editor/index')).default(world)
+export default async () => {
+ if (isClient) {
+ EntityNodeEditor.set(MapComponent, MapNodeEditor)
+ prefabIcons[GEO_MAP] = MapIcon
+ startSystem(MapUpdateSystem, { after: InputSystemGroup })
}
- world.scenePrefabRegistry.set(map, [
+ Engine.instance.scenePrefabRegistry.set(GEO_MAP, [
...defaultSpatialComponents,
{ name: SCENE_COMPONENT_MAP, props: SCENE_COMPONENT_MAP_DEFAULT_VALUES }
])
-
- world.sceneLoadingRegistry.set(SCENE_COMPONENT_MAP, {
- deserialize: deserializeMap,
- serialize: serializeMap,
- update: updateMap
- })
}