Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
various scene loading improvements (#6889)
Browse files Browse the repository at this point in the history
  • Loading branch information
HexaField authored Sep 8, 2022
1 parent f88c68b commit af68634
Show file tree
Hide file tree
Showing 15 changed files with 40 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const useLocationSpawnAvatar = () => {
AvatarService.fetchAvatarList()
}, [])

useHookEffect(async () => {
useHookEffect(() => {
if (
didSpawn.value ||
Engine.instance.currentWorld.localClientEntity ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ export const LoadLocationScene = () => {
}
}, [authState.isLoggedIn.value, locationState.locationName.value])

useHookEffect(() => {
if (authState.user.id.value) dispatchAction(EngineActions.connect({ id: authState.user.id.value }))
}, [authState.user])

if (isUserBanned) return <div className="banned">{t('location.youHaveBeenBannedMsg')}</div>
if (userNotAuthorized) return <div className="not-authorized">{t('location.notAuthorizedAtLocation')}</div>

Expand Down
6 changes: 1 addition & 5 deletions packages/client-core/src/user/services/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ export interface LinkedInLoginForm {
email: string
}

export const avatarFetchedReceptor = (s: any, action: any) => {
return s.avatarList.set(action.avatarList)
}

export const AuthServiceReceptor = (action) => {
const s = getState(AuthState)
matches(action)
Expand Down Expand Up @@ -159,7 +155,7 @@ export const AuthServiceReceptor = (action) => {
return s.user.merge({ user_setting: action.data })
})
.when(AuthAction.updateAvatarListAction.matches, (action) => {
return avatarFetchedReceptor(s, action)
return s.avatarList.set(action.avatarList)
})
}

Expand Down
9 changes: 7 additions & 2 deletions packages/editor/src/components/EditorContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ const EditorContainer = () => {
const importScene = async (sceneFile: SceneJson) => {
setDialogComponent(<ProgressDialog message={t('editor:loading')} />)
try {
await loadProjectScene(sceneFile)
await loadProjectScene({
project: projectName.value!,
scene: sceneFile,
thumbnailUrl: null!,
name: ''
})
dispatchAction(EditorAction.sceneModified({ modified: true }))
setDialogComponent(null)
} catch (error) {
Expand Down Expand Up @@ -180,7 +185,7 @@ const EditorContainer = () => {
const project = await getScene(projectName.value, sceneName, false)

if (!project.scene) return
await loadProjectScene(project.scene)
await loadProjectScene(project)

setDialogComponent(null)
} catch (error) {
Expand Down
6 changes: 3 additions & 3 deletions packages/editor/src/functions/projectFunctions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { API } from '@xrengine/client-core/src/API'
import { MultiError } from '@xrengine/client-core/src/util/errors'
import { ProjectInterface } from '@xrengine/common/src/interfaces/ProjectInterface'
import { SceneJson } from '@xrengine/common/src/interfaces/SceneInterface'
import { SceneData, SceneJson } from '@xrengine/common/src/interfaces/SceneInterface'
import { AnimationManager } from '@xrengine/engine/src/avatar/AnimationManager'
import { EngineActions } from '@xrengine/engine/src/ecs/classes/EngineState'
import TransformGizmo from '@xrengine/engine/src/scene/classes/TransformGizmo'
Expand Down Expand Up @@ -51,7 +51,7 @@ export async function runPreprojectLoadTasks(): Promise<void> {
/**
* Loads scene from provided project file.
*/
export async function loadProjectScene(projectFile: SceneJson) {
export async function loadProjectScene(projectData: SceneData) {
executeCommand({ type: EditorCommands.REPLACE_SELECTION, affectedNodes: [] })
clearHistory()

Expand All @@ -61,7 +61,7 @@ export async function loadProjectScene(projectFile: SceneJson) {

removeInputEvents()
disposePlayModeControls()
const errors = await initializeScene(projectFile)
const errors = await initializeScene(projectData)

dispatchAction(EditorAction.projectLoaded({ loaded: true }))
dispatchAction(SelectionAction.changedSceneGraph({}))
Expand Down
13 changes: 8 additions & 5 deletions packages/editor/src/functions/sceneRenderFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Group, Object3D, Scene, Vector3, WebGLInfo } from 'three'

import { SceneJson } from '@xrengine/common/src/interfaces/SceneInterface'
import { SceneData, SceneJson } from '@xrengine/common/src/interfaces/SceneInterface'
import { Engine } from '@xrengine/engine/src/ecs/classes/Engine'
import { EngineActions } from '@xrengine/engine/src/ecs/classes/EngineState'
import { Entity } from '@xrengine/engine/src/ecs/classes/Entity'
import { addComponent, removeComponent } from '@xrengine/engine/src/ecs/functions/ComponentFunctions'
import { removeEntity } from '@xrengine/engine/src/ecs/functions/EntityFunctions'
import { emptyEntityTree } from '@xrengine/engine/src/ecs/functions/EntityTreeFunctions'
import { matchActionOnce } from '@xrengine/engine/src/networking/functions/matchActionOnce'
import {
accessEngineRendererState,
EngineRendererAction,
Expand All @@ -15,8 +17,8 @@ import { EngineRenderer } from '@xrengine/engine/src/renderer/WebGLRendererSyste
import InfiniteGridHelper from '@xrengine/engine/src/scene/classes/InfiniteGridHelper'
import TransformGizmo from '@xrengine/engine/src/scene/classes/TransformGizmo'
import { ObjectLayers } from '@xrengine/engine/src/scene/constants/ObjectLayers'
import { loadSceneFromJSON } from '@xrengine/engine/src/scene/systems/SceneLoadingSystem'
import { dispatchAction } from '@xrengine/hyperflux'
import { updateSceneFromJSON } from '@xrengine/engine/src/scene/systems/SceneLoadingSystem'
import { addActionReceptor, dispatchAction } from '@xrengine/hyperflux'

import { EditorCameraComponent } from '../classes/EditorCameraComponent'
import { ActionSets, EditorMapping } from '../controls/input-mappings'
Expand Down Expand Up @@ -52,13 +54,14 @@ export const SceneState: SceneStateType = {
editorEntity: null!
}

export async function initializeScene(projectFile: SceneJson): Promise<Error[] | void> {
export async function initializeScene(sceneData: SceneData): Promise<Error[] | void> {
SceneState.isInitialized = false

if (!Engine.instance.currentWorld.scene) Engine.instance.currentWorld.scene = new Scene()

// getting scene data
await loadSceneFromJSON(projectFile, [])
await updateSceneFromJSON(sceneData)
await new Promise((resolve) => matchActionOnce(EngineActions.sceneLoaded.matches, resolve))

Engine.instance.currentWorld.camera.position.set(0, 5, 10)
Engine.instance.currentWorld.camera.lookAt(new Vector3())
Expand Down
1 change: 1 addition & 0 deletions packages/engine/src/avatar/functions/avatarFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const loadAvatarForUser = async (
}
}

if (hasComponent(entity, AvatarPendingComponent)) removeComponent(entity, AvatarPendingComponent)
addComponent(entity, AvatarPendingComponent, true)
const parent = await loadAvatarModelAsset(avatarURL)
if (hasComponent(entity, AvatarPendingComponent)) removeComponent(entity, AvatarPendingComponent)
Expand Down
5 changes: 0 additions & 5 deletions packages/engine/src/ecs/classes/EngineState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ export class EngineActions {
progress: matches.number
})

static connect = defineAction({
type: 'xre.engine.CONNECT' as const,
id: matches.string
})

static browserNotSupported = defineAction({
type: 'xre.engine.BROWSER_NOT_SUPPORTED' as const,
msg: matches.string
Expand Down
3 changes: 0 additions & 3 deletions packages/engine/src/initializeEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ export const initializeBrowser = () => {
// maybe needs to be awaited?
FontManager.instance.getDefaultFont()

matchActionOnce(EngineActions.connect.matches, (action: any) => {
Engine.instance.userId = action.id
})
EngineRenderer.instance.initialize()
Engine.instance.engineTimer.start()
}
Expand Down
10 changes: 6 additions & 4 deletions packages/engine/src/scene/systems/HyperspacePortalSystem.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { AmbientLight, Color } from 'three'

import { createActionQueue } from '@xrengine/hyperflux'

import { AssetLoader } from '../../assets/classes/AssetLoader'
import { Engine } from '../../ecs/classes/Engine'
import { EngineActions } from '../../ecs/classes/EngineState'
Expand Down Expand Up @@ -34,6 +36,8 @@ export default async function HyperspacePortalSystem(world: World) {

let sceneVisible = true

const sceneLoadedQueue = createActionQueue(EngineActions.sceneLoaded.matches)

return () => {
const playerObj = getComponent(world.localClientEntity, Object3DComponent)

Expand All @@ -49,11 +53,9 @@ export default async function HyperspacePortalSystem(world: World) {
Engine.instance.currentWorld.scene.add(light)
Engine.instance.currentWorld.scene.add(hyperspaceEffect)

// create receptor for joining the world to end the hyperspace effect
matchActionOnce(EngineActions.sceneLoaded.matches, () => {
if (sceneLoadedQueue().length) {
transition.setState('OUT')
return true
})
}
}

// run the logic for
Expand Down
35 changes: 5 additions & 30 deletions packages/engine/src/scene/systems/SceneLoadingSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ export const loadECSData = async (sceneData: SceneJson, assetRoot = undefined):
return result
}

const postProcessingQuery = defineQuery([PostprocessingComponent])

/**
* Updates the scene based on serialized json data
* @param oldSceneData
Expand All @@ -141,7 +139,7 @@ const postProcessingQuery = defineQuery([PostprocessingComponent])
export const updateSceneFromJSON = async (sceneData: SceneData) => {
const world = Engine.instance.currentWorld

const sceneSystems = getSystemsFromSceneData(sceneData.project, sceneData.scene, true)
const sceneSystems = getSystemsFromSceneData(sceneData.project, sceneData.scene)
const systemsToLoad = sceneSystems.filter(
(systemToLoad) =>
!Object.values(world.pipelines)
Expand Down Expand Up @@ -233,32 +231,6 @@ export const updateSceneFromJSON = async (sceneData: SceneData) => {
entities: changedEntityNodes.map(([uuid]) => world.entityTree.uuidNodeMap.get(uuid)?.entity!)
})
)
}

/**
* Loads a scene from scene json, unloading the current scene if there is one already loaded
* @param sceneData
* @param sceneSystems an array of system modules to load
* @param softReload a boolean to indicate if the unloading should only unload scene entities, rather than network objects
*/
export const loadSceneFromJSON = async (sceneData: SceneJson, sceneSystems: SystemModuleType<any>[]) => {
const world = Engine.instance.currentWorld

unloadScene(world)

await initSystems(world, sceneSystems)

// reset renderer settings for if we are teleporting and the new scene does not have an override
resetEngineRenderer(true)

const { entityLoadQueue, entityDynamicQueue } = splitLazyLoadedSceneEntities(sceneData)

if (Engine.instance.isEditor) {
for (const [key, val] of Object.entries(sceneData.entities)) createSceneEntity(key, val, world)
} else {
for (const [key, val] of Object.entries(entityDynamicQueue)) addDynamicallyLoadedEntity(key, val, world)
for (const [key, val] of Object.entries(entityLoadQueue)) createSceneEntity(key, val, world, sceneData)
}

if (!sceneAssetPendingTagQuery().length) {
dispatchAction(EngineActions.sceneLoaded({}))
Expand All @@ -270,6 +242,9 @@ export const addDynamicallyLoadedEntity = (
entityJson: EntityJson,
world = Engine.instance.currentWorld
) => {
if (Engine.instance.isEditor) {
return createSceneEntity(uuid, entityJson, world)
}
const transform = entityJson.components.find((comp) => comp.name === SCENE_COMPONENT_TRANSFORM)
const dynamicLoad = entityJson.components.find((comp) => comp.name === SCENE_COMPONENT_DYNAMIC_LOAD)!
if (transform) {
Expand Down Expand Up @@ -379,7 +354,7 @@ export default async function SceneLoadingSystem(world: World) {
dispatchAction(
EngineActions.sceneLoadingProgress({
progress:
promisesCompleted > totalPendingAssets ? 100 : Math.round((100 * promisesCompleted) / totalPendingAssets)
promisesCompleted >= totalPendingAssets ? 100 : Math.round((100 * promisesCompleted) / totalPendingAssets)
})
)
}
Expand Down
8 changes: 2 additions & 6 deletions packages/engine/tests/portal/portal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import dotenv from 'dotenv-flow'
import { parseSceneDataCacheURLs } from '@xrengine/server-core/src/projects/scene/scene-parser'

import sceneJson from '../../../projects/default-project/default.scene.json'
import { Engine } from '../../src/ecs/classes/Engine'
import { unloadScene } from '../../src/ecs/functions/EngineFunctions'
import { useWorld } from '../../src/ecs/functions/SystemHooks'
import { loadSceneFromJSON } from '../../src/scene/systems/SceneLoadingSystem'

dotenv.config({
path: appRootPath.path,
Expand All @@ -24,7 +20,7 @@ describe.skip('Portal', () => {
// })
// it('Can load scene', async () => {
// const world = useWorld()
// await loadSceneFromJSON(sceneData)
// await updateSceneFromJSON(sceneData)
// assert.equal(world.entityQuery().length, 10)
// // TODO: test scene actor removal directly
// assert.equal(world.physics.bodies.size, 1)
Expand All @@ -38,7 +34,7 @@ describe.skip('Portal', () => {
// assert.equal(world.physics.bodies.size, 0)
// })
// it('Can load new scene', async () => {
// await loadSceneFromJSON(sceneData)
// await updateSceneFromJSON(sceneData)
// const world = useWorld()
// assert.equal(world.entityQuery().length, 10)
// assert.equal(world.physics.bodies.size, 1)
Expand Down
8 changes: 3 additions & 5 deletions packages/instanceserver/src/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ import {
import { NetworkTopics } from '@xrengine/engine/src/networking/classes/Network'
import { matchActionOnce } from '@xrengine/engine/src/networking/functions/matchActionOnce'
import { NetworkPeerFunctions } from '@xrengine/engine/src/networking/functions/NetworkPeerFunctions'
import { loadSceneFromJSON } from '@xrengine/engine/src/scene/systems/SceneLoadingSystem'
import { updateSceneFromJSON } from '@xrengine/engine/src/scene/systems/SceneLoadingSystem'
import { dispatchAction } from '@xrengine/hyperflux'
import { loadEngineInjection } from '@xrengine/projects/loadEngineInjection'
import { getSystemsFromSceneData } from '@xrengine/projects/loadSystemInjection'
import { Application } from '@xrengine/server-core/declarations'
import config from '@xrengine/server-core/src/appconfig'
import multiLogger from '@xrengine/server-core/src/logger'
Expand Down Expand Up @@ -260,9 +259,8 @@ const loadEngine = async (app: Application, sceneId: string) => {
await loadEngineInjection(world, projects)

const sceneUpdatedListener = async () => {
const sceneData = (await sceneResultPromise).data.scene
const sceneSystems = getSystemsFromSceneData(projectName, sceneData, false)
await loadSceneFromJSON(sceneData, sceneSystems)
const sceneData = (await sceneResultPromise).data
await updateSceneFromJSON(sceneData)
}
app.service('scene').on('updated', sceneUpdatedListener)
await sceneUpdatedListener()
Expand Down
2 changes: 1 addition & 1 deletion packages/instanceserver/src/preload-location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default async function (locationName, app: Application) {
}
}, 1000)
await loadSceneFromJSON(result, (left) => {
await updateSceneFromJSON(result, (left) => {
entitiesLeft = left
})
Expand Down
7 changes: 2 additions & 5 deletions packages/projects/loadSystemInjection.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import type { SceneJson } from '@xrengine/common/src/interfaces/SceneInterface'
import { isClient } from '@xrengine/engine/src/common/functions/isClient'
import type { SystemModuleType } from '@xrengine/engine/src/ecs/functions/SystemFunctions'
import type { SystemComponentType } from '@xrengine/engine/src/scene/components/SystemComponent'

export const getSystemsFromSceneData = (
project: string,
sceneData: SceneJson,
isClient: boolean
): SystemModuleType<any>[] => {
export const getSystemsFromSceneData = (project: string, sceneData: SceneJson): SystemModuleType<any>[] => {
const systems: SystemModuleType<any>[] = []
for (const [uuid, entity] of Object.entries(sceneData.entities)) {
for (const component of entity.components) {
Expand Down

0 comments on commit af68634

Please sign in to comment.