Skip to content

Commit

Permalink
fix: include resources loaded by GLTF into the custom asset package
Browse files Browse the repository at this point in the history
  • Loading branch information
cazala committed Dec 16, 2024
1 parent e8dad99 commit 448a5d8
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { NullEngine, Scene } from '@babylonjs/core'
import { getDataLayerInterface } from '../../../redux/data-layer'
import { loadAssetContainer, resourcesByPath } from './sdkComponents/gltf-container'
import future from 'fp-future'

// This function takes a path to a gltf or glb file, loads it in Babylon, checks for all the resources loaded by the file, and returns them
export async function getResourcesFromModel(path: string) {
const base = path.split('/').slice(0, -1).join('/')
const src = path + '?base=' + encodeURIComponent(base)
const engine = new NullEngine()
const resources: Set<string> = new Set()
const scene = new Scene(engine)
const extension = path.toLowerCase().endsWith('.gltf') ? '.gltf' : '.glb'
const dataLayer = getDataLayerInterface()
if (!dataLayer) {
return resources
}
const { content } = await dataLayer.getFile({ path })
const file = new File([content], src)

const load = future<void>()

loadAssetContainer(
file,
scene,
() => load.resolve(),
() => {},
(_scene, _error) => load.reject(new Error(_error)),
extension,
path
)

await load

return resourcesByPath.get(path)
}

export async function getResourcesFromModels(paths: string[]): Promise<string[]> {
const results = await Promise.all(paths.map(getResourcesFromModel))
return results.flatMap((resourceSet) => (resourceSet ? Array.from(resourceSet) : []))
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { CAMERA, PLAYER } from '../../../sdk/tree'

let sceneContext: WeakRef<SceneContext>

export const resourcesByPath = new Map<string, Set<string>>()

BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
if (plugin instanceof GLTFFileLoader) {
plugin.animationStartMode = GLTFLoaderAnimationStartMode.NONE
Expand All @@ -30,7 +32,8 @@ BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
// caches all the files by their name (CIDv1)
const loader: GLTFLoader = (plugin as any)._loader
const file: string = (loader as any)._fileName
const [_gltfFilename, strParams] = file.split('?')
const [gltfFilename, strParams] = file.split('?')

if (strParams) {
const params = new URLSearchParams(strParams)
const base = params.get('base') || ''
Expand All @@ -40,8 +43,14 @@ BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
console.log(`Fetching ${filePath}`)
const content = await ctx.getFile(filePath)
if (content) {
// This is a hack to get the resources loaded by the gltf file
if (!resourcesByPath.has(gltfFilename)) {
resourcesByPath.set(gltfFilename, new Set())
}
const resources = resourcesByPath.get(gltfFilename)!
resources.add(filePath)
// TODO: this works with File, but it doesn't match the types (it requires string)
return new File([content], _gltfFilename) as any
return new File([content], gltfFilename) as any
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@ import { ErrorType } from '../index'
import { AssetData } from '../../../lib/logic/catalog'
import { selectAssetsTab } from '../../ui'
import { AssetsTab } from '../../ui/types'
import { getResourcesFromModels } from '../../../lib/babylon/decentraland/get-resources'

export function* createCustomAssetSaga(
action: PayloadAction<{ name: string; composite: AssetData['composite']; resources: string[] }>
) {
const dataLayer: IDataLayer = yield call(getDataLayerInterface)
if (!dataLayer) return
try {
const models = action.payload.resources.filter(
(resource) => resource.endsWith('.gltf') || resource.endsWith('.glb')
)
const resourcesFromModels: string[] = yield call(getResourcesFromModels, models)
const resources = [...action.payload.resources, ...resourcesFromModels]
yield call(dataLayer.createCustomAsset, {
name: action.payload.name,
composite: Buffer.from(JSON.stringify(action.payload.composite)),
resources: action.payload.resources
resources
})
// Fetch asset catalog again
yield put(getAssetCatalog())
Expand Down

0 comments on commit 448a5d8

Please sign in to comment.