Skip to content

Commit

Permalink
Remove self-contained GLTF/GLB asset (#569)
Browse files Browse the repository at this point in the history
* feat: add assset removal

* feat: add Modal component + use it on ProjectAssetExplorer

* fix: comments
  • Loading branch information
nicoecheza authored May 10, 2023
1 parent f7826d6 commit a1c5020
Show file tree
Hide file tree
Showing 27 changed files with 280 additions and 40 deletions.
51 changes: 51 additions & 0 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: 2 additions & 0 deletions packages/@dcl/inspector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@types/node": "^18.11.18",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@types/react-modal": "^3.16.0",
"@vscode/webview-ui-toolkit": "^1.2.2",
"@well-known-components/pushable-channel": "^1.0.3",
"classnames": "^2.3.2",
Expand All @@ -30,6 +31,7 @@
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
"react-modal": "^3.16.1",
"typescript": "^5.0.2"
},
"files": [
Expand Down
8 changes: 7 additions & 1 deletion packages/@dcl/inspector/src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Toolbar } from '../Toolbar'
import './App.css'
import { Resizable } from '../Resizable'
import ImportAsset from '../ImportAsset'
import { fileSystemEvent } from '../../hooks/catalog/useFileSystem'

enum Tab {
FileSystem = 'FileSystem',
Expand All @@ -33,6 +34,11 @@ const App = () => {
[tab]
)

const handleSave = useCallback(() => {
setTab(Tab.FileSystem)
fileSystemEvent.emit('change')
}, [])

return (
<Resizable type="horizontal" min={300} initial={300}>
<Box>
Expand All @@ -56,7 +62,7 @@ const App = () => {
<div className="footer-content">
{tab === Tab.AssetsPack && catalog && <AssetsCatalog value={catalog} />}
{tab === Tab.FileSystem && <ProjectAssetExplorer onImportAsset={handleTabClick(Tab.Import)} />}
{tab === Tab.Import && <ImportAsset onSave={handleTabClick(Tab.FileSystem)} />}
{tab === Tab.Import && <ImportAsset onSave={handleSave} />}
</div>
)}
<div className="footer-buttons">
Expand Down
6 changes: 6 additions & 0 deletions packages/@dcl/inspector/src/components/Block/Block.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@
flex-direction: row;
flex-grow: 1;
}

.Block.error {
border: 1px var(--primary) dashed;
padding: 0 5px 8px 5px;
border-radius: 2px;
}
5 changes: 3 additions & 2 deletions packages/@dcl/inspector/src/components/Block/Block.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react'
import cx from 'classnames'

import { Props } from './types'

import './Block.css'

const Block = React.forwardRef<null, React.PropsWithChildren<Props>>(({ label, children }, ref) => {
const Block = React.forwardRef<null, React.PropsWithChildren<Props>>(({ label, error, children }, ref) => {
return (
<div ref={ref} className="Block">
<div ref={ref} className={cx("Block", { error })}>
{label && <label>{label}</label>}
<div className="content">{children}</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/@dcl/inspector/src/components/Block/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export type Props = {
label?: string
error?: boolean
}
14 changes: 14 additions & 0 deletions packages/@dcl/inspector/src/components/Button/Button.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,17 @@
width: 24px;
height: 24px;
}

.Button.big {
padding: 16px;
font-size: 16px;
}

.Button.danger {
background-color: var(--primary);
}

.Button.danger:hover,
.Button.danger.active {
background-color: var(--primary-darker)
}
9 changes: 4 additions & 5 deletions packages/@dcl/inspector/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React from 'react'
import classNames from 'classnames'
import cx from 'classnames'

import { PropTypes } from './types'
import './Button.css'

function Button(props: PropTypes) {
function Button({ size, type, ...props }: PropTypes) {
return (
<button {...props} className={classNames('Button', props.className)}>
<button {...props} className={cx('Button', size, type, props.className)}>
{props.children}
</button>
)
}

export default Button
export default Button
7 changes: 6 additions & 1 deletion packages/@dcl/inspector/src/components/Button/types.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
export type PropTypes = React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
type Button = React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>

export type PropTypes = Omit<Button, 'type' | 'size'> & {
type?: 'danger' | 'etc'
size?: 'big' | 'etc'
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@ const DROP_TYPES = ['project-asset-gltf']

export default withSdk<Props>(
withContextMenu<WithSdkProps & Props>(({ sdk, entity, contextMenuId }) => {
const [files] = useFileSystem()
const [files, init] = useFileSystem()
const { handleAction } = useContextMenu()
const { GltfContainer } = sdk.components

const hasGltf = useHasComponent(entity, GltfContainer)
const handleInputValidation = useCallback(({ src }: { src: string }) => isValidInput(files, src), [files])
const getInputProps = useComponentInput(entity, GltfContainer, fromGltf, toGltf, handleInputValidation)
const { getInputProps, isValid } = useComponentInput(entity, GltfContainer, fromGltf, toGltf, handleInputValidation, [files])

const handleRemove = useCallback(() => GltfContainer.deleteFrom(entity), [])
const handleDrop = useCallback((src: string) => {
GltfContainer.createOrReplace(entity, { src })
const handleDrop = useCallback(async (src: string) => {
const { operations } = sdk
operations.updateValue(GltfContainer, entity, { src })
await operations.dispatch()
}, [])

const [{ isHover }, drop] = useDrop(
Expand All @@ -56,15 +58,17 @@ export default withSdk<Props>(

if (!hasGltf) return null

const inputProps = getInputProps('src')

return (
<Container label="Gltf" className={cx('Gltf', { hover: isHover })}>
<Menu id={contextMenuId}>
<Item id="delete" onClick={handleAction(handleRemove)}>
<DeleteIcon /> Delete
</Item>
</Menu>
<Block label="Path" ref={drop}>
<TextField type="text" {...getInputProps('src')} />
<Block label="Path" ref={drop} error={init && !isValid}>
<TextField type="text" {...inputProps} />
</Block>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default withSdk<Props>(({ sdk, entity }) => {
const { Scene } = sdk.components

const hasScene = useHasComponent(entity, Scene)
const getInputProps = useComponentInput(entity, Scene, fromScene, toScene, isValidInput)
const { getInputProps } = useComponentInput(entity, Scene, fromScene, toScene, isValidInput)

if (!hasScene) {
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
.TextField>input {
width: 100%;
color: var(--text);
background-color: var(--transparent-color);
background-color: var(--transparent);
outline: none;
border: none;
}

.TextField:last-child {
margin-right: 0px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default withSdk<Props>(
const { Transform } = sdk.components

const hasTransform = useHasComponent(entity, Transform)
const getInputProps = useComponentInput(entity, Transform, fromTransform, toTransform, isValidNumericInput)
const { getInputProps } = useComponentInput(entity, Transform, fromTransform, toTransform, isValidNumericInput)
const { handleAction } = useContextMenu()

const handleRemove = useCallback(() => Transform.deleteFrom(entity), [])
Expand Down
24 changes: 24 additions & 0 deletions packages/@dcl/inspector/src/components/Modal/Modal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.Modal {
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
border: 1px solid var(--modal-content-border-color);
background: var(--modal-content-bg-color);
overflow: auto;
border-radius: 3px;
outline: none;
padding: 20px;
min-width: 500px;
min-height: 200px;
display: flex;
flex-direction: column;
justify-content: space-between;
}

.ModalOverlay {
position: fixed;
inset: 0px;
background-color: var(--modal-overlay-bg-color);
}
26 changes: 26 additions & 0 deletions packages/@dcl/inspector/src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react'
import _Modal from 'react-modal'

import { Props } from './types'

import './Modal.css'

const Modal = ({
children,
className = '',
overlayClassName = '',
...props
}: Props) => {
return (
<_Modal
ariaHideApp={false}
className={`${className} Modal`}
overlayClassName={`${overlayClassName} ModalOverlay`}
{...props}
>
{children}
</_Modal>
)
}

export default React.memo(Modal)
2 changes: 2 additions & 0 deletions packages/@dcl/inspector/src/components/Modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Modal from './Modal'
export { Modal }
4 changes: 4 additions & 0 deletions packages/@dcl/inspector/src/components/Modal/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from 'react'
import Modal from 'react-modal'

export type Props = React.PropsWithChildren<Modal.Props>
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import React from 'react'
import { Item } from 'react-contexify'
import { AiOutlineFileAdd } from 'react-icons/ai'
import { IoIosImage } from 'react-icons/io'

import { useContextMenu } from '../../hooks/sdk/useContextMenu'
import { ROOT, TreeNode } from './ProjectView'

function ContextMenu({ value, onImportAsset }: { value: TreeNode | undefined; onImportAsset(): void }) {
interface Props {
value: TreeNode | undefined
onImportAsset(): void
}

function ContextMenu({ value, onImportAsset }: Props) {
const { handleAction } = useContextMenu()

if (value?.type === 'asset') return null

return (
<>
<Item hidden={false} id="new-asset-pack" onClick={handleAction(onImportAsset)}>
<Item id="new-asset-pack" onClick={handleAction(onImportAsset)}>
<AiOutlineFileAdd /> Import new asset
</Item>
<Item hidden={true || value?.name === ROOT} id="new-asset-texture" onClick={handleAction(onImportAsset)}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@

.ProjectView .with-context-menu {
height: 100%;
}
}

.RemoveAsset.Modal > div button {
margin-right: 12px;
}
Loading

0 comments on commit a1c5020

Please sign in to comment.