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

Commit

Permalink
IR-2225 Asset Loading Tech Debt (#10296)
Browse files Browse the repository at this point in the history
* Move asset type enums to common

* Asset type mapping

* Asset loader cleanup

* Test fix

* Leverage useImmediateEffect better for resource hooks

* debug

* Texture loader

* License

* Texture scaling more generic, last cleanup

* Remove comment

---------

Co-authored-by: Josh Field <[email protected]>
  • Loading branch information
MichaelEstes and HexaField authored Jun 6, 2024
1 parent d0a75d7 commit 7e9bc80
Show file tree
Hide file tree
Showing 30 changed files with 554 additions and 506 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import InputText from '@etherealengine/client-core/src/common/components/InputTe
import Menu from '@etherealengine/client-core/src/common/components/Menu'
import { getCanvasBlob } from '@etherealengine/client-core/src/common/utils'
import config from '@etherealengine/common/src/config'
import { AssetExt } from '@etherealengine/common/src/constants/AssetType'
import { THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH } from '@etherealengine/common/src/constants/AvatarConstants'
import { AssetLoader } from '@etherealengine/engine/src/assets/classes/AssetLoader'
import { AssetType } from '@etherealengine/engine/src/assets/enum/AssetType'
import { isAvaturn } from '@etherealengine/engine/src/avatar/functions/avatarFunctions'
import Box from '@etherealengine/ui/src/primitives/mui/Box'
import Icon from '@etherealengine/ui/src/primitives/mui/Icon'
Expand Down Expand Up @@ -94,7 +94,7 @@ const AvatarCreatorMenu = (selectedSdk: string) => () => {
setAvatarName(avatarIdRegexExec ? avatarIdRegexExec[1] : generateAvatarId())

try {
const assetType = AssetLoader.getAssetType(url) ?? isAvaturn(url) ? AssetType.glB : null
const assetType = AssetLoader.getAssetType(url) ?? isAvaturn(url) ? AssetExt.GLB : null
if (assetType) {
const res = await fetch(url)
const data = await res.blob()
Expand Down
149 changes: 149 additions & 0 deletions packages/common/src/constants/AssetType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
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.
*/

/** List of Asset Types. */
export enum AssetType {
Model = 'Model',
Material = 'Material',
Image = 'Image',
Video = 'Video',
Audio = 'Audio',
Prefab = 'Prefab',
Lookdev = 'Lookdev',
Volumetric = 'Volumetric',
Unknown = 'unknown'
}

/** List of Asset Extensions. */
export enum AssetExt {
GLB = 'glb',
GLTF = 'gltf',
VRM = 'vrm',
FBX = 'fbx',
OBJ = 'obj',
USDZ = 'usdz',
BIN = 'bin',

PNG = 'png',
JPEG = 'jpeg',
TGA = 'tga',
KTX2 = 'ktx2',
DDS = 'dds',

MP4 = 'mp4',
AVI = 'avi',
WEBM = 'webm',
MKV = 'mkv',
MOV = 'mov',
M3U8 = 'm3u8',
MPD = 'mpd',

MP3 = 'mp3',
WAV = 'wav',
OGG = 'ogg',
M4A = 'm4a',
FLAC = 'flac',
AAC = 'acc',

MAT = 'material',

UVOL = 'uvol',
JSON = 'json'
}

export const AssetExtToAssetType = (assetExt: AssetExt | undefined): AssetType => {
switch (assetExt) {
// Model
case AssetExt.GLB:
case AssetExt.GLTF:
case AssetExt.VRM:
case AssetExt.FBX:
case AssetExt.OBJ:
case AssetExt.USDZ:
return AssetType.Model

// Image
case AssetExt.PNG:
case AssetExt.JPEG:
case AssetExt.TGA:
case AssetExt.KTX2:
case AssetExt.DDS:
return AssetType.Image

// Video
case AssetExt.MP4:
case AssetExt.AVI:
case AssetExt.WEBM:
case AssetExt.MKV:
case AssetExt.MOV:
case AssetExt.M3U8:
case AssetExt.MPD:
return AssetType.Video

// Audio
case AssetExt.MP3:
case AssetExt.WAV:
case AssetExt.OGG:
case AssetExt.M4A:
case AssetExt.FLAC:
case AssetExt.AAC:
return AssetType.Audio

// Material
case AssetExt.MAT:
return AssetType.Material

// Volumetric
case AssetExt.JSON:
case AssetExt.UVOL:
return AssetType.Volumetric

default:
return AssetType.Unknown
}
}

export const FileExtToAssetExt = (fileExt: string): AssetExt | undefined => {
fileExt = fileExt.toLowerCase()
if (fileExt === 'jpg') return AssetExt.JPEG
return <AssetExt>fileExt
}

export const FileToAssetType = (fileName: string): AssetType => {
fileName = fileName.toLowerCase()
const split = fileName.split('.')
const ext = split.pop()
if (!ext) return AssetType.Unknown
if (ext === 'gltf') {
const prev = split.pop()
if (prev) {
if (prev === 'material') return AssetType.Material
else if (prev === 'lookdev') return AssetType.Lookdev
else if (prev === 'prefab') return AssetType.Prefab
}
}

return AssetExtToAssetType(FileExtToAssetExt(ext))
}
22 changes: 12 additions & 10 deletions packages/editor/src/components/assets/AssetsPreviewPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ Ethereal Engine. All Rights Reserved.
*/
import React, { useImperativeHandle } from 'react'

import { AssetLoader } from '@etherealengine/engine/src/assets/classes/AssetLoader'
import { AssetType } from '@etherealengine/engine/src/assets/enum/AssetType'
import { AssetExt } from '@etherealengine/common/src/constants/AssetType'
import { NO_PROXY, useHookstate } from '@etherealengine/hyperflux'
import createReadableTexture from '@etherealengine/spatial/src/renderer/functions/createReadableTexture'

import { getTextureAsync } from '@etherealengine/engine/src/assets/functions/resourceLoaderHooks'
import { AudioPreviewPanel } from './AssetPreviewPanels/AudioPreviewPanel'
import { ImagePreviewPanel } from './AssetPreviewPanels/ImagePreviewPanel'
import { JsonPreviewPanel } from './AssetPreviewPanels/JsonPreviewPanel'
Expand Down Expand Up @@ -75,9 +75,11 @@ export const AssetsPreviewPanel = React.forwardRef(({ hideHeading, previewPanelP
const onSelectionChanged = async (props: AssetSelectionChangePropsType) => {
thumbnail.value && URL.revokeObjectURL(thumbnail.value)
if (/ktx2$/.test(props.resourceUrl)) {
const texture = await AssetLoader.loadAsync(props.resourceUrl)
thumbnail.set((await createReadableTexture(texture, { url: true })) as string)
texture.dispose()
const [texture, unload] = await getTextureAsync(props.resourceUrl)
if (texture) {
thumbnail.set((await createReadableTexture(texture, { url: true })) as string)
unload()
}
} else {
thumbnail.set('')
}
Expand All @@ -90,13 +92,13 @@ export const AssetsPreviewPanel = React.forwardRef(({ hideHeading, previewPanelP
case 'model/gltf':
case 'model/gltf-binary':
case 'model/glb':
case AssetType.VRM:
case AssetExt.VRM:
case 'model/vrm':
case AssetType.glB:
case AssetType.glTF:
case AssetExt.GLB:
case AssetExt.GLTF:
case 'gltf-binary':
case AssetType.USDZ:
case AssetType.FBX:
case AssetExt.USDZ:
case AssetExt.FBX:
const modelPreviewPanel = {
PreviewSource: ModelPreviewPanel,
resourceProps: { resourceUrl: props.resourceUrl, name: props.name, size: props.size }
Expand Down
8 changes: 4 additions & 4 deletions packages/editor/src/components/inputs/TexturePreviewInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import { Stack } from '@mui/material'
import React, { Fragment, useEffect } from 'react'
import { ColorSpace, DisplayP3ColorSpace, LinearSRGBColorSpace, SRGBColorSpace, Texture, Vector2 } from 'three'

import { AssetType } from '@etherealengine/common/src/constants/AssetType'
import { AssetLoader } from '@etherealengine/engine/src/assets/classes/AssetLoader'
import { ImageFileTypes, VideoFileTypes } from '@etherealengine/engine/src/assets/constants/fileTypes'
import { AssetClass } from '@etherealengine/engine/src/assets/enum/AssetClass'
import { useHookstate } from '@etherealengine/hyperflux'
import Button from '@etherealengine/ui/src/primitives/mui/Button'

Expand Down Expand Up @@ -75,7 +75,7 @@ export default function TexturePreviewInput({
}
const { preview } = rest
const validSrcValue =
typeof value === 'string' && [AssetClass.Image, AssetClass.Video].includes(AssetLoader.getAssetClass(value))
typeof value === 'string' && [AssetType.Image, AssetType.Video].includes(AssetLoader.getAssetClass(value))

const srcState = useHookstate(value)
const texture = srcState.value as Texture
Expand Down Expand Up @@ -109,10 +109,10 @@ export default function TexturePreviewInput({
{showPreview && (
<Fragment>
{(typeof preview === 'string' ||
(typeof value === 'string' && AssetLoader.getAssetClass(value) === AssetClass.Image)) && (
(typeof value === 'string' && AssetLoader.getAssetClass(value) === AssetType.Image)) && (
<img src={previewSrc} style={previewStyle} alt="" crossOrigin="anonymous" />
)}
{typeof value === 'string' && AssetLoader.getAssetClass(value) === AssetClass.Video && (
{typeof value === 'string' && AssetLoader.getAssetClass(value) === AssetType.Video && (
<video src={previewSrc} style={previewStyle} />
)}
</Fragment>
Expand Down
4 changes: 2 additions & 2 deletions packages/editor/src/components/properties/ModelNodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import config from '@etherealengine/common/src/config'
import { pathJoin } from '@etherealengine/common/src/utils/miscUtils'
import { useComponent } from '@etherealengine/ecs/src/ComponentFunctions'
import { pathResolver } from '@etherealengine/engine/src/assets/functions/pathResolver'
import { updateResource } from '@etherealengine/engine/src/assets/functions/resourceLoaderFunctions'
import { updateModelResource } from '@etherealengine/engine/src/assets/functions/resourceLoaderFunctions'
import { recursiveHipsLookup } from '@etherealengine/engine/src/avatar/AvatarBoneMatching'
import { getEntityErrors } from '@etherealengine/engine/src/scene/components/ErrorComponent'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
Expand Down Expand Up @@ -131,7 +131,7 @@ export const ModelNodeEditor: EditorComponentType = (props) => {
value={modelComponent.src.value}
onRelease={(src) => {
if (src !== modelComponent.src.value) commitProperty(ModelComponent, 'src')(src)
else updateResource(src)
else updateModelResource(src)
}}
/>
{errors?.LOADING_ERROR ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import DeblurIcon from '@mui/icons-material/Deblur'
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'

import { AssetExt } from '@etherealengine/common/src/constants/AssetType'
import { getOptionalMutableComponent, useComponent } from '@etherealengine/ecs/src/ComponentFunctions'
import { Entity, UndefinedEntity } from '@etherealengine/ecs/src/Entity'
import { AssetLoader } from '@etherealengine/engine/src/assets/classes/AssetLoader'
import { AssetType } from '@etherealengine/engine/src/assets/enum/AssetType'
import { loadResource } from '@etherealengine/engine/src/assets/functions/resourceLoaderFunctions'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
import { Heuristic, VariantComponent, VariantLevel } from '@etherealengine/engine/src/scene/components/VariantComponent'
Expand Down Expand Up @@ -268,7 +268,7 @@ export const BudgetVariantNodeEditor = (props: {
lastSrc.set(src)

const assetType = AssetLoader.getAssetType(src)
if (assetType !== AssetType.glB && assetType !== AssetType.glTF) return
if (assetType !== AssetExt.GLB && assetType !== AssetExt.GLTF) return

const controller = new AbortController()
buildBudgetVariantMetadata(level.value, controller.signal, (maxTextureSize: number, vertexCount: number) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ Ethereal Engine. All Rights Reserved.
import React, { useCallback } from 'react'
import { Texture, Vector2, Vector3 } from 'three'

import { AssetLoader } from '@etherealengine/engine/src/assets/classes/AssetLoader'
import {
ApplyForceBehaviorJSON,
ApplySequencesJSON,
Expand All @@ -52,6 +51,7 @@ import {
import { State } from '@etherealengine/hyperflux'
import createReadableTexture from '@etherealengine/spatial/src/renderer/functions/createReadableTexture'

import { getTextureAsync } from '@etherealengine/engine/src/assets/functions/resourceLoaderHooks'
import BooleanInput from '../../inputs/BooleanInput'
import { Button } from '../../inputs/Button'
import InputGroup from '../../inputs/InputGroup'
Expand Down Expand Up @@ -344,7 +344,8 @@ export default function BehaviorInput({
(scope: State<TextureSequencerJSON>) => {
const thisOnChange = onChange(scope.src)
return (src: string) => {
AssetLoader.load(src, (texture: Texture) => {
getTextureAsync(src).then(([texture]) => {
if (!texture) return
createReadableTexture(texture, { canvas: true, flipY: true }).then((readableTexture: Texture) => {
const canvas = readableTexture.image as HTMLCanvasElement
const ctx = canvas.getContext('2d')!
Expand Down
23 changes: 11 additions & 12 deletions packages/editor/src/constants/AssetTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20
Ethereal Engine. All Rights Reserved.
*/

import { AssetExt } from '@etherealengine/common/src/constants/AssetType'
import { NativeTypes } from 'react-dnd-html5-backend'

import { AssetType } from '@etherealengine/engine/src/assets/enum/AssetType'

/**
* ItemTypes object containing types of items used.
*
Expand All @@ -35,24 +34,24 @@ import { AssetType } from '@etherealengine/engine/src/assets/enum/AssetType'
export const ItemTypes = {
File: NativeTypes.FILE,
Folder: 'folder',
Audios: [AssetType.MP3, 'mpeg', 'audio/mpeg'],
Images: [AssetType.PNG, AssetType.JPEG, 'jpg', 'gif', AssetType.KTX2, 'image/png', 'image/jpeg', 'image/ktx2'],
Audios: [AssetExt.MP3, 'mpeg', 'audio/mpeg'],
Images: [AssetExt.PNG, AssetExt.JPEG, 'jpg', 'gif', AssetExt.KTX2, 'image/png', 'image/jpeg', 'image/ktx2'],
Models: [
AssetType.glB,
AssetExt.GLB,
'model/glb',
AssetType.glTF,
AssetExt.GLTF,
'model/gltf',
AssetType.FBX,
AssetExt.FBX,
'model/fbx',
AssetType.USDZ,
AssetExt.USDZ,
'model/usdz',
AssetType.VRM,
AssetExt.VRM,
'model/vrm'
],
Scripts: ['tsx', AssetType.TS, 'jsx', 'js', AssetType.Script],
Videos: [AssetType.MP4, AssetType.M3U8, 'video/mp4', AssetType.MKV],
Scripts: ['tsx', 'ts', 'jsx', 'js', 'script'],
Videos: [AssetExt.MP4, AssetExt.M3U8, 'video/mp4', AssetExt.MKV],
Volumetrics: ['manifest'],
Text: [AssetType.PlainText, 'txt'],
Text: ['text', 'txt'],
ECS: ['scene.json'],
Node: 'Node',
Material: 'Material',
Expand Down
Loading

0 comments on commit 7e9bc80

Please sign in to comment.