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

Optimize non 3d webpages from rendering canvas #10421

Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
40d9a0c
initial work to separate engine canvas as requirement
HexaField Jun 20, 2024
b41efdd
studio works
HexaField Jun 20, 2024
b1b42ea
fixes
HexaField Jun 20, 2024
70d9619
Merge branch 'dev' into IR-2746-Optimize-performance-of-webpages-when…
HexaField Jun 20, 2024
1ea319c
studio fixes
HexaField Jun 20, 2024
dd9aefd
fix cache busting for admin panel
HexaField Jun 20, 2024
70daa18
license
HexaField Jun 20, 2024
e2fcc45
fix preview panels, various bug fixes
HexaField Jun 21, 2024
c6f0005
fix checks and tests
HexaField Jun 21, 2024
23b927e
visual script, particles
HexaField Jun 21, 2024
fba15eb
Merge branch 'dev' into IR-2746-Optimize-performance-of-webpages-when…
HexaField Jun 21, 2024
7354e1d
fix
HexaField Jun 21, 2024
7237bbd
add dispose to mock renderer
HexaField Jun 21, 2024
2e88d02
skip visual script tests
HexaField Jun 21, 2024
1737abc
console log
HexaField Jun 21, 2024
084285f
add note
HexaField Jun 21, 2024
7ae328a
Merge branch 'dev' into IR-2746-Optimize-performance-of-webpages-when…
HexaField Jun 21, 2024
2dd466e
Merge branch 'dev' into IR-2746-Optimize-performance-of-webpages-when…
HexaField Jun 24, 2024
45662dc
fix error with renderer system test, don't start time for tests
HexaField Jun 25, 2024
2c54141
Merge branch 'dev' into IR-2746-Optimize-performance-of-webpages-when…
HexaField Jun 25, 2024
4131f8f
format
HexaField Jun 25, 2024
4d6ec2d
fix regressions
HexaField Jun 25, 2024
3e5da7d
fix destroying spatial entities
HexaField Jun 25, 2024
d2430c3
fix zindex for viewport toolbar
HexaField Jun 25, 2024
58080e3
client input system was still running if no viewer was available
DanielBelmes Jun 25, 2024
92f19a2
revert
HexaField Jun 25, 2024
afb28d0
Merge branch 'dev' into IR-2746-Optimize-performance-of-webpages-when…
HexaField Jun 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { PopoverState } from '@etherealengine/client-core/src/common/services/Po
import { AvatarService } from '@etherealengine/client-core/src/user/services/AvatarService'
import { THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH } from '@etherealengine/common/src/constants/AvatarConstants'
import { AvatarType } from '@etherealengine/common/src/schema.type.module'
import { cleanURL } from '@etherealengine/common/src/utils/cleanURL'
import { AssetsPreviewPanel } from '@etherealengine/editor/src/components/assets/AssetsPreviewPanel'
import { ItemTypes } from '@etherealengine/editor/src/constants/AssetTypes'
import { useHookstate } from '@etherealengine/hyperflux'
Expand Down Expand Up @@ -118,12 +119,12 @@ export default function AddEditAvatarModal({ avatar }: { avatar?: AvatarType })
avatarFile = avatarAssets.model.value
avatarThumbnail = avatarAssets.thumbnail.value
} else {
const modelName = avatarAssets.modelURL.value.split('/').pop()!
const avatarData = await fetch(avatarAssets.modelURL.value)
const modelName = cleanURL(avatarAssets.modelURL.value).split('/').pop()!
avatarFile = new File([await avatarData.blob()], modelName)

const thumbnailData = await fetch(avatarAssets.thumbnailURL.value)
const thumbnailName = avatarAssets.thumbnailURL.value.split('/').pop()!
const thumbnailName = cleanURL(avatarAssets.thumbnailURL.value).split('/').pop()!
avatarThumbnail = new File([await thumbnailData.blob()], thumbnailName)
}

Expand Down Expand Up @@ -165,12 +166,13 @@ export default function AddEditAvatarModal({ avatar }: { avatar?: AvatarType })

useEffect(() => {
if (!avatarAssets.modelURL.value || avatarAssets.source.value !== 'url') return
const modelName = avatarAssets.modelURL.value.split('/').pop()
const modelType = avatarAssets.modelURL.value.split('.').pop()
const modelURL = cleanURL(avatarAssets.modelURL.value)
const modelName = modelURL.split('/').pop()
const modelType = modelURL.split('.').pop()
if (!modelName || !modelType) return
;(previewPanelRef as any).current?.onSelectionChanged({
name: modelName,
resourceUrl: avatarAssets.modelURL.value,
resourceUrl: modelURL,
contentType: `model/${modelType}`
})
}, [avatarAssets.modelURL])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { useTranslation } from 'react-i18next'

import { PopoverState } from '@etherealengine/client-core/src/common/services/PopoverState'
import { StaticResourceType, uploadAssetPath } from '@etherealengine/common/src/schema.type.module'
import { cleanURL } from '@etherealengine/common/src/utils/cleanURL'
import { AssetsPreviewPanel } from '@etherealengine/editor/src/components/assets/AssetsPreviewPanel'
import {
AssetTypeToMimeType,
Expand Down Expand Up @@ -110,12 +111,13 @@ export default function CreateResourceModal({ selectedResource }: { selectedReso
contentType: MimeTypeToAssetType[state.mimeType.value]
})
} else {
getNameAndType(state.resourceURL.value).then(({ name, mimeType, assetType }) => {
const url = cleanURL(state.resourceURL.value)
getNameAndType(url).then(({ name, mimeType, assetType }) => {
state.name.set(name)
state.mimeType.set(mimeType)
;(previewPanelRef as any).current?.onSelectionChanged({
name: name,
resourceUrl: state.resourceURL.value,
resourceUrl: url,
contentType: assetType
})
})
Expand Down Expand Up @@ -145,8 +147,9 @@ export default function CreateResourceModal({ selectedResource }: { selectedReso
})
} else if (state.source.value === 'url' && state.resourceURL.value) {
const response = await fetch(state.resourceURL.value)
const url = cleanURL(state.resourceURL.value)
const blob = await response.blob()
const resourceFile = new File([blob], state.resourceURL.value.split('/').pop()!, {
const resourceFile = new File([blob], url.split('/').pop()!, {
type: state.mimeType.value
})
await uploadToFeathersService(uploadAssetPath, [resourceFile], {
Expand Down
79 changes: 79 additions & 0 deletions packages/client-core/src/hooks/useEngineCanvas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
CPAL-1.0 License

The contents of this file are subject to the Common Public Attribution License
Version 1.0. (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://github.com/EtherealEngine/etherealengine/blob/dev/LICENSE.
The License is based on the Mozilla Public License Version 1.1, but Sections 14
and 15 have been added to cover use of software over a computer network and
provide for limited attribution for the Original Developer. In addition,
Exhibit A has been modified to be consistent with Exhibit B.

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License.

The Original Code is Ethereal Engine.

The Original Developer is the Initial Developer. The Initial Developer of the
Original Code is the Ethereal Engine team.

All portions of the code written by the Ethereal Engine team are Copyright © 2021-2023
Ethereal Engine. All Rights Reserved.
*/

import { getComponent } from '@etherealengine/ecs'
import { getState, useHookstate } from '@etherealengine/hyperflux'
import { EngineState } from '@etherealengine/spatial/src/EngineState'
import { destroySpatialEngine, initializeSpatialEngine } from '@etherealengine/spatial/src/initializeEngine'
import { RendererComponent } from '@etherealengine/spatial/src/renderer/WebGLRendererSystem'
import { useEffect } from 'react'

export const useEngineCanvas = (ref: React.RefObject<HTMLElement>) => {
const lastRef = useHookstate(ref.current)

useEffect(() => {
if (ref.current !== lastRef.value) {
lastRef.set(ref.current)
}
}, [ref.current])

useEffect(() => {
if (!lastRef.value) return

const parent = lastRef.value as HTMLElement

const canvas = document.getElementById('engine-renderer-canvas') as HTMLCanvasElement
const originalParent = canvas.parentElement
initializeSpatialEngine(canvas)
parent.appendChild(canvas)

const observer = new ResizeObserver(() => {
getComponent(getState(EngineState).viewerEntity, RendererComponent).needsResize = true
})

observer.observe(parent)

return () => {
destroySpatialEngine()
observer.disconnect()
parent.removeChild(canvas)
originalParent?.appendChild(canvas)
}
}, [lastRef.value])
}

export const useRemoveEngineCanvas = () => {
useEffect(() => {
const canvas = document.getElementById('engine-renderer-canvas')!
const parent = canvas.parentElement
parent?.removeChild(canvas)

return () => {
parent?.appendChild(canvas)
}
}, [])

return null
}
7 changes: 5 additions & 2 deletions packages/client-core/src/systems/AvatarUISystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { TransformComponent } from '@etherealengine/spatial/src/transform/compon
import { TransformSystem } from '@etherealengine/spatial/src/transform/systems/TransformSystem'
import { XRUIComponent } from '@etherealengine/spatial/src/xrui/components/XRUIComponent'

import { EngineState } from '@etherealengine/spatial/src/EngineState'
import { InputComponent } from '@etherealengine/spatial/src/input/components/InputComponent'
import AvatarContextMenu from '../user/components/UserMenu/menus/AvatarContextMenu'
import { PopupMenuState } from '../user/components/UserMenu/PopupMenuService'
Expand Down Expand Up @@ -159,9 +160,11 @@ const onSecondaryClick = () => {
}

const execute = () => {
const viewerEntity = getState(EngineState).viewerEntity
if (!viewerEntity) return

const ecsState = getState(ECSState)

const viewerEntity = Engine.instance.viewerEntity
const buttons = InputComponent.getMergedButtons(viewerEntity)

// const buttons = InputSourceComponent.getMergedButtons()
Expand Down Expand Up @@ -190,7 +193,7 @@ const execute = () => {
AvatarUI.set(userEntity, ui)
}

const cameraTransform = getComponent(Engine.instance.cameraEntity, TransformComponent)
const cameraTransform = getComponent(viewerEntity, TransformComponent)

const immersiveMedia = getState(MediaSettingsState).immersiveMedia
const mediaNetwork = NetworkState.mediaNetwork
Expand Down
51 changes: 34 additions & 17 deletions packages/client-core/src/systems/LoadingUISystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Ethereal Engine. All Rights Reserved.
import React, { useEffect } from 'react'
import { BackSide, Color, Mesh, MeshBasicMaterial, SphereGeometry, Vector2 } from 'three'

import { Entity } from '@etherealengine/ecs'
import { Entity, UndefinedEntity } from '@etherealengine/ecs'
import {
getComponent,
getMutableComponent,
Expand Down Expand Up @@ -69,9 +69,10 @@ import { XRUIComponent } from '@etherealengine/spatial/src/xrui/components/XRUIC
import { ObjectFitFunctions } from '@etherealengine/spatial/src/xrui/functions/ObjectFitFunctions'
import type { WebLayer3D } from '@etherealengine/xrui'

import { EngineState } from '@etherealengine/spatial/src/EngineState'
import { AdminClientSettingsState } from '../admin/services/Setting/ClientSettingService'
import { AppThemeState, getAppTheme } from '../common/services/AppThemeState'
import { useRemoveEngineCanvas } from '../hooks/useRemoveEngineCanvas'
import { useRemoveEngineCanvas } from '../hooks/useEngineCanvas'
import { LocationState } from '../social/services/LocationService'
import { AuthState } from '../user/services/AuthService'
import { LoadingSystemState } from './state/LoadingState'
Expand All @@ -85,6 +86,20 @@ export const LoadingUISystemState = defineState({
name: 'LoadingUISystemState',
initial: () => {
const transition = createTransitionState(transitionPeriodSeconds, 'IN')
return {
ui: null as null | ReturnType<typeof createLoaderDetailView>,
colors: {
main: '',
background: '',
alternate: ''
},
meshEntity: UndefinedEntity,
transition,
ready: false
}
},

createLoadingUI: () => {
const ui = createLoaderDetailView()
getMutableComponent(ui.entity, InputComponent).grow.set(false)
setComponent(ui.entity, NameComponent, 'Loading XRUI')
Expand Down Expand Up @@ -117,17 +132,10 @@ export const LoadingUISystemState = defineState({

getComponent(meshEntity, TransformComponent).scale.set(-1, 1, -1)

return {
getMutableState(LoadingUISystemState).merge({
ui,
colors: {
main: '',
background: '',
alternate: ''
},
meshEntity,
transition,
ready: false
}
meshEntity
})
}
})

Expand All @@ -140,7 +148,12 @@ const LoadingReactor = (props: { sceneEntity: Entity }) => {
const state = useMutableState(LoadingUISystemState)

useEffect(() => {
state.ui.get(NO_PROXY).state.progress.set(loadingProgress)
if (!state.ui.value) LoadingUISystemState.createLoadingUI()
}, [])

useEffect(() => {
const ui = state.ui.get(NO_PROXY)!
ui.state.progress.set(loadingProgress)
}, [loadingProgress])

/** Scene is loading */
Expand All @@ -160,7 +173,8 @@ const LoadingReactor = (props: { sceneEntity: Entity }) => {
}, [sceneLoaded])

useEffect(() => {
const xrui = getComponent(state.ui.entity.value, XRUIComponent)
const ui = state.ui.get(NO_PROXY)!
const xrui = getComponent(ui.entity!, XRUIComponent)
const progressBar = xrui.getObjectByName('progress-container') as WebLayer3D | undefined
if (!progressBar) return

Expand Down Expand Up @@ -261,7 +275,7 @@ const defaultColor = new Color()

const execute = () => {
const { transition, ui, meshEntity, colors, ready } = getState(LoadingUISystemState)
if (!transition) return
if (!ui) return

const ecsState = getState(ECSState)

Expand Down Expand Up @@ -322,7 +336,7 @@ const execute = () => {
setVisibleComponent(ui.entity, isReady)
}

const reactor = () => {
const Reactor = () => {
const themeState = useMutableState(AppThemeState)
const themeModes = useHookstate(getMutableState(AuthState).user?.userSetting?.ornull?.themeModes)
const clientSettings = useHookstate(
Expand Down Expand Up @@ -353,5 +367,8 @@ export const LoadingUISystem = defineSystem({
uuid: 'ee.client.LoadingUISystem',
insert: { before: TransformSystem },
execute,
reactor
reactor: () => {
if (!useMutableState(EngineState).viewerEntity.value) return null
return <Reactor />
}
})
30 changes: 18 additions & 12 deletions packages/client-core/src/systems/WarningUISystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ import { removeEntity } from '@etherealengine/ecs/src/EntityFunctions'
import { defineSystem } from '@etherealengine/ecs/src/SystemFunctions'
import { PresentationSystemGroup } from '@etherealengine/ecs/src/SystemGroups'
import { defineState, getMutableState, getState, useMutableState } from '@etherealengine/hyperflux'
import { EngineState } from '@etherealengine/spatial/src/EngineState'
import { CameraComponent } from '@etherealengine/spatial/src/camera/components/CameraComponent'
import { createTransitionState } from '@etherealengine/spatial/src/common/functions/createTransitionState'
import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
import { setVisibleComponent, VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
import { createTransitionState } from '@etherealengine/spatial/src/common/functions/createTransitionState'
import { VisibleComponent, setVisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
import { ComputedTransformComponent } from '@etherealengine/spatial/src/transform/components/ComputedTransformComponent'
import { XRUIComponent } from '@etherealengine/spatial/src/xrui/components/XRUIComponent'
import { createXRUI } from '@etherealengine/spatial/src/xrui/functions/createXRUI'
import { ObjectFitFunctions } from '@etherealengine/spatial/src/xrui/functions/ObjectFitFunctions'
import { createXRUI } from '@etherealengine/spatial/src/xrui/functions/createXRUI'
import type { WebLayer3D } from '@etherealengine/xrui'

export const WarningUIState = defineState({
Expand Down Expand Up @@ -151,12 +152,8 @@ export const WarningUISystemState = defineState({
const transitionPeriodSeconds = 0.2
const transition = createTransitionState(transitionPeriodSeconds, 'OUT')

const ui = createXRUI(WarningSystemXRUI)
removeComponent(ui.entity, VisibleComponent)
setComponent(ui.entity, NameComponent, 'Warning XRUI')

return {
ui,
ui: null as null | ReturnType<typeof createXRUI>,
transition
}
}
Expand All @@ -179,8 +176,10 @@ function TransitionReactor() {
let accumulator = 0

const execute = () => {
const state = getState(WarningUIState)
const { transition, ui } = getState(WarningUISystemState)
if (!ui) return

const state = getState(WarningUIState)

const deltaSeconds = getState(ECSState).deltaSeconds

Expand Down Expand Up @@ -226,10 +225,14 @@ const execute = () => {
})
}

const reactor = () => {
const Reactor = () => {
useEffect(() => {
const ui = createXRUI(WarningSystemXRUI)
removeComponent(ui.entity, VisibleComponent)
setComponent(ui.entity, NameComponent, 'Warning XRUI')
getMutableState(WarningUISystemState).ui.set(ui)

return () => {
const ui = getState(WarningUISystemState).ui
removeEntity(ui.entity)
}
}, [])
Expand All @@ -240,5 +243,8 @@ export const WarningUISystem = defineSystem({
uuid: 'ee.client.WarningUISystem',
insert: { after: PresentationSystemGroup },
execute,
reactor
reactor: () => {
if (!useMutableState(EngineState).viewerEntity.value) return null
return <Reactor />
}
})
Loading
Loading