Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve: asset import #760

Merged
merged 2 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -6,7 +6,7 @@ import { PropTypes } from './types'
function parseAccept(accept: PropTypes['accept']) {
let value = ''
for (const [key, values] of Object.entries(accept ?? {})) {
value += `${key},${values.join(',')}`
value += `${key},${values.join(',')},`
}
return value
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
overflow: hidden;
white-space: nowrap;
width: inherit;
text-align: center;
}

.ImportAsset .file-container {
Expand Down
68 changes: 55 additions & 13 deletions packages/@dcl/inspector/src/components/ImportAsset/ImportAsset.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useCallback, useState } from 'react'
import { HiOutlineUpload } from 'react-icons/hi'
import { RxCross2 } from 'react-icons/rx'
import { RxCross2, RxReload } from 'react-icons/rx'
import { IoIosImage } from 'react-icons/io'

import FileInput from '../FileInput'
Expand All @@ -18,9 +18,17 @@ import { DIRECTORY, withAssetDir } from '../../lib/data-layer/host/fs-utils'
import { importAsset } from '../../redux/data-layer'
import { useAppDispatch, useAppSelector } from '../../redux/hooks'
import { selectAssetCatalog } from '../../redux/app'
import { getRandomMnemonic } from './utils'

const ONE_MB_IN_BYTES = 1_048_576
const ONE_GB_IN_BYTES = ONE_MB_IN_BYTES * 1024
const ACCEPTED_FILE_TYPES = {
'model/gltf-binary': ['.gltf', '.glb'],
'image/png': ['.png'],
'audio/mpeg': ['.mp3'],
'audio/wav': ['.wav'],
'audio/ogg': ['.ogg']
}

interface PropTypes {
onSave(): void
Expand Down Expand Up @@ -61,6 +69,23 @@ async function validateGltf(data: ArrayBuffer): Promise<ValidationError> {
}
}

async function validateAsset(extension: string, data: ArrayBuffer): Promise<ValidationError> {
switch (extension) {
case 'glb':
case 'gltf':
return validateGltf(data)
// add validators for .png/.ktx2?
case 'png':
case 'ktx2':
case 'mp3':
case '.wav':
case '.ogg':
return null
default:
return `Invalid asset format ".${extension}"`
}
}

const ImportAsset: React.FC<PropTypes> = ({ onSave }) => {
// TODO: multiple files
const dispatch = useAppDispatch()
Expand Down Expand Up @@ -96,9 +121,9 @@ const ImportAsset: React.FC<PropTypes> = ({ onSave }) => {
return
}

const gltfValidationError = await validateGltf(binary)
if (gltfValidationError !== null) {
setValidationError(gltfValidationError)
const validationError = await validateAsset(assetExtension, binary)
if (validationError !== null) {
setValidationError(validationError)
return
}

Expand Down Expand Up @@ -127,22 +152,34 @@ const ImportAsset: React.FC<PropTypes> = ({ onSave }) => {
setAssetName(event.target.value)
}, [])

const invalidName = !!assets.find((asset) => {
const [packageName, otherAssetName] = removeBasePath(basePath, asset.path).split('/')
if (packageName === 'builder') return false
else return otherAssetName?.toLocaleLowerCase() === assetName?.toLocaleLowerCase() + '.' + assetExtension
})
const isValidName = useCallback((name: string, ext: string) => {
return !assets.find((asset) => {
const [packageName, otherAssetName] = removeBasePath(basePath, asset.path).split('/')
if (packageName === 'builder') return false
return otherAssetName?.toLocaleLowerCase() === name?.toLocaleLowerCase() + '.' + ext
})
}, [])

const invalidName = !isValidName(assetName, assetExtension)

const generateAssetName = useCallback(() => {
let name: string = assetName
while (!isValidName(name, assetExtension)) {
name = getRandomMnemonic()
}
setAssetName(name)
}, [assetName])

return (
<div className="ImportAsset">
<FileInput disabled={!!file} onDrop={handleDrop} accept={{ 'model/gltf-binary': ['.gltf', '.glb'] }}>
<FileInput disabled={!!file} onDrop={handleDrop} accept={ACCEPTED_FILE_TYPES}>
{!file && (
<>
<div className="upload-icon">
<HiOutlineUpload />
</div>
<span>
To import an asset drag and drop a single GLB or GLTF file
To import an asset drag and drop a single GLB/GLTF/PNG/MP3 file
<br /> or click to select a file.
</span>
</>
Expand All @@ -156,9 +193,14 @@ const ImportAsset: React.FC<PropTypes> = ({ onSave }) => {
<IoIosImage />
<div className="file-title">{file.name}</div>
</Container>
<div className={classNames({ error: !!invalidName })}>
<div className={classNames({ error: invalidName })}>
<Block label="Asset name">
<TextField label="" value={assetName} onChange={handleNameChange} />
<TextField value={assetName} onChange={handleNameChange} />
{invalidName && (
<div onClick={generateAssetName}>
<RxReload />
</div>
)}
</Block>
<Button disabled={invalidName || !!validationError} onClick={handleSave}>
Import
Expand Down
20 changes: 20 additions & 0 deletions packages/@dcl/inspector/src/components/ImportAsset/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getRandomMnemonic, nouns, adjectives } from './utils'

describe('getRandomMnemonic', () => {
it('should return a string with a random adjective and noun', () => {
const mnemonic = getRandomMnemonic()
const [adjective, noun] = mnemonic.split('-')

expect(adjectives).toContain(adjective)
expect(nouns).toContain(noun)
})

it('should return a valid mnemonic', () => {
const mnemonic = getRandomMnemonic()
const parts = mnemonic.split('-')

expect(parts.length).toBe(2)
expect(adjectives).toContain(parts[0])
expect(nouns).toContain(parts[1])
})
})
91 changes: 91 additions & 0 deletions packages/@dcl/inspector/src/components/ImportAsset/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const sampleIndex = (list: any[]) => Math.floor(Math.random() * list.length)

export function getRandomMnemonic() {
return `${adjectives[sampleIndex(adjectives)]}-${nouns[sampleIndex(nouns)]}`
}

export const nouns = [
'transportation',
'chest',
'variation',
'director',
'tale',
'extent',
'interaction',
'exam',
'combination',
'movie',
'literature',
'significance',
'member',
'priority',
'analyst',
'audience',
'food',
'complaint',
'wedding',
'awareness',
'outcome',
'army',
'resolution',
'ratio',
'baseball',
'family',
'excitement',
'cheek',
'payment',
'freedom',
'sir',
'storage',
'elevator',
'satisfaction',
'organization',
'agency',
'industry',
'arrival',
'thanks',
'hall'
]

export const adjectives = [
'cluttered',
'tricky',
'scandalous',
'rampant',
'well-off',
'abashed',
'fallacious',
'adventurous',
'dizzy',
'huge',
'youthful',
'succinct',
'legal',
'purring',
'wise',
'jagged',
'smart',
'learned',
'relieved',
'plain',
'pushy',
'vast',
'heady',
'vagabond',
'disillusioned',
'obese',
'electric',
'far',
'unaccountable',
'loud',
'early',
'wealthy',
'long',
'thinkable',
'sordid',
'striped',
'violet',
'likeable',
'cheap',
'absorbed'
]
6 changes: 3 additions & 3 deletions packages/@dcl/inspector/src/lib/babylon/setup/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { initKeyboard } from './input'
import { setupEngine } from './setup'
import { InspectorPreferences } from '../../logic/preferences/types'

/*
I refactored the piece that uses canvas and window into this file and ignored it from coverage
because it's not possible to test it without jsdom, and we can't use jsdom because of the ecs
/*
I refactored the piece that uses canvas and window into this file and ignored it from coverage
because it's not possible to test it without jsdom, and we can't use jsdom because of the ecs
*/

export function initRenderer(canvas: HTMLCanvasElement, preferences: InspectorPreferences) {
Expand Down
Loading