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

Load Percentage Calculation and Dynamic Loading Refactor #7624

Merged
merged 37 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1c963f3
Calculate loaded percentage based on file size
AidanCaruso Feb 22, 2023
b0cbf31
Cleanup
AidanCaruso Feb 22, 2023
b6f7812
Remove log
AidanCaruso Feb 22, 2023
459d18b
Merge branch 'dev' into smoothload
AidanCaruso Feb 23, 2023
9f1f999
Use reactor responding to progress callback
AidanCaruso Feb 23, 2023
b346170
Conditions
AidanCaruso Feb 24, 2023
c971775
hasComponent check
AidanCaruso Feb 24, 2023
1373755
Update component functions
AidanCaruso Feb 24, 2023
3b0ea92
Merge branch 'dev' into byteload
AidanCaruso Feb 24, 2023
9568c89
Update reactor
AidanCaruso Feb 24, 2023
dfdf79b
Check props
AidanCaruso Feb 24, 2023
c978d36
remove console log
AidanCaruso Feb 24, 2023
efd1ab6
Remove component in reactor query
AidanCaruso Feb 24, 2023
060f8f5
Fix progress not being set to 100%
AidanCaruso Feb 24, 2023
81e275b
Remove extraneous logging
AidanCaruso Feb 24, 2023
18c0274
Loading bar refactor
AidanCaruso Feb 27, 2023
cacfb68
Default to theme
AidanCaruso Feb 28, 2023
1be35cc
Loading screen color is set in the loading system
AidanCaruso Feb 28, 2023
f6baf4d
Fix colors
AidanCaruso Feb 28, 2023
92a5990
Dom element scaling
AidanCaruso Feb 28, 2023
adee0f0
Scaling logic
AidanCaruso Feb 28, 2023
44d1351
Progress bar only has dom layout applied once
AidanCaruso Mar 1, 2023
30414f0
Condition change
AidanCaruso Mar 1, 2023
c25321f
Prerasterize when attribute is passed, basic overrides
AidanCaruso Mar 3, 2023
f81e34e
Apply Prerasterized Texture
AidanCaruso Mar 4, 2023
4a5fa53
Force textElement consistency in async prerasterization
AidanCaruso Mar 5, 2023
9c60dea
Pass in prerasterized elements.
AidanCaruso Mar 5, 2023
d6de9b8
Use strings, only update when refreshed
AidanCaruso Mar 7, 2023
9557d6b
hardcoded offset
AidanCaruso Mar 7, 2023
6adba24
Merge branch 'dev' into byteload
speigg Mar 9, 2023
86375dc
Merge branch 'dev' of https://github.com/EtherealEngine/etherealengin…
HexaField Jun 11, 2023
c6fedc8
disable xrui prerasterization changes
HexaField Jun 11, 2023
466388c
loading fixes
HexaField Jun 11, 2023
db11a7b
rewrite dynamic loading
HexaField Jun 12, 2023
09246fd
clean up
HexaField Jun 12, 2023
e4c0e32
update scene names
HexaField Jun 12, 2023
fb6fb31
fix loading offset bug for children
HexaField Jun 12, 2023
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
168 changes: 106 additions & 62 deletions packages/client-core/src/systems/LoadingUISystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import getImagePalette from 'image-palette-core'
import { useEffect } from 'react'
import React from 'react'
import {
Color,
CompressedTexture,
DoubleSide,
Mesh,
Expand Down Expand Up @@ -40,6 +41,7 @@ import { ObjectFitFunctions } from '@etherealengine/engine/src/xrui/functions/Ob
import { defineActionQueue, defineState, getMutableState, getState, useHookstate } from '@etherealengine/hyperflux'
import type { WebLayer3D } from '@etherealengine/xrui'

import { getAppTheme } from '../common/services/AppThemeState'
import { LoadingSystemState } from './state/LoadingState'
import { createLoaderDetailView } from './ui/LoadingDetailView'

Expand All @@ -56,9 +58,8 @@ const LoadingUISystemState = defineState({

const mesh = new Mesh(
new SphereGeometry(10),
new MeshBasicMaterial({ side: DoubleSide, transparent: true, depthWrite: true, depthTest: false })
new MeshBasicMaterial({ side: DoubleSide, transparent: true, depthWrite: true, depthTest: false, color: 'white' })
)
mesh.visible = false

// flip inside out
mesh.scale.set(-1, 1, 1)
Expand All @@ -67,18 +68,42 @@ const LoadingUISystemState = defineState({
setObjectLayers(mesh, ObjectLayers.UI)

return {
metadataLoaded: false,
ui,
mesh,
transition
}
}
})

function SceneDataReactor() {
const sceneData = useHookstate(getMutableState(SceneState).sceneData)
const avatarModelChangedQueue = defineActionQueue(EngineActions.avatarModelChanged.matches)
const spectateUserQueue = defineActionQueue(EngineActions.spectateUser.matches)

function LoadingReactor() {
const loadingState = useHookstate(getMutableState(AppLoadingState))
const engineState = useHookstate(getMutableState(EngineState))
const state = useHookstate(getMutableState(LoadingUISystemState))
const sceneData = useHookstate(getMutableState(SceneState).sceneData)
const mesh = state.mesh.value
const metadataLoaded = state.metadataLoaded

/** Handle loading state changes */
useEffect(() => {
const transition = getState(LoadingUISystemState).transition
console.log('metadataLoaded', metadataLoaded.value)
if (
loadingState.state.value === AppLoadingStates.SCENE_LOADING &&
transition.state === 'OUT' &&
metadataLoaded.value
) {
transition.setState('IN')
}
if (loadingState.state.value === AppLoadingStates.FAIL && transition.state === 'IN') {
transition.setState('OUT')
}
}, [loadingState.state, metadataLoaded])

/** Scene Colors */
function setDefaultPalette() {
const uiState = getState(LoadingUISystemState).ui.state
const colors = uiState.colors
Expand All @@ -96,57 +121,71 @@ function SceneDataReactor() {
colors.main.set(palette.color)
colors.background.set(palette.backgroundColor)
colors.alternate.set(palette.alternativeColor)
console.log('palette', palette)
}
}

/** Scene data changes */
useEffect(() => {
if (!sceneData.value) return
const thumbnailUrl = sceneData.value.thumbnailUrl
const envmapURL = sceneData.value.thumbnailUrl
.replace('thumbnail.jpeg', 'envmap.png')
.replace('thumbnail.ktx2', 'envmap.ktx2')
if (thumbnailUrl && mesh.userData.url !== thumbnailUrl) {
mesh.userData.url = thumbnailUrl
if (envmapURL && mesh.userData.url !== envmapURL) {
mesh.userData.url = envmapURL
setDefaultPalette()
AssetLoader.load(thumbnailUrl, {}, (texture: Texture | CompressedTexture) => {
const compressedTexture = texture as CompressedTexture
if (compressedTexture.isCompressedTexture) {
createReadableTexture(compressedTexture).then((texture: Texture) => {

/** Load envmap and parse colours */
AssetLoader.load(
envmapURL,
{},
(texture: Texture | CompressedTexture) => {
mesh.material.map = texture

const compressedTexture = texture as CompressedTexture
if (compressedTexture.isCompressedTexture) {
try {
createReadableTexture(compressedTexture).then((texture: Texture) => {
setColors(texture)
})
} catch (e) {
console.error(e)
setDefaultPalette()
}
} else {
setColors(texture)
})
if (texture) mesh.material.map = texture
mesh.visible = true
} else {
setColors(texture)
if (texture) mesh.material.map = texture
mesh.visible = true
}
},
undefined,
(error: ErrorEvent) => {
console.error(error)
setDefaultPalette()
}
})
)
}
}, [sceneData])

return null
}

const avatarModelChangedQueue = defineActionQueue(EngineActions.avatarModelChanged.matches)
const spectateUserQueue = defineActionQueue(EngineActions.spectateUser.matches)

function LoadingReactor() {
const loadingState = useHookstate(getMutableState(AppLoadingState))

useEffect(() => {
if (loadingState.state.value === AppLoadingStates.SCENE_LOADING) {
getState(LoadingUISystemState).transition.setState('IN')
}
if (loadingState.state.value === AppLoadingStates.FAIL) {
getState(LoadingUISystemState).transition.setState('OUT')
}
}, [loadingState.state])
const xrui = getComponent(state.ui.entity.value, XRUIComponent)
const progressBar = xrui.getObjectByName('progress-container') as WebLayer3D | undefined
if (!progressBar) return

if (progressBar.position.lengthSq() <= 0) progressBar.shouldApplyDOMLayout = 'once'
const percentage = engineState.loadingProgress.value
const scaleMultiplier = 0.01
const centerOffset = 0.05
progressBar.scale.setX(percentage * scaleMultiplier)
progressBar.position.setX(percentage * scaleMultiplier * centerOffset - centerOffset)
}, [engineState.loadingProgress])

return null
}

const mainThemeColor = new Color()
const defaultColor = new Color()

const execute = () => {
const { transition, ui, mesh } = getState(LoadingUISystemState)
const { transition, ui, mesh, metadataLoaded } = getState(LoadingUISystemState)
if (!transition) return

const appLoadingState = getState(AppLoadingState)
Expand Down Expand Up @@ -198,41 +237,46 @@ const execute = () => {
// // todo: figure out how to make this work properly for VR #7256
// }

const loadingState = getState(LoadingSystemState).loadingScreenOpacity

transition.update(Engine.instance.deltaSeconds, (opacity) => {
if (opacity !== loadingState) getMutableState(LoadingSystemState).loadingScreenOpacity.set(opacity)
mesh.material.opacity = opacity
mesh.visible = opacity > 0 && !!mesh.material.map
xrui.rootLayer.traverseLayersPreOrder((layer: WebLayer3D) => {
const mat = layer.contentMesh.material as MeshBasicMaterial
mat.opacity = opacity
mat.visible = opacity > 0
layer.visible = opacity > 0
})
if (opacity < 0.001) setVisibleComponent(ui.entity, false)
defaultColor.set(getAppTheme()!.textColor)
mainThemeColor.set(ui.state.colors.alternate.value)

transition.update(engineState.deltaSeconds, (opacity) => {
getMutableState(LoadingSystemState).loadingScreenOpacity.set(opacity)
})

const opacity = getState(LoadingSystemState).loadingScreenOpacity
const ready = opacity > 0

mesh.material.opacity = opacity
mesh.visible = ready

xrui.rootLayer.traverseLayersPreOrder((layer: WebLayer3D) => {
const mat = layer.contentMesh.material as MeshBasicMaterial
mat.opacity = opacity
mat.visible = ready
layer.visible = ready
mat.color.lerpColors(defaultColor, mainThemeColor, engineState.loadingProgress * 0.01)
})
setVisibleComponent(ui.entity, ready)
}

const reactor = () => {
useEffect(() => {
return () => {
const { ui, mesh } = getState(LoadingUISystemState)

removeEntity(ui.entity)
mesh.removeFromParent()

getMutableState(LoadingUISystemState).set({
ui: null!,
mesh: null!,
transition: null!
})
}
// return () => {
// const { ui, mesh } = getState(LoadingUISystemState)
// removeEntity(ui.entity)
// mesh.removeFromParent()
// getMutableState(LoadingUISystemState).set({
// metadataLoaded: false,
// ui: null!,
// mesh: null!,
// transition: null!
// })
// }
}, [])

return (
<>
<SceneDataReactor />
<LoadingReactor />
</>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const LoadingDetailView = () => {
const uiState = useXRUIState<LoadingUIState>()
const engineState = useHookstate(getMutableState(EngineState))
const { t } = useTranslation()
const colors = uiState.colors

const sceneLoaded = engineState.sceneLoaded.value
const joinedWorld = engineState.joinedWorld.value
Expand All @@ -52,7 +51,7 @@ const LoadingDetailView = () => {

return (
<>
<LoadingDetailViewStyle colors={colors} />
<LoadingDetailViewStyle />
<div id="loading-container" xr-layer="true">
{/* <div id="thumbnail">
<img xr-layer="true" xr-pixel-ratio="1" src={thumbnailUrl} crossOrigin="anonymous" />
Expand All @@ -61,14 +60,14 @@ const LoadingDetailView = () => {
<div id="loading-text" xr-layer="true" xr-pixel-ratio="3">
{t('common:loader.loading')}
</div>
<div id="progress-text" xr-layer="true" xr-pixel-ratio="3">
{engineState.loadingProgress.value}%
<div id="progress-text" xr-layer="true" xr-pixel-ratio="2" xr-prerasterized="0-9">
{`${engineState.loadingProgress.value}%`}
</div>
<div id="progress-container" xr-layer="true">
<div id="progress-container" xr-layer="true" xr-scalable="true" xr-apply-dom-layout="once">
<ProgressBar
bgColor={colors.alternate.value}
completed={engineState.loadingProgress.value}
height="1px"
bgColor={'#ffffff'}
completed={100}
height="2px"
baseBgColor="#000000"
isLabelVisible={false}
/>
Expand Down
18 changes: 6 additions & 12 deletions packages/client-core/src/systems/ui/LoadingDetailView/style.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import React from 'react'

interface LoadingDetailViewStyleProps {
colors: any
}

const LoadingDetailViewStyle = (props: LoadingDetailViewStyleProps) => {
const { colors } = props

const LoadingDetailViewStyle = () => {
return (
<style>{`
#loading-container {
Expand All @@ -24,7 +18,7 @@ const LoadingDetailViewStyle = (props: LoadingDetailViewStyleProps) => {
left: 50%;
transform: translate(-50%, -50%);
filter: blur(5px);
${colors.background.value ? 'backgroundColor: ' + colors.background.value : ''};
color: #FFFFFF;
}

#loading-ui {
Expand All @@ -35,7 +29,7 @@ const LoadingDetailViewStyle = (props: LoadingDetailViewStyleProps) => {
z-index: 2;
padding: 2px;
text-align: center;
text-shadow: 1px 1px 1px ${colors.background.value};
text-shadow: 1px 1px 1px ${'#000'};
-webkit-font-smoothing: antialiased;
}

Expand All @@ -44,15 +38,15 @@ const LoadingDetailViewStyle = (props: LoadingDetailViewStyleProps) => {
margin: auto;
text-align: center;
padding: 2px;
color: ${colors.alternate.value};
color: #FFFFFF;
}

#progress-text {
font-size: 25px;
margin: auto;
text-align: center;
padding: 2px;
color: ${colors.main.value};
color: #FFFFFF;
}

#progress-container {
Expand All @@ -67,7 +61,7 @@ const LoadingDetailViewStyle = (props: LoadingDetailViewStyleProps) => {
margin: auto;
text-align: center;
padding: 2px;
color: ${colors.main.value};
color: #FFFFFF;
}

`}</style>
Expand Down
10 changes: 1 addition & 9 deletions packages/engine/src/ecs/classes/EngineState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,9 @@ export function EngineEventReceptor(a) {
)
.when(EngineActions.initializeEngine.matches, (action) => s.merge({ isEngineInitialized: action.initialised }))
.when(EngineActions.sceneUnloaded.matches, (action) => s.merge({ sceneLoaded: false }))
.when(EngineActions.sceneLoaded.matches, (action) =>
s.merge({ sceneLoading: false, sceneLoaded: true, loadingProgress: 100 })
)
.when(EngineActions.sceneLoaded.matches, (action) => s.merge({ sceneLoading: false, sceneLoaded: true }))
.when(EngineActions.joinedWorld.matches, (action) => s.merge({ joinedWorld: true }))
.when(EngineActions.leaveWorld.matches, (action) => s.merge({ joinedWorld: false }))
.when(EngineActions.sceneLoadingProgress.matches, (action) => s.merge({ loadingProgress: action.progress }))
.when(EngineActions.connectToWorld.matches, (action) => s.connectedWorld.set(action.connectedWorld))
.when(EngineActions.setTeleporting.matches, (action) => s.merge({ isTeleporting: action.isTeleporting }))
.when(EngineActions.spectateUser.matches, (action) => s.spectating.set(!!action.user))
Expand Down Expand Up @@ -102,11 +99,6 @@ export class EngineActions {
type: 'xre.engine.Engine.SCENE_UNLOADED' as const
})

static sceneLoadingProgress = defineAction({
type: 'xre.engine.Engine.SCENE_LOADING_PROGRESS' as const,
progress: matches.number
})

static browserNotSupported = defineAction({
type: 'xre.engine.Engine.BROWSER_NOT_SUPPORTED' as const,
msg: matches.string
Expand Down
Loading