Skip to content

Commit

Permalink
feat: support dropping folders on Gltf UI component (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoecheza authored Apr 19, 2023
1 parent 00dea08 commit 377c8b9
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useCallback, useState } from 'react'
import { useCallback } from 'react'
import { Menu, Item } from 'react-contexify'
import { useDrop } from 'react-dnd'
import { AiFillDelete as DeleteIcon } from 'react-icons/ai'
import cx from 'classnames'

import { AssetNodeItem } from '../../ProjectAssetExplorer/types'
import { memoize } from '../../../lib/logic/once'
import { TreeNode } from '../../ProjectAssetExplorer/ProjectView'

import { withContextMenu } from '../../../hoc/withContextMenu'
import { WithSdkProps, withSdk } from '../../../hoc/withSdk'
Expand All @@ -18,14 +19,30 @@ import { Container } from '../../Container'
import { TextField } from '../TextField'
import { Props } from './types'
import { fromGltf, toGltf, isValidInput } from './utils'
import { isAssetNode } from '../../ProjectAssetExplorer/utils'
import { AssetNodeItem } from '../../ProjectAssetExplorer/types'

const DROP_TYPES = ['project-asset-gltf']

interface IDrop {
value: string;
context: { tree: Map<string, AssetNodeItem> }
context: { tree: Map<string, TreeNode> }
}

const isModel = (node: TreeNode): node is AssetNodeItem => isAssetNode(node) && (node.name.endsWith('.gltf') || node.name.endsWith('.glb'))

const getModel = memoize((node: TreeNode, tree: Map<string, TreeNode>): AssetNodeItem | null => {
if (isModel(node)) return node

const children = node.children || []
for (const child of children) {
const childNode = tree.get(child)!
if (isModel(childNode)) return childNode
}

return null
})

export default withSdk<Props>(
withContextMenu<WithSdkProps & Props>(({ sdk, entity, contextMenuId }) => {
const { files } = useFileSystem()
Expand All @@ -37,16 +54,22 @@ export default withSdk<Props>(
const getInputProps = useComponentInput(entity, GltfContainer, fromGltf, toGltf, handleInputValidation)

const handleRemove = useCallback(() => GltfContainer.deleteFrom(entity), [])
const handleDrop = useCallback((value: AssetNodeItem) => {
GltfContainer.createOrReplace(entity, { src: value.asset.src })
const handleDrop = useCallback((src: string) => {
GltfContainer.createOrReplace(entity, { src })
}, [])

const [{ isHover }, drop] = useDrop(
() => ({
accept: DROP_TYPES,
drop: ({ value, context }: IDrop, monitor) => {
if (monitor.didDrop()) return
handleDrop(context.tree.get(value)!)
const node = context.tree.get(value)!
const model = getModel(node, context.tree)
if (model) handleDrop(model.asset.src)
},
canDrop: ({ value, context }: IDrop) => {
const node = context.tree.get(value)!
return !!getModel(node, context.tree)
},
collect: (monitor) => ({
isHover: monitor.canDrop() && monitor.isOver()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Props = {
const ROOT = 'File System'


type TreeNode = Omit<AssetNode, 'children'> & { children?: string[] }
export type TreeNode = Omit<AssetNode, 'children'> & { children?: string[] }

function ProjectView({ folders }: Props) {
const [open, setOpen] = useState(new Set<string>())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as utils from './utils'

import { AssetNodeFolder, AssetNodeItem } from './types'

describe('ProjectAssetExplorer/utils', () => {
describe('getFullNodePath', () => {
it('should return full node path given a child', () => {
const parentA = { name: 'parentA', parent: null }
const parentB = { name: 'parentB', parent: parentA }
const child = { name: 'file.gltf', parent: parentB } as AssetNodeItem
expect(utils.getFullNodePath(child)).toBe('/parentA/parentB/file.gltf')
})
it('should return child name if node has no parent', () => {
const child = { name: 'file.gltf', parent: null } as AssetNodeItem
expect(utils.getFullNodePath(child)).toBe('/file.gltf')
})
})
describe('isAssetNode', () => {
it('should return true when node type "asset"', () => {
const node: AssetNodeItem = {
name: 'some-name',
parent: null,
type: 'asset',
asset: {
src: 'some-file.glb',
type: 'gltf'
}
}
expect(utils.isAssetNode(node)).toBe(true)
})
it('should return false when node type is different from "asset"', () => {
const node: AssetNodeFolder = {
name: 'some-name',
parent: null,
type: 'folder',
children: []
}
expect(utils.isAssetNode(node)).toBe(false)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AssetNode, AssetNodeFolder } from './types'
import { TreeNode } from './ProjectView'
import { AssetNode, AssetNodeFolder, AssetNodeItem } from './types'

export function AssetNodeRootNull(): AssetNodeFolder {
return { name: '', parent: null, type: 'folder', children: [] }
Expand Down Expand Up @@ -44,12 +45,16 @@ export function buildAssetTree(paths: string[]): AssetNodeFolder {
return root
}

export function getFullNodePath(item: AssetNode) {
export function getFullNodePath(item: AssetNode | TreeNode): string {
let path = ''
let it = item
while (it.parent !== null && item.name !== '') {
path = item.name + '/' + path
let it: AssetNode | TreeNode | null = item
while (it) {
path = '/' + it.name + path
it = it.parent
}
return path
}

export function isAssetNode(node: AssetNode | TreeNode): node is AssetNodeItem {
return node.type === 'asset'
}
6 changes: 3 additions & 3 deletions packages/@dcl/inspector/src/lib/logic/once.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export function memoize<K extends object, V>(cb: (a: K) => V): (a: K) => V {
export function memoize<K extends object, P, V>(cb: (a: K, ...params: P[]) => V): (a: K, ...params: P[]) => V {
const memoized = new WeakMap<K, V>()
return (a: K) => {
return (a: K, ...params: P[]) => {
if (!memoized.has(a)) {
const ret = cb(a)
const ret = cb(a, ...params)
memoized.set(a, ret)
return ret
}
Expand Down

0 comments on commit 377c8b9

Please sign in to comment.