Skip to content

Commit

Permalink
feat: custom assets (#1046)
Browse files Browse the repository at this point in the history
* feat: create custom item

* fix: exclude editor components

* fix: add children to composite

* fix: map resources from within actions

* feat: support mapping resources from deeper properties like the case of material

* feat: replace ids with {self} notation

* fix: make a deep copy of component value

* feat: read custom items from data-layer and render tab

* feat: instance custom assets

* fix: component value key

* fix: map ids with multiple entities

* fix: preserve names

* chore: remove debuggers

* fix: use addChild to set unique name

* fix: styles

* feat: delete custom asset

* fix: allow writing over empty item

* feat: custom component and icon

* fix: enable tween component

* feat: show instance of in entity header

* fix: include resources loaded by GLTF into the custom asset package

* chore: upgrade asset-packs

* chore: rebuild

* chore: fix tests

* chore: roll back change in default formatter

* feat: rename custom asset

* chore: fix test

* fix: smart item basic view re-render

* fix: map cross-entity actions, conditions and triggers

* fix: context menu multiselect

* fix: centroid on custom assets with multiple roots

* fix: use first entity name as custom asset name

* feat: support naming custom asset before creation

* chore: fix test

* fix: icon size

* feat: generate thumbnail

* feat: added spinner while image is being generated

* chore: added tests

* chore: added more tests

* fix: rename custom assets to custom items

* fix: allow smart item basic view on custom items

* fix: pass other resources necessary to render the model to generate the thumbnails

* fix: bind hotkeys to body instead of canvas
  • Loading branch information
cazala authored Jan 7, 2025
1 parent 8eaa4e2 commit 392992d
Show file tree
Hide file tree
Showing 64 changed files with 2,256 additions and 160 deletions.
8 changes: 4 additions & 4 deletions packages/@dcl/inspector/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/@dcl/inspector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@dcl/inspector",
"version": "0.1.0",
"dependencies": {
"@dcl/asset-packs": "^2.1.1",
"@dcl/asset-packs": "^2.1.2",
"ts-deepmerge": "^7.0.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,49 @@ import { useRef } from 'react'
const WIDTH = 300
const HEIGHT = 300

export function AssetPreview({ value, onScreenshot }: Props) {
export function AssetPreview({ value, resources, onScreenshot, onLoad }: Props) {
return (
<div className="AssetPreview">
{isGltf(value.name) ? (
<GltfPreview value={value} onScreenshot={onScreenshot} />
<GltfPreview value={value} resources={resources} onScreenshot={onScreenshot} onLoad={onLoad} />
) : value.name.endsWith('png') ? (
<PngPreview value={value} onScreenshot={onScreenshot} />
<PngPreview value={value} onScreenshot={onScreenshot} onLoad={onLoad} />
) : (
<IoIosImage />
)}
</div>
)
}

function GltfPreview({ value, onScreenshot }: Props) {
const onLoad = React.useCallback(() => {
function GltfPreview({ value, resources, onScreenshot, onLoad }: Props) {
const handleLoad = React.useCallback(() => {
onLoad?.()
const wp = WearablePreview.createController(value.name)
void wp.scene.getScreenshot(WIDTH, HEIGHT).then(($) => onScreenshot($))
}, [])
}, [onLoad])

return (
<WearablePreview
id={value.name}
blob={toWearableWithBlobs(value)}
blob={toWearableWithBlobs(value, resources)}
disableAutoRotate
disableBackground
projection={PreviewProjection.ORTHOGRAPHIC}
camera={PreviewCamera.STATIC}
onLoad={onLoad}
onLoad={handleLoad}
/>
)
}

function PngPreview({ value, onScreenshot }: Props) {
function PngPreview({ value, onScreenshot, onLoad }: Props) {
const canvasRef = useRef<HTMLCanvasElement>(null)

const url = URL.createObjectURL(value)
const img = new Image(WIDTH, HEIGHT)
img.src = url

img.onload = () => {
onLoad?.()
const canvas = canvasRef.current
const ctx = canvasRef.current?.getContext('2d')
const canvas2 = document.createElement('canvas')
Expand Down
4 changes: 3 additions & 1 deletion packages/@dcl/inspector/src/components/AssetPreview/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type Props = {
export interface Props {
value: File
resources?: File[]
onScreenshot: (value: string) => void
onLoad?: () => void
}
8 changes: 6 additions & 2 deletions packages/@dcl/inspector/src/components/AssetPreview/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BodyShape, WearableCategory, WearableWithBlobs } from '@dcl/schemas'

export function toWearableWithBlobs(file: File): WearableWithBlobs {
export function toWearableWithBlobs(file: File, resources: File[] = []): WearableWithBlobs {
return {
id: file.name,
name: '',
Expand All @@ -21,7 +21,11 @@ export function toWearableWithBlobs(file: File): WearableWithBlobs {
{
key: file.name,
blob: file
}
},
...resources.map((resource) => ({
key: resource.name,
blob: resource
}))
],
overrideHides: [],
overrideReplaces: []
Expand Down
9 changes: 9 additions & 0 deletions packages/@dcl/inspector/src/components/Assets/Assets.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@
width: 100%;
}

.Assets .Assets-buttons .icon-custom-assets {
background-image: url('./custom-asset-icon.svg');
background-size: 16px 16px;
background-repeat: no-repeat;
background-position: center;
width: 16px;
height: 12px;
}

.Assets .Assets-buttons > div > div::after {
content: '';
position: absolute;
Expand Down
22 changes: 22 additions & 0 deletions packages/@dcl/inspector/src/components/Assets/Assets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import { HiOutlinePlus } from 'react-icons/hi'
import { AssetPack, catalog, isSmart } from '../../lib/logic/catalog'
import { getConfig } from '../../lib/logic/config'
import { useAppDispatch, useAppSelector } from '../../redux/hooks'
import { selectAssetToRename, selectStagedCustomAsset } from '../../redux/data-layer'
import { getSelectedAssetsTab, selectAssetsTab } from '../../redux/ui'
import { AssetsTab } from '../../redux/ui/types'
import { FolderOpen } from '../Icons/Folder'
import { AssetsCatalog } from '../AssetsCatalog'
import { ProjectAssetExplorer } from '../ProjectAssetExplorer'
import ImportAsset from '../ImportAsset'
import { CustomAssets } from '../CustomAssets'
import { selectCustomAssets } from '../../redux/app'
import { RenameAsset } from '../RenameAsset'
import { CreateCustomAsset } from '../CreateCustomAsset'

import './Assets.css'

Expand All @@ -25,6 +30,7 @@ function removeSmartItems(assetPack: AssetPack) {
function Assets({ isAssetsPanelCollapsed }: { isAssetsPanelCollapsed: boolean }) {
const dispatch = useAppDispatch()
const tab = useAppSelector(getSelectedAssetsTab)
const customAssets = useAppSelector(selectCustomAssets)

const handleTabClick = useCallback(
(tab: AssetsTab) => () => {
Expand All @@ -38,6 +44,9 @@ function Assets({ isAssetsPanelCollapsed }: { isAssetsPanelCollapsed: boolean })
? catalog.map(removeSmartItems).filter((assetPack) => assetPack.assets.length > 0)
: catalog

const assetToRename = useAppSelector(selectAssetToRename)
const stagedCustomAsset = useAppSelector(selectStagedCustomAsset)

return (
<div className="Assets">
<div className="Assets-buttons">
Expand All @@ -47,6 +56,14 @@ function Assets({ isAssetsPanelCollapsed }: { isAssetsPanelCollapsed: boolean })
<span>LOCAL ASSETS</span>
</div>
</div>
{customAssets.length > 0 ? (
<div className="tab" onClick={handleTabClick(AssetsTab.CustomAssets)} data-test-id={AssetsTab.CustomAssets}>
<div className={cx({ underlined: tab === AssetsTab.CustomAssets })}>
<i className="icon-custom-assets" />
<span>CUSTOM ITEMS</span>
</div>
</div>
) : null}
<div className="tab" onClick={handleTabClick(AssetsTab.AssetsPack)} data-test-id={AssetsTab.AssetsPack}>
<div className={cx({ underlined: tab === AssetsTab.AssetsPack })}>
<MdImageSearch />
Expand All @@ -63,6 +80,11 @@ function Assets({ isAssetsPanelCollapsed }: { isAssetsPanelCollapsed: boolean })
{tab === AssetsTab.AssetsPack && <AssetsCatalog catalog={filteredCatalog} />}
{tab === AssetsTab.FileSystem && <ProjectAssetExplorer />}
{tab === AssetsTab.Import && <ImportAsset onSave={handleTabClick(AssetsTab.FileSystem)} />}
{tab === AssetsTab.CustomAssets && <CustomAssets />}
{tab === AssetsTab.RenameAsset && assetToRename && (
<RenameAsset assetId={assetToRename.id} currentName={assetToRename.name} />
)}
{tab === AssetsTab.CreateCustomAsset && stagedCustomAsset && <CreateCustomAsset />}
</div>
</div>
)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
.CreateCustomAsset {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px;
}

.CreateCustomAsset .file-container {
display: flex;
gap: 16px;
padding: 16px;
align-items: flex-start;
}

.CreateCustomAsset .file-container svg {
width: 80px;
height: 80px;
padding: 8px;
border-radius: 8px;
background: var(--list-item-bg-color);
}

.CreateCustomAsset .preview-container {
width: 80px;
height: 80px;
border-radius: 8px;
background: var(--list-item-bg-color);
overflow: hidden;
position: relative;
}

.CreateCustomAsset .preview-container .AssetPreview {
width: 100%;
height: 100%;
}

.CreateCustomAsset .loader-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.5);
z-index: 1;
}

.CreateCustomAsset .column {
width: 300px;
display: flex;
flex-direction: column;
gap: 16px;
}

.CreateCustomAsset .button-container {
display: flex;
gap: 8px;
}

.CreateCustomAsset .create {
background-color: var(--primary);
color: var(--text-on-primary);
}
Loading

0 comments on commit 392992d

Please sign in to comment.